社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

Python中的 @property特性

Python程序员 • 7 年前 • 648 次点击  


你将了解Python中的 @property特性, 以pythonic的方式使用getter和setter。


目录表


  • 从一个例子开始

  • 使用 Getter 和 Setter

  • @property的力量

  • 深入理解Property


Python有一个很棒的概念,叫做property,它使面向对象的程序员的生活更加简单。


在定义和研究@property是什么之前,让我们先直观感受下为什么首先应该使用它。


从一个例子开始


我们假设你决定创建一个可以以摄氏度存储温度的类[1],它还将实现一个将温度转换为华氏度的方法。一种方法是像下面这样做。



我们可以使用这个类创建对象,并按照我们的意愿操作其属性temperature。你可以在Python shell上试试这些操作。


在转换成华氏温度时,由于浮点运算错误(请在Python解释器中尝试1.1 + 2.2),小数点多了一位。


当我们赋值或检索任何对象属性像temperature时,如上面所示,Python都会在该对象的__dict__字典中搜索它。


因此, man.temperature在内部会变成 man.__dict__['temperature']


现在,让我们进一步假设我们的类在客户中很受欢迎,他们开始在自己的程序中使用它。他们对这个对象做了各种各样的赋值操作。


有一天,一个值得信赖的客户来找我们,建议温度不能低于-273摄氏度(热力学专业的学生可能会说实际上是-273.15摄氏度),也被称为绝对零度。他还要求我们实现这个值约束。作为一家追求客户满意的公司,我们很高兴地采纳了这个建议,并发布了1.01版本(对现有的类进行升级)。


使用Getter和Setter


上述对值进行约束的一个明显解决方案是隐藏属性temperature(使其私有)并定义新的 getter 和 setter 接口来操作它。可以按照下面这样做。



从上面可以看出,我们定义了get_temperature()set_temperature()两个新方法,并且用 _temperature 替换了temperature。在Python中,开头的下划线 (_) 用于表示私有变量。



这次更新成功地实现了新的限制。我们没法再将温度设置在-273度以下。


请注意,Python中不存在私有变量,但还是有一些简单的准则可以遵循。Python语言本身并不会做限制。


但这并不是什么大问题。上述更新的一个大问题是,所有在其程序中实现我们前面的类的客户都必须修改他们的代码,将obj.temperature修改为 obj.get_temperature(),并且将像 obj.temperature = val 的所有赋值语句修改为obj.set_temperature(val)


这种重构可能会给客户带来数十多万行代码的麻烦。


总之,我们的新更新不向后兼容。这时property就派上用场了。


@property的力量


处理上述问题的Pythonic的方法是使用property。以下是我们如何实现它。



然后,在shell中运行以下代码并注意观察。



我们在 get_temperature()set_temperature() 中添加了一个 print() 函数,来清楚地观察它们是否正在执行。


代码的最后一行创建了一个property对象 temperature。简单地说,property将一些代码( get_temperature set_temperature )附加到成员属性访问中( temperature )。


任何检索 temperature 值的代码都将自动调用 get_temperature(),而不是使用字典(__dict__)进行查找。类似地,任何对temperature 赋值的代码都会自动调用 set_temperature()。这是Python中一个很酷的特性。


我们可以看到上面的 set_temperature() 即使在创建对象时也被调用。


你能猜到这是为什么吗?


原因是在创建对象时, __init__() 方法被调用。这个方法有 self.temperature = temperature 这行代码,所以赋值时会自动调用set_temperature()



类似地,任何访问,比如 c.temperature,都会自动调用 get_temperature()。这就是property的作用。这里有更多的几个例子。



通过使用 property,可以看到,我们修改了类并实现了对值的约束,而不需要对客户代码进行任何更改。因此,我们的实现是向后兼容的,皆大欢喜。


最后请注意,实际的温度值存储在私有变量 _temperature中。属性 temperature是一个property对象,它为这个私有变量提供接口。


深入理解 Property


在Python中,property()是一个内置函数,用于创建和返回一个property对象。这个函数的签名是:



其中,fget 是获取属性值的函数,fset 是设置属性值的函数,fdel 是删除属性的函数,doc 是字符串(像注释一样)。从上述实现中可以看出,这些函数参数是可选的。因此,可以按照以下方式创建property对象。



property对象有三个方法,getter()setter()deleter(),用于后续指定 fgetfsetfdel。这意味着本行代码

可以分解为

这两段代码是等价的。


熟悉Python中的装饰器[2]的程序员可能会意识到,上面的构造可以实现为装饰器。


我们可以继续,不去定义 get_temperature set_temperature名称,因为它们是不必要的,并且会污染类命名空间。为此,我们在定义 gettersetter 函数时重用了名称 temperature。这就是它实现的方式。



上述实现是既简单又推荐使用的创建property的方法。当你在Python中寻找property时,你很可能会遇到这些类型的构造。


好了,今天就到这里。


相关链接:

[1]——https://www.programiz.com/python-programming/class 

[2]——https://www.programiz.com/python-programming/decorator



英文原文:https://www.programiz.com/python-programming/property  
 译者:野生大熊猫  



今天看啥 - 高品质阅读平台
本文地址:http://www.jintiankansha.me/t/8E7qFFI1bN
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/29056