python魔方方法__getitem__、setitem__和__len
一、简介
当我们重载了类的__getitem__
和__setitem__
方法后,我们便可以对该类的实例,通过[]
索引运算符来进行取值和赋值。具体而言__getitem__
对于的是取值运算,而__setitem__
对应的是赋值运算。
注意:重载上述的magic method仅仅支持修改值和查看值,并不支持切片运算
注意:要想支持切片方法,还需要重载__len__
方法
二、详解
__setitem__语法:object.__getitem__(self, key)
参数:
- self指代自身类的实例
- key指代sequence对象的索引,如果对象缺少为sequence,那么key要为整数
__getitem__语法:object.__setitem__(self, key, value)
参数:
- self指代自身类的实例
- key指代index
- value指代需要传入的新值
__len__语法:object.__len__(self)
参数:
- self指代自身类的实例
返回值:
- 需要返回长度的整数值
三、代码
举一个简单的例子,简单自定义一个用户列表类,为了使用索引运算符,我们重载了该类的__getitem__和__setitem__方法
class CustomList(object):
def __init__(self, *args):
self.slots = list(args)
def __getitem__(self, key):
return self.slots[key]
def __setitem__(self, key, data):
self.slots[key] = data
def __len__(self):
return len(self.slots)
def __repr__(self): # 用于终端显示,与本博文关系不大
return str(self.slots)
a = CustomList(1,2,3,4)
print(a)
print(a[0]) # 查看a[0]的值
a[0] = 'something' # 修改a[0]的值
print(a)
print(a[0:2]) # 定义__len__方法后支持切片访问
a[0:2] = 9,10 # 支持切片赋值
print(a)
[1, 2, 3, 4]
1
['something', 2, 3, 4]
['something', 2]
[9, 10, 3, 4]
举一个自定义HashTable实现映射的例子,slots用于存储hash值,data用于存储具体数据。
# 利用hash表完成map映射
class HashTAble(object):
def __init__(self, size=11):
self.size = size
self.slots = [None] * self.size
self.data = [None] * self.size
def hashfunc(self, key):
return key % self.size
def rehash(self, oldhashvalue):
return (oldhashvalue + 1) % self.size
def put(self, key, data):
hashvalue = self.hashfunc(key)
if self.slots[hashvalue] == None:
self.slots[hashvalue] = key
self.data[hashvalue] = data
else:
if self.slots[hashvalue] == key: # 替换
self.data[hashvalue] = data
nextslot = self.rehash(hashvalue) # 处理hash值的计算冲突
while self.slots[nextslot] != None and \
self.slots[nextslot] != key:
nextslot = self.rehash(nextslot)
if self.slots[nextslot] == None:
self.slots[nextslot] = key
self.data[nextslot] = data
else:
self.data[nextslot] = data # 替换
def get(self, key):
stop = False
found = False
startslot = self.hashfunc(key)
pos = startslot
while self.slots[pos] != None and \
not found and not stop:
if self.slots[pos] == key:
found = True
return self.slots[pos]
else:
pos = self.rehash(pos)
if pos == startslot:
stop = True
def __getitem__(self, key):
return self.get(key)
def __setitem__(self, key, data):
self.put(key, data)
H = HashTAble()
H[20] = 'cat'
print(H.slots)
print(H.data)
print(H.get(20))
print(H[20])
[None, None, None, None, None, None, None, None, None, 20, None]
[None, None, None, None, None, None, None, None, None, 'cat', None]
20
20
四、Reference
《Python数据结构与算法分析_2nd》
https://docs.python.org/zh-cn/3.9/reference/datamodel.html?highlight=object%20__getitem__#object.getitem