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

前言

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

魔法方法

数学计算

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__方法,获取一个对象的散列值,相等的两个数哈希值相等,反过来不一定成立

hex(*args, **kwargs):调用__hex__方法,求整数的十六进制表示形式,只支持Int类型

oct(*args, **kwargs):调用__oct__方法,求整数的八进制表示形式,只支持Int类型

访问控制

__getattr__(self, name):getattr方法触发,仅对对象未定义的属性有效,即如果视图获取一个没有的属性时会调用该方法,前提是该对象未定义__getattribute__(self, name)方法;

__getattribute__(self, name):getattr方法触发,如果对象定义了该方法,一定触发,__getattr__方法将不会被调用;它也可以被self.name语法糖触发;

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

__delattr__(self, name):delattr方法触发,删除一个对象的属性,或由del self.name 形式触发;

容器类型

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

不可变容器,需要定义 _len_ 和 _getitem_ ;

可变容器,需要定义 _len_ 、_getitem_、_setitem_、_delitem_ ;

容器可迭代,需要定义 _iter_ ;

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

索引语法糖与魔法方法

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

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

__setitem__(self, key):使用self[key] = 'xxx'形式复制会触发;

__delitem__(self, key):使用del self[key]语法糖触发

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

__missing__(self, key):字典结构使用self[key]形式获取元素,如果元素不存在触发;

分片语法糖与魔法方法

切片在底层的原理,py2和py3有很大的不同,py2中使用_getslice_、_setslice_、__delslice__三个魔法方法控制,py3中将索引和切片统一由_getitem_、_setitem_、__delitem__控制。

# py2中

ls = [1,2,3,4]

print(ls[1:3]) # py2中该语法糖调用__getslice__方法,py3中废弃

del ls[1:3] # py2中该语法糖调用__delslice__方法,py3中废弃

ls[1:3] = [1,2,2] # py2中该语法糖调用__setslice__方法,py3中废弃

# py3中

class Person(object):

def __getitem__(self, item):

print(item)

return 'getitem'

def __setitem__(self, key, value):

print(key, value)

return 'setitem'

def __delitem__(self, key):

print(key)

return 'delitem'

if __name__ == "__main__":

person = Person()

print(person[0]) # person[0] ==> person.__getitem__(0)

print(person[0:2]) # person[0:2] ==> person.__getitem__(slice(0,2,None))

person[0:2] = 'test' # ==> person.__setitem__(slice(0,2,None), 'test')

del person[0:2] # ==> person.__delitem__(slice(0,2,None))

# 结果

0

getitem

slice(0, 2, None)

getitem

slice(0, 2, None) test

slice(0, 2, None)

python在处理索引语法糖的时候,将索引当做参数传入相关getitem、setitem、delitem的魔法方法;在处理切片语法糖的时候先调用slice方法得到slice实例对象,将其作为参数调用相关的魔法方法。

拷贝

__copy__(self):如果对象定义了该方法,copy.copy()就会调用该方法返回拷贝对象;

__deepcopy__(self, x):如果对象定义了该方法,copy.deepcopy()就会调用该方法返回拷贝对象;

序列化

序列化我们可以简单理解成对任何数据的一种描述方法,如果多种平台遵循了相同的序列化协议,数据之间的传递就会变得方便。python默认的序列化模块为pickle。

序列化的简单例子

class Person(object):

def __init__(self):

self.name = 'cai'

if __name__ == "__main__":

import pickle

person = Person()

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

# 序列化后存储

pickle.dump(person,f)

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

# 反序列化

per = pickle.load(f)

print(per.name)

# 我们可以把一个类保存起来,后续读取它直接使用。

相关的魔法方法

__getinitargs__(self):该魔法方法在py3中似乎被废弃,原本的功能是在序列化时获取实例化参数,应该返回一个元组;

__getnewargs__(self):对新式类,通过这个方法改变类在反pickle时传递给__new__ 的参数;应该返回一个参数元组。

__getstate__(self):定义对象被序列化时的状态,而不使用对象的 __dict__ 属性,必须返回一个字典,他会去替代 __dict__ 属性,在序列化时被调用;

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

class Person(object):

def __init__(self,name):

print('init')

self.name = name

def __getinitargs__(self):

print('initargs')

return 'zhao',

def __getnewargs__(self):

print('newargs')

return 'wang',

def __getstate__(self):

print('getstate')

return {'name':'xiao'}

def __setstate__(self, state):

print('setstate')

print(state)

self.__dict__ = state

if __name__ == "__main__":

import pickle

person = Person('cai')

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

# 序列化后存储

pickle.dump(person,f)

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

# 反序列化

per = pickle.load(f)

print(per.name)

# 结果

__new__

init

newargs

getstate

__new__

setstate

{'name': 'xiao'}

xiao

说明:

pickle序列化对象之前,先执行__getnewargs__或__new__方法的参数;

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

反序列化时调用new方法,以getnewargs返回的值作为参数创建实例;

最后调用__setstate__方法,将getstate方法的返回值作为state参数;

所以由于反序列化时不会调用init方法初始化,getinitargs和getnewargs方法的作用都变得不大;

其他

__instancecheck__(self, instance):instance触发,判断对象的类型

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

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

__dir__(self):dir()触发,获取对象的所有属性、方法的名字组成的列表;

__str_和_repr

调用str触发_str_,调用repr()触发_repr_,但是print()也可以触发__str_和_repr,如果对象定义了_str_,则print()一般触发_str_,否则触发_repr_;但列表以及字典等容器总是会使用_repr_ 方法.

__str__和__repr__的区别

一般来说,_str_ 的返回结果在于强可读性,而 _repr_ 的返回结果在于准确性;

默认情况下,在需要却找不到 __str__方法的时候,会自动调用 _repr_ 方法。

总结

熟悉了python语法糖、内置函数与魔法方法之间的关系后,显然对于如何写好一个优雅易用的类有很大的帮助。

参考

python进阶之内置方法

python进阶之内置方法 字符串类型的内置方法 常用操作与方法: 按索引取值 str[index] 切片 ste[start:stop:step] 长度 len(str) 成员运算in和not in ...

Python基础之内置函数(二)

先上一张图,python中内置函数: python官方解释在这:点我点我 继续聊内置函数: callable(object):检查对象是否可被调用,或是否可执行,结果为bool值 def f1(): ...

Python基础之内置函数和递归

一.内置函数 下面简单介绍几个: 1.abs() 求绝对值 2.all() 如果 iterable 的所有元素都为真(或者如果可迭代为空),则返回 True 3.any() 如果 iterable 的 ...

python基础之内置函数补充、匿名函数、递归函数

内置函数补充 python divmod()函数:把除数和余数运算结果结合起来,返回一个包含商和余数的元组(a // b, a % b) 语法: 1 divmod(a, b) #a.b为数字,a为除数 ...

python基础之内置函数

该博客内容参考http://www.cnblogs.com/wupeiqi/articles/4943406.html 内置函数 一 详细见python文档,猛击这里 文件操作 操作文件时,一般需要经 ...

python基础之内置函数和匿名函数

内置函数 学习函数以后多了很多概念,例如函数的命名空间,函数的作用域,函数的调用等等,函数的作用就是为了实现某些功能而方便以后可以调用,内置函数就是这样的一些公共的函数,被称为内置函数. 我们就一 ...

python学习之内置函数(二)

4.7.3 内置函数(2) int() str() bool() set() list():将一个可迭代对象转化为列表 tuple():将一个可迭代对象转换成元组 dic(): 通过相应的方式创建字典 ...

Python系列之内置函数

内置函数 一.数学运算类: abs(a):求绝对值如果参数是个复数则返回复数的模. a = abs(-1) print(a) >>>1 compilex([real[, imag]] ...

python学习之内置函数(一)

4.7 内置函数 4.7.1 内置函数(1) eval 执行字符串类型的代码,并返回最终结果. eval('2 + 2') # 4 n=81 eval("n + 4") # 85 ...

随机推荐

Android安全开发之ZIP文件目录遍历

1.ZIP文件目录遍历简介 因为ZIP压缩包文件中允许存在“../”的字符串,攻击者可以利用多个“../”在解压时改变ZIP包中某个文件的存放位置,覆盖掉应用原有的文件.如果被覆盖掉的文件是动态链接s ...

MVC学习网站

http://www.cnblogs.com/artech/archive/2012/04/10/how-mvc-works.html

nginx--配置https服务器

1.下载安装nginx: nginx可以从这里选择对应版本下载,我下载的是1.8.1版本.下载完成后,直接解压缩,命令窗口进入根目录,输入命令: start nginx 在浏览器中,直接输入&quot ...

ios 获取n个月前或者n个月后的日期

NSCalendar *calendar = [NSCalendar currentCalendar]; NSRange range = [calendar rangeOfUnit:NSDayCale ...

POJ 3723 Conscription

Conscription Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6325   Accepted: 2184 Desc ...

gcc编译通过,运行却显示“段错误”的解决方法

​第一次在Liunx上(liunx mint 17)使用gcc编译c文件,竟然提示“找不到stdio.h",经过google后发现执行 sudo apt-get install build- ...

wampserver php 设置时间

php.ini 查找date.timezone = Europe/Paris 修改成亚洲地区 date.timezone = Asia/Shanghai

socket网络编程快速上手(二)——细节问题(3)

3.SIGPIPE问题 人怕牺牲,我们写的程序也一样,人有死不瞑目,程序又何尝不是?程序跑着跑着,突然就崩掉了.好一点的牺牲前告诉你些打印,差点的也能用core文件等一些手段查出死在哪了,最惨不忍睹的 ...

sass学习--安装ruby

1.下载ruby:https://rubyinstaller.org/downloads/ 2.安装完ruby之后,在开始菜单中,找到刚才我们安装的ruby,打开Start Command Promp ...

java对象在内存中的结构

在HotspotJVM中,32位机器下,Integer对象的大小是int的几倍? 我们都知道在java语言规范已经规定了int的大小是4个字节,那么Integer对象的大小是多少呢?要知道一个对象的大 ...

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值