看了小甲鱼的Python教程视屏后做的一些总结
init(self)
构造方法之一,用于初始化实例对象,在创建实例对象时将自动调用,可根据具体需求设置实例对象的一些属性:
class Ball:
def __init__(self, name):
self.name = name
def call(self):
print('我叫%s' % self.name)
a = Ball('球A')
a.call()
输出结果为:
‘我叫球A’
init(self)不能有返回值
new(cls[,…])
真正创建实例对象的方法,创建实例对象时将首先调用此方法进行实例对象的创建,然后再调用__init__方法对实例对象进行初始化。Object类中已对其进行了定义,它将通过一系列封装起来的操作完成对象的创建。
__new__方法一般不重写,如果单纯地对其重写:
class A:
def __new__(cls):
print('__new__方法被调用')
def __init__(self):
print('self方法被调用')
aaa = A()
此时,__init__将不被调用,仅输出 ‘__new__方法被调用’,而且实例对象aa也不存在(输入print(aa)
将得到None)。
这是因为定义__new__方法时对A的父类Object中的__new__方法进行了重写,原有的用于创建实例对象的代码被覆盖,导致未能创建实例对象。
所以重写__new__方法通常会在返回值里调用其父类的__new__来保证实例对象的成功创建:
class A:
def __new__(cls):
print('__new__方法被调用')
return super().__new__(cls)
def __init__(self):
print('self方法被调用')
aa = A()
new(cls[,…])中的cls默认指代当前类,它将创建cls类型的实例对象,而此实例对象将作为self传给__init__,也就是说,__new__创建的实例对象就是__init__的第一个参数self
__new__中cls后的参数也将作为__init__中self后的参数传入。但如果__new__创建的实例对象的类型不属于当前类,则当前类的__init__方法不会被调用:
class A:
def __new__(cls):
print('A--->New')
return super().__new__(A)
def __init__(self):
print('A--->Init')
class B:
def __new__(cls):
print('B--->New')
return super().__new__(A)
def __init__(self):
print('B--->Init')
aa = A()
bb = B()
输出结果为:
A—>New
A—>Init
B—>New
A—>New
这里A的__new__方法返回了A类型的实例对象,所以A的__init__方法被调用,而B的__new__方法返回的为A类型的对象,所以B的__init__对象没有被调用(使用type(bb)
可发现bb的类型为A),这里将return super().__new__(A)
换为return super().__new__(cls)
将可调用B的__init__方法
__new__方法中cls后的参数会自动传给__init__方法,如下:
class A:
def __new__(cls, string):
return super().__new__(cls, string)
def __init__(self, string):
print(string)
aaa = A('I love China!')
将输出 ‘I love China!’
一般很少重写__new__方法,但如果继承了一不可变类型(如字符串)却需要进行修改,则需重写,如下(小甲鱼课上举的例子):
class CapStr(str):
def __new__(cls, string)
string = string.upper()
return str.__new__(cls,string)
a = CapStr('I love China')
这里将输出’I LOVE CHINA’,
即先将字符串改为大写,然后将修改后的字符串作为str__new__方法的一个参数传入,由str的__new__方法创建一个字符串类型的实例对象,所以使用type(a)
查看实例对象a的类型可以发现a的类型为str(字符串)
这也是__new__方法的作用之一,即对一些不可变类型在其未被创建时做出需要的修改
del(self)
析构器,当一个对象要被销毁时会自动调用__del__(self),但del x
并不等于自动调用x.__del__()
,即当垃圾回收机制认定对象无用将要回收时,才会自动调用__del__(self)(当del删除了一个对象的所有引用,将自动启动__del__(self))
class A:
def __del__(self):
print('A--->Del')
a1 = A()
a2 = A()
a3 = A()
del a1
del a2
del a3 # 仅在此句被执行后打印'A--->Del'