魔法方法 #
Python 中以 __
开头的方法都被称作魔法方法。
对象间的计算 #
__add__
, __sub__
, __iadd__
等魔法方法用于进行对象间的计算,以上三个分别在 +
, -
, +=
时会被调用。
例
定义魔法方法
class RichInt(int):
def __add__(self, other):
print('add', self, other)
return int.__add__(self, other)
def __sub__(self, other):
print('sub', self, other)
return int(self) - int(other)
def __iadd__(self, other):
print('iadd', self, other)
self = self.__add__(other)
return self
使用魔法方法
a = RichInt(2)
b = RichInt(3)
print(a + b)
print(a - b)
a += 10
print(a)
以下例子中如果 a 没有实现 add 方法的话,python 就会调用 b 的 add 方法,所以在减法等有顺序的计算时需要特别注意安排顺序
print(1 + a)
print(a + 1)
自定义容器 #
自定义容器需要实现 __len__
和 __getitem__
两个魔法方法。
class Array:
def __init__(self, *args):
self.values = [x for x in args]
self.access_count = {}.fromkeys(range(len(self.values)), 0)
def __len__(self):
return len(self.values)
def __getitem__(self, item):
self.access_count[item] += 1
return self.values[item]
array = Array(1, 2, 3, 4, 5)
print(array[3])
print(array[3])
print(array[2])
print(array.access_count)
属性访问 #
# Field Accessor
class Foo:
def __init__(self):
self.x = 10
# When field not exist
def __getattr__(self, item):
print('getattr', item)
# When field is accessed
def __getattribute__(self, item):
print('getattribute', item)
return super().__getattribute__(item)
def __setattr__(self, key, value):
print('set', key, value)
super().__setattr__(key, value)
def __delattr__(self, item):
print('del', item)
super().__delattr__(item)
foo = Foo() # set x
print(foo.x) # getattribute x
print(getattr(foo, 'x', 'null')) # getattribute x
print(getattr(foo, 'y', 'null')) # getattribute y,getattr y
del foo.x # del x
描述符 #
描述符就是将某种类型的类实例指派给另一个类的属性。
使用描述符需要实现描述符属性的三个方法 __get()
, __set()
, __delete()
。
class Descriptor:
def __get__(self, instance, owner):
print('get', instance, owner)
def __set__(self, instance, value):
print('set', instance, value)
def __delete__(self, instance):
print('delete', instance)
class Test:
foo = Descriptor()
test = Test()
print(test.foo) # get, None
test.foo = 'foo' # set
print(test.foo) # get, None
迭代器 #
使用迭代器
str = 'foo'
it = iter(str)
print(next(it))
print(next(it))
print(next(it))
# print(next(it)) StopIteration
自定义迭代器
自定义迭代器只需要实现 __init__
, __iter__
, __next__
三个方法。
class Fibs:
def __init__(self, n=10):
self.a = 0
self.b = 1
self.n = n
def __iter__(self):
return self
def __next__(self):
self.a, self.b = self.b, self.a + self.b
if self.a > self.n:
raise StopIteration
return self.a
f = Fibs(20)
for e in f:
print('fib', e)
print()
it = iter(Fibs(20))
print(next(it))