特殊方法
# 特殊方法总览
# 跟运算符无关的特殊方法
# 字符串/字节序列表示形式
# __repr__、 __str__、 __format__、 __bytes__
# 数值转换
# __abs__、 __bool__、 __complex__、 __int__、 __float__、 __hash__、 __index__
# 集合模拟
# __len__、 __getitem__、 __setitem__、 __delitem__、 __contains__
# 迭代枚举
# __iter__、 __reversed__、 __next__
# 可调用模拟
# __call__
# 上下文管理
# __enter__、 __exit__
# 实例创建和销毁
# __new__、 __init__、 __del__
# 属性管理
# __getattr__、 __getattribute__、 __setattr__、 __delattr__、 __dir__
# 属性描述符
# __get__、 __set__、 __delete__
# 跟类相关的服务
# __prepare__、 __instancecheck__、 __subclasscheck__
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 跟运算符相关的特殊方法
# 一元运算符
# __neg__ -、 __pos__ +、 __abs__ abs()
# 众多比较运算符
# __lt__ <、 __le__ <=、 __eq__ ==、 __ne__ !=、 __gt__ >、 __ge__ >=
# 算术运算符
# __add__ +、 __sub__ -、 __mul__ *、 __truediv__ /、 __floordiv__ //、 __mod__ %、 __divmod__ divmod()、
# __pow__ ** 或pow()、 __round__ round()
# 反向算术运算符
# __radd__、 __rsub__、 __rmul__、 __rtruediv__、 __rfloordiv__、 __rmod__、 __rdivmod__、__rpow__
# 增量复制算术运算符
# __iadd__、 __isub__、 __imul__、 __itruediv__、 __ifloordiv__、 __imod__、 __ipow__
# 位运算符
# __invert__ ~、 __lshift__ <<、 __rshift__ >>、 __and__ &、 __or__ |、 __xor__ ^
# 反向位运算符
# __rlshift__、 __rrshift__、 __rand__、 __rxor__、 __ror__
# 增量赋值运算符
# __ilshift__、 __irshift__、 __iand__、 __ixor__、 __ior__
# 当交换两个操作数的位置时, 就会调用反向运算符(b * a
# 而不是 a * b) 。 增量赋值运算符则是一种把中缀运算符变成赋值
# 运算的捷径(a = a * b 就变成了 a *= b) 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# __call__
# 模拟可调用对象
class A:
def __call__(self, *args, **kwargs):
# 此方法会在实例作为一个函数被“调用”时被调用。
print('this is class')
a = A()
a() # 类实例,作为函数调用
class B:
def main(self):
print('this is 主业务!')
def __call__(self, *args, **kwargs):
return self.main()
b = B()
b()
# 类装饰器
# 单例
class Single:
def __init__(self, cls):
self._cls = cls
self._instance = {}
def __call__(self, *args, **kwargs):
if self._cls not in self._instance:
self._instance[self._cls] = self._cls(*args, **kwargs)
return self._instance[self._cls]
@Single
class D:
def __init__(self, name):
self.name = name
def run(self):
print('this is [{}] run!'.format(self.name))
d = D('tom')
d.run()
d1 = D('jack')
d1.run()
print(id(d) == id(d1))
# 检查
class Check:
def __init__(self, c):
self._c = c
def __call__(self, *args, **kwargs):
print('做检查')
return self._c(*args, **kwargs)
@Check
def demo():
print('hello')
@Check
class Demo:
def d(self):
print('this id Demo')
# 类装饰器和函数装饰器是有区别的,这里调用了才会执行__call__
demo()
dd = Demo()
dd.d()
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
61
62
63
64
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
61
62
63
64
# __bytes__
class A:
def __bytes__(self):
# 返回一个 bytes 对象
return b'this is __bytes__'
print(bytes(A()), type(bytes(A())))
1
2
3
4
5
6
2
3
4
5
6
# __format__
class A:
def __format__(self, format_spec):
return 'this is __format__![{}]'.format(format_spec)
def __str__(self):
# 返回值必须为一个 字符串 对象。
return 'this is __str__!'
a = A()
print(format(a, 'test')) # 有 __format__ 时会先调用 __format__
print(str.format('1'))
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# __repr__ 和 __str__
class A:
def __repr__(self):
# 此方法通常被用于调试,因此确保其表示的内容包含丰富信息且无歧义是很重要的。
return 'this is __repr__!'
def __str__(self):
# 返回值必须为一个 字符串 对象。
return 'this is __str__!'
print(repr(A()))
# __str__ 的三种调用方式
print(str(A()))
print(format(A())) # 有 __format__ 时会先调用 __format__
print(A())
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
# __abs__
class A:
def __init__(self, num):
self._num = num
def __abs__(self):
if self._num < 0:
return -self._num
return self._num
print(abs(A(-5)))
print(abs(-5))
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# __bool__
class A:
def __bool__(self):
# 调用此方法以实现真值检测以及内置的 bool() 操作;应该返回 False 或 True。
# 如果未定义此方法,则会查找并调用 __len__() 并在其返回非零值时视对象的逻辑值为真。
# 如果一个类既未定义 __len__() 也未定义 __bool__() 则视其所有实例的逻辑值为真。
return False
print(bool(A()))
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# __enter__ 和 __exit__
上次更新: 2023/09/04, 18:39:45