|
发表于 2023-8-17 16:01:15
|
显示全部楼层
## \_\_getitem__(self, index)
当对象被索引的时候, python会调用`__getitem__`,它既能响应单个下标的索引操作,又能支持代表范围的切片索引的方式
```python
class C:
def __getitem__(self, index):
print(index)
c = C()
c[2]
2
c[2:8]
slice(2, 8, None)
```
slice()是一个BIF函数,切片操作是他的语法糖
```python
s = "I love you"
s[2:6]
'love'
s[slice(2, 6)]
'love'
s[7:]
'you'
s[slice(7, None)]
'you'
s[::4]
'Ivo'
s[slice(None, None, 4)]
'Ivo'
```
## \_\_setitem__(self, key, value)
为索引或切片赋值操作的时候就会被setitem方法拦截
```python
class D:
def __init__(self, data):
self.data = data
def __getitem__(self, index):
return self.data[index]
def __setitem__(self, index, value):
self.data[index] = value
d = D([1, 2, 3, 4, 5])
d[1]
2
d[1] = 1
d[1]
1
d[2:4] = [2, 3]
d[:]
[1, 1, 2, 3, 5]
```
如果迭代器是基于索引的(例如,使用一个索引来迭代列表元素),那么会触发该对象的 `__getitem__` 方法
```python
class D:
def __init__(self, data):
self.data = data
def __getitem__(self, index):
return self.data[index] * 2
def __setitem__(self, index, value):
self.data[index] = value
d = D([1, 2, 3, 4, 5])
for i in d:
print(i, end=' ')
2 4 6 8 10
```
## \_\_iter__(self)和\_\_next__(self)
用for语句去访问`__getitem()__`是python退而求其次的方法
如果一个对象定义了`__iter__()`魔法方法那么他就是一个可迭代对象,定义了`__next__()`则是一个迭代器
比如说,列表是一个可迭代对象,他不是一个迭代器,他没有next方法
```python
x = [1, 1, 2, 3, 5]
dir(x)
['__add__', '__class__', '__class_getitem__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
next(x)
Traceback (most recent call last):
File "<pyshell#111>", line 1, in <module>
next(x)
TypeError: 'list' object is not an iterator
```
可迭代对象定义了`__iter()__`魔法方法,调用就会得到一个相应的迭代器对象
使用for对一个可迭代对象操作时,先将对象传入内置函数iter()中并拿到一个相应的迭代器,才能拥有`__next__()`方法,再利用`__next__()`方法进行迭代操作,当抛出StopIteration时到达尽头
```python
_ = iter(x)
while True:
try:
i = _.__next__()
except StopIteration:
break
print(i, end = ' ')
1 1 2 3 5
```
创造一个迭代器对象
```python
class Double:
def __init__(self, start, stop):
self.value = start - 1
self.stop = stop
def __iter__(self):
return self
def __next__(self):
if self.value == self.stop:
raise StopIteration
self.value += 1
return self.value * 2
d = Double(1, 5)
for i in d:
print(i, end = ' ')
2 4 6 8 10
```
|
|