1. 概述
任何事物都有一个从创建,被使用,再到消亡的过程,在程序语言面向对象编程模型中,对象也有相似的命运:创建、初始化、使用、垃圾回收,不同的阶段由不同的方法(角色)负责执行。而这也正像是Python创建实例对象的过程,从创建到使用,然后再到被析构删除。这些过程也就是由__new__()
、__init__()
、__call__()
、__del__()
这些方法来实现的,下面详细介绍这几种方法:
2. __new__()
和__init__()
方法
__new__()
方法是在新式类中引入的方法,新式类是在创建的时候会继承内置object对象,而经典类是直接声明的。使用dir()方法可以打印出新式类中的所有属性和方法:
>>> class A(object):
... pass
...
>>> a = A()
>>> dir(a)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
__new__()
执行在__init__()
方法之前,能够真正的创建出一个实例对象,可以和__init__()
方法配合使用实现单例(只创建一个对象)的效果。
也就是会在构造方法__init()__
执行之前,__new__()
方法先被调用,返回一个实例对象,接着__init__()
被调用, 为实例对象添加预先定义的一些属性,如果类中没有定义这个方法,python解释器会去在这个类的父类中寻找,如果父类没有就会调用默认的__init__()
方法。
但是__new__()
也可以调用其他类的构造方法或者直接返回别的类对象作为本类的实例,或者也可以返回None。如果返回None,__init__()
不会被调用。
例1:
class A(object):
def __init__(self):
print("__init__ A")
super(A, self).__init__()
def __new__(cls, *args, **kwargs):
print("__new__ A")
self = super(A, cls).__new__(cls)
print(self)
return self
class B(A):
def __init__(self):
super(B, self).__init__()
print('__init__ B')
def __new__(cls, *args, **kwargs):
print("__new__ B")
# return None
return super(B, cls).__new__(cls)
a = A()
print('\n' + '***' * 10 + '\n')
b = B()
结果为:
__new__ A
<__main__.A object at 0x000002290FE6DC88>
__init__ A
******************************
__new__ B
__new__ A
<__main__.B object at 0x000002290FFED278>
__init__ A
__init__ B
# if return None
__new__ A
<__main__.A object at 0x00000169EBE12048>
__init__ A
******************************
__new__ B
可以看出:
- 在执行
__init__()
之前先是执行了__new__()
方法,并返回本类的实例。 - 子类在重写
__new__()
函数时,写return时必须返回有继承关系的类的__new__()
函数调用,即上面代码中的B类继承自A类,则重写B类的__new__()
函数,写return时,只能返回继承父类A.__new__(cls)
或者object.__new__(cls)
,不能返回其他类的。 - 如果B类的
__new()__
方法返回值为None的话,输出值为最下面部分,可以看出只有A类的__init__()
方法被调用了,但是B类的————init__()
并没有被调用。
例2:
3. __call__()
方法
如果在类中实现了__call__()
方法,那么类的实例对象会成为一个可调用对象(callable)。函数callable判断对象是否是可调用对象。
class A(object):
def __init__(self, name):
self.name = name
print("__init__ A")
super(A, self).__init__()
def __call__(self, *args, **kwargs):
print("__call__ A")
return self.name
a = A('Crise')
print(callable(a))
name = a()
print(name)
print(a.name)
结果为:
__init__ A
True
__call__ A
Crise
Crise
可以看出实例对象a是一个callbale对象,并能够在__call__()
方法中实现想要的功能。
4. __del__()
方法
__del__()
方法是类的析构函数,是python垃圾回收机制的实际应用,当类的所有引用都被删除后,该类就会被系统从内存中删除,注意是所有的引用都被删除,而不是每一次删除。实现如下:
class A(object):
def __init__(self, name):
self.name = name
print("__init__ A")
super(A, self).__init__()
def __new__(cls, *args, **kwargs):
print("__new__ A")
self = super(A, cls).__new__(cls)
print(self)
return self
def __call__(self):
print("__call__")
return 0
def __del__(self):
print('%s has been deleted' % self.name)
class B(A):
def __init__(self, name):
super(B, self).__init__(name)
print('__init__ B')
def __new__(cls, *args, **kwargs):
print("__new__ B")
return A.__new__(cls)
class C(B):
def __init__(self, name):
super(C, self).__init__(name)
print("__init__ C")
def __call__(self, *args, **kwargs):
return self.name
c = C("Crise")
print(c.name)
c1 = c
print(c1.__class__)
结果为:
__new__ B
__new__ A
<__main__.C object at 0x000001D4CAD0D518>
__init__ A
__init__ B
__init__ C
Crise
<class '__main__.C'>
Crise has been deleted
可以看出当实例对象c被复制给c1时,__del__()
不会被调用,只有当c1用完之后,实例对象才会被析构。
再加一些python的魔法方法吧:
Python3中只要类中的方法名格式为: __方法名__
都是为特殊的方法,可以称为"魔法"方法
5. __str__()
方法:
当使用print输出对象的时候,只要自己定义了__str__()
方法,那么就会打印从在这个方法中return的数据。
class Car:
def __init__(self, newWheelNum, newColor):
self.wheelNum = newWheelNum
self.color = newColor
def move(self):
print('车在跑,目标:夏威夷')
BMW = Car(4, "白色")
print(BMW)
print(id(BMW))
运行结果为:
<__main__.Car object at 0x000001DC4B533D68>
2045668179304
加上__str__()
方法之后:
class Car:
def __init__(self, newWheelNum, newColor):
self.wheelNum = newWheelNum
self.color = newColor
def __str__(self):
return "车是%s的,有%d个轮子" % (self.color, self.wheelNum)
def move(self):
print('车在跑,目标:夏威夷')
BMW = Car(4, "白色")
car_dsp = str(BMW) + ', 这辆车是Crise的'
print(car_dsp)
print(id(BMW))
运行结果为:
车是白色的,有4个轮子, 这辆车是Crise的
1613528775984