在Python中,被双下滑线包围起来的方法(定义在类中)叫魔术方法(Magic Method),比如我们最常见的init()就是一个典型的魔术方法。
一、构造和初始化
new和init相配合才是python中的类构造器。
1 2 3 4 5 6 7 8 9 10 11 12
| class A: pass class B(A): def __new__(cls): print("__new__方法被执行") return super().__new__(cls)
def __init__(self): print("__init__方法被执行")
b = B()
|
二、类的描述
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class A: '''我是一个测试类''' def __init__(self, item): self.item = item def __repr__(self): return "something:"+str(self.item)
a = A(100)
print('这是哪个类:') print(a.__class__) print('这个类是做什么的:') print(a.__doc__) print('打印这个类:') print(a)
|
三、类的属性访问控制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| class A: def __init__(self, age): self.age = age
def __getattribute__(self, key): return super().__getattribute__(key)
def __getattr__(self, key): return '属性不存在!'
def __setattr__(self, key, value): self.__dict__[key] = value
def __delattr__(self, key): print("对象被销毁.")
a = A(15)
print('查询属性值:') print(a.age) print(a.name) print('属性赋值:') a.age = 16 print(a.age) print('属性删除:') a.qq = "123" del a.qq
|
四、描述器类的魔术方法
描述器是通过获取、设置以及删除的时候被访问的类。从描述器的创建来说,一个类中定义了get、set、delete中的一个或几个,这个类的实例就可以叫做一个描述器。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
class M: def __init__(self, x=1): self.x = x def __get__(self, instance, owner): return self.x def __set__(self, instance, value): self.x = value
class A: m = M() a = A() print(a.m) a.m = 2 print(a.m)
|
下面再看一个单位转换的描述器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| class Meter(object): def __init__(self, value=0.0): self.value = float(value)
def __get__(self, instance, owner): return self.value
def __set__(self, instance, value): self.value = float(value)
class Foot(object): def __get__(self, instance, owner): return instance.meter * 3.2808
def __set__(self, instance, value): instance.meter = float(value) / 3.2808
class Distance(object): meter = Meter() foot = Foot()
d = Distance() d.foot = 30 print(d.foot) print(d.meter) d.meter = 10 print(d.meter) print(d.foot)
|
更多
五、容器类的魔术方法
我们常用的list、dict、tuple、string等等就是容器类。python的容器类型分为可变类型(如list、dict)和不可变类型(如string、tuple),可变容器和不可变容器的区别在于,不可变容器一旦赋值后,不可对其中的某个元素进行修改。
注意事项
- 要实现不可变容器的话,你只能定义 len 和 getitem。
- 可变容器协议需要所有不可变容器的所有,另外还需要 setitem和 delitem。
- 如果你希望你的对象是可迭代的话,你需要定义 iter 返回一个迭代器。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| class FunctionalList: '''实现了内置类型list的功能,并丰富了一些其他方法''' def __init__(self, values=None): if values is None: self.values = [] else: self.values = values
def __len__(self): return len(self.values)
def __getitem__(self, key): return self.values[key]
def __setitem__(self, key, value): self.values[key] = value
def __delitem__(self, key): del self.values[key]
def __iter__(self): return iter(self.values)
def __reversed__(self): return FunctionalList(reversed(self.values))
def append(self, value): self.values.append(value)
def head(self): return self.values[0]
def last(self): return self.values[-1]
def drop(self, n): return self.values[n:]
def take(self, n): return self.values[:n]
l = FunctionalList([1,2,3,4,5,6]) print(l.take(5)) print(list(l.__iter__())) print(list(l.__reversed__())) l.__delitem__(3) print(list(l.__iter__())) l[3] = 9 print(list(l.__iter__()))
|