python中的双下方法---带你从底层逻辑看python(__str__、__repr__、__del__、__call__)

我们在写代码的过程中,往往都是直接去取调用函数,比如len(),print()input()等等,事实上,这些方法或者函数在调用过程中,触发了很多内在的运行机制和底层逻辑,深入研究之后,我们能看到不一样的python,下面跟大家分享几个双下方法及他们的运行逻辑。
双下方法:指的是带双下划线的方法,比如我们在类中非常常见的的__init__,今天我们要介绍的是__str__、reprdelcall
-----------------------------------分割线-----------------------------------
str
我们先定义这样一个类,并实例化:

class A:
    pass
a=A()
print(a)

输出结果是:
<main.A object at 0x0000026034D36E08>
这个结果其实是类的内存地址,同时可以看出他是object的一个子类,修改代码再次测试:

class A:
    pass
    def __str__(self):
        return '我已经打印了'
a=A()
print(str(a))
print(a)

这时输出结果为:
我已经打印了
我已经打印了
说明类中的__str__方法被调用两次,这其中的逻辑是:
当我们在类中调用str()方法,或者打印某个对象时,就会触发__str__方法,我们可以利用这一特性,设置需要的返回值作为参考;当对象a打印时,程序默认先调用对象a的__str__方法,当对象a没有设置时,则找到他的父类object去调用,这就是为什么我们设置了__str__方法时,会被触发的原因。
-----------------------------------分割线-----------------------------------
repr
repr() 函数将对象转化为供解释器读取的形式,简单说就是转化成其本来的形式。比如

a='1'
print(a)
print(repr(a))

打印结果:
1
‘1’
虽然a是字符串类型的数字,但当我们直接打印时,显示的是数字1,使用repr时,则会显示字符串的形式,也就是他的本来形式。还是上面同样的例子,我们将str改为repr

class A:
    def __repr__(self):
        return '我已经打印了repr'
a = A()
print(a)

结果如下:
我已经打印了repr

同样的,在类中打印对象时,会触发这个方法,看起来结果与__str__是一样的;如果__str__和__repr__同时存在时,顺序是如何的?代码测试下

class A:
     def __str__(self):
        return '我已经打印了str'
     def __repr__(self):
        return '我已经打印了repr'
a = A()
print(a)

结果如下:
我已经打印了str

运行逻辑:str__和__repr__同时存在时,优先执行__str,当没有__str__时,会继续执行__repr__。
-----------------------------------分割线-----------------------------------
del__析构方法:当我们的程序执行完成后,会释放内存,这时就会触发__del。比如下面的例子:

class A:
    def __del__(self):
        print( '我已经执行了')
a = A()
del a

我们在A类中实例化对象a,然后删除a,就会触发__del__方法。
结果如下:
我已经执行了
此时如果我们打印对象a,会发现结果如下:
NameError: name ‘a’ is not defined
说明我们使用del删除时,不仅仅会触发__del__方法,也会对对象删除,而且是先执行前者。
因为他不仅仅在使用del时触发,在程序结束,内存释放的时候也会被触发,我们可以使用__del__作为工作的收尾,所以比如关闭文件等操作。
-----------------------------------分割线-----------------------------------
call:这个方法平时我们很少见到,但却很有意思,先看下面的代码

class A:
    def __call__(self):
        print('我已经执行了')
a = A()()

执行结果:
我已经执行了

从上面的结果可以推测出,当对象加上()后,会触发__call__方法,实际运行结果也与我们推测的是一样的。
总结:
1)str:在类中打印时触发
2)repr:在类中打印时触发,但__str__存在时,优先执行__str__
3)del:在执行del或者内存释放时触发
4)call:在对象后加()时触发
更多应用,大家可以尝试摸索下

发布了13 篇原创文章 · 获赞 1 · 访问量 189

猜你喜欢

转载自blog.csdn.net/aa12551827/article/details/104919173
今日推荐