Python中Property内建函数深入理解
来源:互联网 发布:淘宝卖家刷信誉怎么刷 编辑:程序博客网 时间:2024/05/29 17:23
Property内建函数深入理解
先把python核心编程一句话搬过来:
属性是一种有用的特殊类型的描述符,它们是用来处理所有对实例属性的访问,其工作方式和我们前面说过的描述符相似,一般情况下,当你使用属性符号来处理一个实例属性时,其实你是在修改这个实例的__dict__
属性。表面上看,property()访问和一般的属性访问没有什么区别,但是它使用了函数或者方法。property()内建函数有四个参数
property(fget=None, fset=None, fdel=None, doc=None)
四个参数都是函数,且在类声明的时候就已经调用了。
OK,还是云里雾里, 首先看一个简单例子
class T(object): def __init__(self,x): self.__x=x def get_x(self): return self.__x+1 x=property(get_x)
>>>t=T(2)>>>t.__dict__{'_T__x': 3}
>>>T.__dict__dict_proxy({'__module__': 'pro', 'get_x': <function get_x at 0x7f9864263668>, '__dict__': <attribute '__dict__' of 'T' objects>, 'x': <property object at 0x7f98642574c8>, '__weakref__': <attribute '__weakref__' of 'T' objects>, '__doc__': None, '__init__': <function __init__ at 0x7f98642635f0>})
如果这时候输入t.x
会产生什么样的结果呢?t.__dict__['_T__x']
又是什么呢?
首先在t.__dict
中,_T__x
这个是什么呢?这就要说到python的私有变量 , python把两个下划线开头的变量当成私有变量,也就是在__init__(self,x)
方法中的 self.__x
,私有变量在代码生成之前会自动转换为长格式,也就是说 __x
会转换为._T__x
这种形式。所谓私有变量,希望外界不能随便访问,只能类中可以访问,所以t.__x
是违法的,但是python提供一种访问机制,就是t._T__x
,且这个出现在t.__dict__
当中,说明在__init__
方法中定义的属性是实例自定义属性。
顺便提下其他两种形式:
以单划线开头的,指定这个属性是私有的,并且不可以被import导入,也就是说当这个类被import后,不可以调用这个属性
前后都有双下划线,是系统自带变量/方法名
回到正事
>>>t._T__x3>>>t.x>4
第一个比较好理解,关于属性查找策略之前在我set和get方法那篇文章详细讲过,父类中没有_T__x
这个属性,连__x
这个属性都没有(是因为__init__
方法中的属性,类不可以直接方法,必须要定义对应的实例).父类中没查到,就直接在自己的t.__dict__
中查找,结果就找到了,OK,返回对应的value,就是3.
第二个当访问t.x
的时候,先去访问父类的T.__dict__
,之前讲过,只有x是数据描述符的时候,才能去返回__get__
方法的结果,可以看到T的属性中有这x,这里注意了,'x': <property object at 0x7f98642574c8>
这个property 可以看成是一个特殊类型的描述符,与传统的数据描述符相比,最大的不同就是: 传统数据描述符必须要包含__set__
__get__
方法,缺一不可,但是property就不同 property(fget=None, fset=None, fdel=None, doc=None)
四个参数可以可无,没有就None
所以访问t.x
的时候,父类中有x属性,发现是一个property的描述符,且第一个参数是get_x, 就类似于数据描述符中转到__set__
方法一样,转到get_x
中得到属性,发现返回值是self.__x+1
, 所以最后返回的是4.
如果尝试给t.x赋值的时候,会发生什么情况呢?
>>> t.x=100Traceback (most recent call last): File "<stdin>", line 1, in <module>AttributeError: can't set attribute
会出错,原因就是property函数第二个参数为空。
同时存在fget, fset 参数的 property()
class Hidex(object): def __init__(self,x): self.x=x+1 self.y=2 def get_x(self): return self.__y def set_x(self,y): self.__y=y+3 y=property(get_x,set_x)
查看一下
>>>t = Hidex(20) >>> t.__dict__{'x': 21, '_Hidex__y': 5}
当去声明一个实例t
的时候,__init__
方法和 __set__
方法都可以影响实例的自定义属性
其实我们发现:
>>> Hidex.__dict__dict_proxy({'set_x': <function set_x at 0x7f9cd2e8a6e0>, '__module__': 'property1', 'get_x': <function get_x at 0x7f9cd2e8a668>, '__dict__': <attribute '__dict__' of 'Hidex' objects>, 'y': <property object at 0x7f9cd2e7e4c8>, '__weakref__': <attribute '__weakref__' of 'Hidex' objects>, '__doc__': None, '__init__': <function __init__ at 0x7f9cd2e8a5f0>})
这时候已经发现y已经是一个描述符了,当在__init__
方法中对y赋值后,发现y是一个数据描述符,2给y只是一个过渡,2作为value 传输到 set_x
中,还会经过一个伪set,再添加到实例的自定义属性中去,
我们可以对t.y
进行赋值
>>> t.y=10>>> t.__dict__{'x': 21, '_Hidex__y': 13}>>> Hidex.__dict__dict_proxy({'set_x': <function set_x at 0x7f9cd2e8a6e0>, '__module__': 'property1', 'get_x': <function get_x at 0x7f9cd2e8a668>, '__dict__': <attribute '__dict__' of 'Hidex' objects>, 'y': <property object at 0x7f9cd2e7e4c8>, '__weakref__': <attribute '__weakref__' of 'Hidex' objects>, '__doc__': None, '__init__': <function __init__ at 0x7f9cd2e8a5f0>})>>> t.y13
赋值的时候,就会调用set_x
, 然后把t的属性_Hidex__y
改为13.
分析下下面的代码:
class Hidex(object): def __init__(self,x): self.x=x+1 self.y=2 def get_x(self): return self.__y def set_x(self,z): self.__y=z+3 z=6 z=property(get_x,set_x)
比如声明 t = Hidex(20)
,可以进行 t.z
的操作吗? 可以进行 t.z=30
的操作吗?
>>> t=Hidex(20)>>> t.__dict__{'y': 2, 'x': 21}>>> t.zTraceback (most recent call last): File "<stdin>", line 1, in <module> File "property1.py", line 6, in get_x return self.__yAttributeError: 'Hidex' object has no attribute '_Hidex__y'>>> t.z=20>>> t.__dict__{'y': 2, 'x': 21, '_Hidex__y': 23}>>> t.z23
为什么会出现上面的结果呢?
当声明一个实例t的时候,先进行初始化,声明了x,y 。当对t.z进行赋值的时候,根据赋值的策略,赋值首先是去父类中找这个属性. 恰好,发现了z 是一个property内建函数的实例,就会去调用里面的fset方法,也就是会产生个__y 的属性。
- Python中Property内建函数深入理解
- python中property函数的理解
- [Python]属性和property内建函数
- iOS 深入理解 @property
- Python中@property的粗略理解
- Python中常用的内建函数
- Python中map()内建函数浅析
- python中常用的内建函数
- Python中有用的内建函数
- python中几个内建函数
- python中实用的内建函数
- python中主要内建函数
- python中yield深入理解
- python @property理解
- Python 内建函数
- Python内建函数
- Python内建函数
- Python 内建函数
- 电脑开机需要按回车键才进入系统
- Android设计模式之MVC模式(一)
- 为什么每个程序员都应该学习使用命令行
- java Struts+Hibernate报价管理系统源代码下载
- 缺公开,为什么
- Python中Property内建函数深入理解
- 剑指offer系列之22:二叉搜索树的后序遍历
- Activity与Fragment 的生命周期对比
- Windows 常用命令
- Closeable 关闭流的简单工具
- 20160412 C/C++, C#常用开发工具大全
- Ubuntu关机重启
- 分享一个链接
- nodejs包 node-uuid(生成唯一id,标识单个记录)