本帖最后由 Ensoleile 于 2023-1-10 00:35 编辑
魔法方法#通过对魔法方法重写,我们就能从中作梗
#参与构建对象之前还有个__new__()方法,在__init__()之前被调用,P161
#事实上对象就是由__new__(cls[, ...])方法来创建的,所以它的第一个参数是cls,而不是self
#所以对象的诞生流程是先调用__new__()方法创建一个类的实例对象,然后将其传递给__init__()方法
#需要重写__new__()方法的情况极少,通常只有两种情况可能用到:
#一种情况是在元类中定制类,在后续课程中讲解,先按住不表
#另一种情况是在继承不可变数据类型时,可以通过重写__new__()方法进行拦截
class CapStr(str):
def __new__(cls, string):
string = string.upper()
return super().__new__(cls, string)
#不需要考虑__new__()怎么去构造对象,直接让其父类<class 'str'>去做
cs = CapStr('FishC')
print(cs) #FISHC
#这里之所以能对不可变对象进行修改,是因为我们赶在实例对象被创建前就进行了拦截,
# 然后才调用super().__new__()创建真正的实例,由于CapStr类继承自str类,所以字符串该有的方法也继承了下来
print(cs.lower()) #fishc
#__del__(self):当对象将被销毁的时候调用此方法,P162
class C:
def __init__(self):
print('我来了')
def __del__(self):
print('我走了')
c = C() #我来了
del c #我走了
#并非调用del c就一定会触发__del__()魔法方法,仅当对象被销毁时才会触发
#python中引入了垃圾回收机制garbage collection,当检测到一个对象没有任何引用的时候,才会将它销毁
c = C() #我来了
d = c
del c #没有我走了
del d #我走了
#__del__方法可以通过创建一个该实例的新引用来推迟其销毁,也被称之为对象的重生
#官方不建议,但是可以实现
#虽然对象通过del语句被删除了,但如果在对象被销毁之前将self送出去,那么对象就算是得以重生
#del是个语句,没法执行这个语句的同时,又把它的返回值赋值给另一个变量存储,即没法通过返回值的形式返回self
class D:
def __init__(self, name):
self.name = name
def __del__(self):
global x
x = self
d = D('fishc')
print(d) #<__main__.D object at 0x000001574FDB7F70>
del d
print(x) #<__main__.D object at 0x000001574FDB7F70>
print(x.name) #fishc
#为避免污染全局变量,使用闭包
class E:
def __init__(self, name, func):
self.name = name
self.func = func
def __del__(self):
self.func(self)
def outter():
x = 0
def inner(y=None):
nonlocal x
if y:
x = y
else:
return x
return inner
f = outter()
e = E('fishc', f)
print(e) #<__main__.E object at 0x0000024B6E6AA8E0>
print(e.name) #fishc
del e
print(f()) #<__main__.E object at 0x0000024B6E6AA8E0>
print(f().name) #fishc
#e删除后f()就是e
#outter()返回值为inner(),f赋值为inner,c被删除时执行__del__()魔法方法
#c.func(c),即f(c),即inner(c),将c传给外层变量x,
#在再次调用f()时,y未传参,执行return x,即返回c
|