18910140161

python进阶之内置函数和语法糖触发魔法方法

顺晟科技

2021-06-16 10:45:01

435

之前已经总结了关键字、运算符和magic方法的对应关系,下面总结了python内置函数对应的magic方法。

魔术方法

数学计算

abs(args):返回值,调用_ _ abs _ _

Round(args):返回舍入值并调用_ _ round _ _

Math.floor():向下舍入并调用_ _ floor _ _

Math.ceil():向上舍入,调用_ _ ceil _ _

Math.trunc():找到一个值最接近0的整数,调用_ _ trunc _ _

Divmod(a,b):返回商和余数,调用_ _ divmod _ _

Pow(a,b):回电,调用_ _ pow _ _

Sum():返回并调用_ _ sum _ _

Float():转换小数,调用_ _ float _ _

Int():转换整数,调用_ _ int _ _

Str():转换字符串并调用_ _ str _ _

Sys.getsizeof():内存中对象的大小,调用_ _ sizeof _ _

Bin(*args,**kwargs):调用参数的__bin__方法,返回整数的二进制表示,只支持一个参数和int类型

Hash():调用__hash__方法获取对象的哈希值。两个数相等的哈希值相等,但反过来不一定成立。

十六进制(*args,**kwargs):调用__hex__方法查找整数的十六进制表示,只支持int类型

Oct(*args,**kwargs):调用__oct__方法查找Integer的八进制表示,只支持int类型

访问控制

_ _ getattr _ _ (self,name) : getattr方法被触发,该方法仅对对象的未定义属性有效,也就是说,如果视图得到一个不存在的属性,如果对象没有定义__getattribute__(self,name)方法,将调用该方法;

__getattr__ (self,name):getattr方法被触发。如果对象定义了此方法,则必须触发它。将不会调用_ _ getattr _ _方法。也可以由self.name语法sugar触发;

_ _ setattr _ _ (self,name,value):由setattr方法触发,设置一个对象的属性;也可以由self.name=' '语法糖触发。

_ _ delattr _ _ (self,name):由delattr方法触发删除对象的属性,或由delattr.name触发;

容器类型

在Python中实现自定义容器类型需要一些协议。不变的容器类型有以下协议:

不可变容器,需要定义_len_和_ getitem _

变量容器需要定义_len_、_getitem_、_setitem_、_ delivery _

容器可以迭代,并且需要定义_ ITER。

迭代器,必须遵守迭代器协议,需要定义_iter_和_next_方法。

索引语法糖和魔术方法

__len__(self):返回容器的长度;

__getitem__(self,key):使用self[key]的语法获取sugar元素,会触发;

__setitem__(self,key): self[key]=' XXX '形式的复制将触发;

_ _ delivery _ _ (self,key) :使用del self[key]语法触发sugar

_ _ reversed _ _(self): reversed(self)触发器反转容器;

__missing__(self,key):如果元素没有触发器,则字典结构以self[key]的形式获取元素;

切片语法糖和魔术方法

py2和py3在底层切片的原理上差别很大。py2使用三种神奇的方法:_getslice_、_setslice_、_delslice_,而py3通过_getitem_、_setitem_、_ delivery _来控制索引和切片。

#在py 2中

ls=[1,2,3,4]

print中的语法sugar(ls[1:3])# py2调用__getslice__方法,该方法在py3中被丢弃

Dells [1:3] #此语法sugar调用py 2中的__delslice__方法,该方法在py3中被丢弃

Ls [1:3]=[1,2,2] #语法sugar调用py2中的__setslice__方法,该方法在py3中被丢弃

#在py 3中

类别人员(对象):

def __getitem__(self,item):

打印(项目)

返回“getitem”

def __setitem__(self,key,value):

打印(键、值)

返回“setitem”

def __delitem__(self,key):

打印(键)

返回“delitem”

if __name__=='__main__':

人=人()

print(person[0])# person[0]==person。__getitem__(0)

print(person[0:2])# person[0:2]==person。__getitem__(切片(0,2,无))

person[0:2]=' test ' #==person。__setitem__(切片(0,2,无),“测试”)

del person[0:2] #==person。__delitem__(切片(0,2,无))

#结果

0

生成物品

切片(0,2,无)

生成物品

切片(0,2,无)测试

切片(0,2,无)

python在处理索引语法sugar时,会将索引作为一个参数,传递给相关的getitem、setitem和delivery这些神奇的方法。在处理切片语法糖时,调用切片方法获取切片实例对象,并调用相关魔术方法作为参数。

复制

__copy__(self):如果对象定义了此方法,copy.copy()将调用此方法返回复制的对象;

__deepcopy__(self,x):如果对象定义了此方法,copy.deepcopy()将调用此方法返回复制的对象;

连载

序列化可以简单理解为任何数据的描述方法。如果多个平台遵循相同的序列化协议,那么传输数据会很方便。Python的默认序列化模块是pickle。

序列化的一个简单例子

类别人员(对象):

def __init__(self):

self.name='cai '

if __name__=='__main__':

进口泡菜

人=人()

带open('。/person.txt ',' wb') as f:

#序列化后存储

pickle.dump(person,f)

带open('。/person.txt ',' rb') as f:

#反序列化

per=pickle.load(f)

打印(按姓名)

#我们可以保存一个类,然后直接阅读使用。

相关魔术方法

__getinitargs__(self):这种魔法方法在py3里好像被抛弃了。原函数是在序列化时获取实例化参数,应该返回一个元组;

__getnewargs__(self):对于一个新类,通过此方法在反pickle期间更改传递给__new__的参数;应该返回一个参数元组。

__getstate__(self):定义对象序列化时的状态,而不是使用对象的__dict__属性,必须返回一个字典,该字典将替换__dict__属性并在序列化过程中被调用;

__setstate__(self,state):当对象反pickle时,如果定义了__setstate__,对象的状态将传递给这个magic方法,而不是直接应用到对象的__dict__属性,状态参数是序列化前的__dict__属性。

类别人员(对象):

def __init__(self,name):

打印(“初始化”)

self.name=name

def __getinitargs__(self):

打印(' initargs ')

返回'赵',

def __getnewargs__(self):

打印(' newargs ')

返回'王',

def __getstate__(self):

打印(' getstate ')

返回{'name':'xiao'}

def __setstate__(self,state):

打印('设置状态')

打印(状态)

自我。_ _ dict _ _=状态

if __name__=='__main__':

进口泡菜

人=人(“才”)

带open('。/person.txt ',' wb') as f:

#序列化后存储

pickle.dump(person,f)

带open('。/person.txt ',' rb') as f:

#反序列化

per=pickle.load(f)

打印(按姓名)

#结果

__新_ _

初始化

newargs

方法

__新_ _

设置

{'name': 'xiao'}

描述:

在拾取序列化对象之前,请执行__getnewargs__或__new__方法的参数;

然后执行__getstate__方法,返回值替换对象的__dict__属性值;

反序列化时,调用新方法并使用getnewargs返回的值作为参数创建一个实例;

最后调用__setstate__方法,以getstate方法的返回值作为状态参数;

因此,因为在反序列化过程中初始化不会调用init方法,所以getinitargs和getnewargs方法的作用并不显著;

其他的

_ _ instancecheck _ _(自身,实例):实例触发器确定对象的类型

_ _子类check _ _ (self,subclass) :由子类触发,判断一个对象是另一个对象的子类;

__call__:callable触发器,判断一个对象是否可以调用;

由__dir__(self):dir()触发,获取对象所有属性和方法名称列表;

__str__和__repr__

调用str triggers _str_,并调用repr()触发器_repr_,但是print()也可以触发__str__和_ _ repr _。如果对象定义了_str_,print()通常会触发_str_,否则,_ repr _但是像列表和字典这样的容器总是使用_repr_方法。

__str__和__repr__

一般来说_str_的返回结果可读性强,而_repr_的返回结果准确性好。

默认情况下,当需要__str__方法但找不到时,会自动调用_repr_方法。

摘要

熟悉了python语法糖、内置函数、魔术方法之间的关系后,写一个优雅易用的类显然是有帮助的。

我们已经准备好了,你呢?
2024我们与您携手共赢,为您的企业形象保驾护航