在Python中,定制类是一种通过定义特定的方法来定制类的行为和属性的方式。Python提供了许多预定义的特殊方法(也称为魔术方法或双下划线方法),这些方法可以被自定义类覆盖以实现不同的功能。
一般魔法方法名都是以__
开头和结尾。在前面的教程或者日常学习使用中,我们都已经或多或少的接触过一些魔法方法了,比如:__init__等。
这2个魔法方法可以让你改变从一个类建立一个对象时候的行为。这2个魔法方法也比较容易搞混。
这个__new__是从一个class建立一个object的过程。
而__init_是有了这个object之后,给这个object初始化的过程。
class A:
def __new__(cls, *args, **kwargs):
print('__new__', args, kwargs)
return super().__new__(cls)
def __init__(self, *args, **kwargs):
print('__init__', args, kwargs)
a = A(1)
new (1,) {}
init (1,) {}
在类的初始化时,传入的参数会同时传给__new__、init,并且__new__方法是必须要有返回值的,返回的就是该对象本身。而__init__则不需要返回。上面的类的初始化相当于:
obj = new(A, 1)
a = init(obj, 1)
__new__方法一般很少会用到,只有在元类、单例模式时才会用到。而__init__方法则经常会用到。一般在__init__方法里,我们需要处理一些类在实例化成对象时,要初始化的操作。
__del__方法可以粗略的理解为一个析构函数。当对象被释放的时候,就会调用这个方法,这个时候我们就可以在该方法内写上要具体的措施。
from icecream import ic
class A:
def __del__(self):
print('__del__')
a = A()
ic()
ic(a)
16:31:34|> t1.py:10 in at 16:31:34.128
16:31:34|> a: <main.A object at 0x000001CEFDB0B310>
del
注意:
1、在Python中,Python自动释放对象比较不可控,所以这个__del__方法不是那么的好用。
2、del关键字和这个__del__并无关系,用del obj时并不一定会触发该对象的__del__方法。del obj只是让这个obj少一个引用。
这两个魔法方法的功能是相似的。都是返回这个obj的字符串表示。这2个方法之间主要是语义上的不同。
一般来说,__str__这个函数返回的内容是人类更容易理解的string,比较注重可读性。
而__repr__返回的内容一般有更详细的信息。
在某个类中,如果这2个方法都定义了,那么print会使用__str__函数返回的内容。可以使用repr、str分别直接调用obj中的__repr__和__str__方法。并得到返回的结果:
class A:
def __repr__(self):
return 'repr'
def __str__(self):
return 'str'
a = A()
print(a)
print(repr(a))
print(str(a))
str
repr
str
如果没有定义__str__,那么repr、str返回的都是__repr__方法结果。
当我们尝试用某种格式打印对象时,就有可能调用到这个__format__方法。
from icecream import ic
class A:
def __format__(self, format_spec):
if format_spec == 'x':
return '0xA'
return 'A'
ic(f'{A()}')
ic(f'{A():x}')
ic('{}'.format(15))
ic('{:b}'.format(15))
ic('{:x}'.format(15))
ic(f'{15}')
ic(f'{15:b}')
ic(f'{15:x}')
15:15:29|> f’{A()}‘: ‘A’
15:15:29|> f’{A():x}‘: ‘0xA’
15:15:29|> ‘{}’.format(15): ‘15’
15:15:29|> ‘{:b}’.format(15): ‘1111’
15:15:29|> ‘{:x}’.format(15): ‘f’
15:15:29|> f’{15}‘: ‘15’
15:15:29|> f’{15:b}‘: ‘1111’
15:15:29|> f’{15:x}': ‘f’
当你尝试用你自己的这个class去建立一个bytes的时候,应该返回什么。一般很少会用到。除非要定制化class的bytes的返回。
from icecream import ic
class A:
def __bytes__(self):
print('__bytes__')
return bytes([0, 1])
ic(bytes(A()))
bytes
15:17:57|> bytes(A()): b’\x00\x01’