魔法方法

魔法方法 #

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))
沪ICP备17055033号-2