python 常用魔术方法-第一篇

魔术方法

在Python中,所有以“__”双下划线包起来的方法,都统称为“Magic Method”,中文称『魔术方法』

魔术方法就是一个类/对象中的方法,和普通方法唯一的不同时,普通方法需要调用!而魔术方法是在特定时刻自动触发

1. __new__

实例化魔术方法  类方法
触发时机: 在实例化对象时触发
参数:至少一个cls 接收当前类
返回值:必须返回一个对象实例
作用:实例化对象
注意:实例化对象是Object类底层实现,其他类继承了Object的 __new__ 才能够实现实例化对象。
没事别碰这个魔术方法,先触发__new__才会触发__init__ 

2 .__init__

初始化魔术方法
触发时机:初始化对象时触发(不是实例化触发,但是和实例化在一个操作中)
参数:至少有一个self,接收对象
返回值:无
作用:初始化对象的
成员

pytorch 中,在自定义数据集时候需要重写该函数用来定义数据集路径等。 


当我们创建一个实例的时候,实际上是调用的__new__函数创建实例,然后再调用__init__对实例进行的初始化

Python当中的类的构造函数是 __new__ 。__init__并不是构造函数,它只是初始化方法。也就是说在调用__init__之前,我们的实例就已经被创建好了,__init__只是为这个实例赋上了一些值。

在使用Python面向对象的时候,一般都不会重构 __new__,而是使用Python提供的默认构造函数

参考:Python面试常见问题,__init__是构造函数吗? - 云+社区 - 腾讯云

3. __del__ 

析构魔术方法  构析函数
触发时机:当对象没有用(没有任何变量引用)的时候被触发
参数:一个self 
返回值:无
作用:在销毁对象时回收资源
注意:del不一定会触发当前方法,只有当前对象没有任何变量引用时才会触发


4 .__len__

触发时机:使用 len(对象) 的时候触发
参数:一个参数self
返回值:必须是一个整型
作用:可以设置为检测对象成员个数,但是也可以进行其他任意操作
注意:返回值必须必须是整数,否则语法报错,另外该要求是格式要求。

pytorch 中,在自定义数据集时,需要重写该函数,用来返回 数据的个数。


 5.  __call__

调用对象的魔术方法
触发时机:将对象当作函数调用时触发,方式: 对象(参数)
参数:至少一个self接收对象,其余根据调用时参数决定
返回值:根据情况而定
作用:可以将复杂的步骤进行合并操作,减少调用的步骤,方便使用
注意:无

允许一个类的实例像函数一样被调用。实质上说,这意味着 x() 与 x.__call__() 是相同的。注意 __call__ 的参数可变。这意味着你可以定义 __call__ 为其他你想要的函数,无论有多少个参数。

__call__ 在那些类的实例经常改变状态的时候会非常有效。调用这个实例是一种改变这个对象状态的直接和优雅的做法。

在pytorch 中:在Model继承的父类nn.Module里应该有一个__call__()直接自动调用了forward函数,而在Model这个nn.Module的子类里我们又重写了forward函数,所以我们间接地通过父类nn.Module里的__call__()调用了子类Model里的forward函数


6. 容器类型相关魔术方法

__len__(self)                  定义当被 len() 调用时的行为(返回容器中元素的个数)
__getitem__(self, key)         定义获取容器中指定元素的行为,相当于 self[key]
__setitem__(self, key, value)  定义设置容器中指定元素的行为,相当于 self[key] = value
__delitem__(self, key)         定义删除容器中指定元素的行为,相当于 del self[key]
__iter__(self)                 定义当迭代容器中的元素的行为
__reversed__(self)             定义当被 reversed() 调用时的行为
__contains__(self, item)       定义当使用成员测试运算符(in 或 not in)时的行为

当实例对象(假定为p)做 p[key] 运算时,会调用类中的方法 __getitem__ 。

在pytorch中,自定义数据集时,需要重写该方法,获取一条数据。该方法需要一个 index 索引。


__iter__(self)

一文彻底搞懂Python可迭代(Iterable)、迭代器(Iterator)和生成器(Generator)的概念 - 云+社区 - 腾讯云

一个对象(在Python里面一切都是对象)只要实现了__iter__()方法,那么用isinstance()函数检查就是Iterable对象;

常见的可迭代对象

Python中有哪些常见的可迭代对象呢?

  1. 集合或序列类型(如listtuplesetdictstr
  2. 文件对象
  3. 在类中定义了__iter__()方法的对象,可以被认为是 Iterable对象,但自定义的可迭代对象要能在for循环中正确使用,就需要保证__iter__()实现必须是正确的(即可以通过内置iter()函数转成Iterator对象。iter()函数是能够将一个可迭代对象转成迭代器对象,然后在for中使用)
  4. 类中实现了如果只实现__getitem__()的对象可以通过iter()函数转化成迭代器但其本身不是可迭代对象。所以当一个对象能够在for循环中运行,但不一定是Iterable对象。

 在定义一个可迭代对象时,我们要非常注意__iter__()方法的内部实现逻辑,一般情况下,是通过一些已知的可迭代对象(例如,上文提到的集合、序列、文件等或其他正确定义的可迭代对象)来辅助我们来实现

for中使用的对象,不一定是可迭代对象。

一个对象实现了__iter__()__next__()方法,那么它就是一个迭代器对象。

一个迭代器(Iterator)对象不仅可以在for循环中使用,还可以通过内置函数next()函数进行调用。

如果一个对象定义了 __iter__ 和 __next__ 两个方法,它就是一个迭代器。对于迭代器来说,__iter__ 返回的是它自身 self__next__ 则是返回迭代器中的下一个值,如果没有值了则抛出一个 StopIteration 的异常。

如果一个对象定义了 __iter__ 和方法,返回一个迭代器对象,那么它就是一个可迭代的对象

迭代器(Iterator)和可迭代(Iterable)这两个的差别:

  1. 一个迭代器一定是可迭代对象,因为它一定有 __iter__ 方法。反过来则不成立。(事实上,Iterator 就是 Iterable 的子类)
  2. 迭代器的 __iter__ 方法返回的是自身,并不产生新实例。而可迭代对象的 __iter__ 方法通常会生成一个新的迭代器对象。

for 循环的实现理解:

  1. 首先 for 循环会调用可迭代对象的 __iter__ 方法,获取相应的迭代器
  2. 每次循环,将迭代器的 __next__ 方法的返回值赋值给循环变量
  3. 直到捕获迭代器抛出的 StopIteration 异常,循环结束

参考: 

Python进阶——如何正确使用魔法方法?(上) - 云+社区 - 腾讯云

11 python 魔术方法_黎丶辰的博客-CSDN博客_python魔法方法 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

理心炼丹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值