http://blog.csdn.net/pipisorry/article/details/50708616

Python 中的 property 属性

Python中有个很赞的概念,叫做property,它使得面向对象的编程更加简单。

property使用实例

假设有天你决定创建一个类,用来存储摄氏温度。当然这个类也需要实现一个将摄氏温度转换为华氏温度的方法。一种实现的方式如下:

class Celsius:

    def __init__(self, temperature = 0):

        self.temperature = temperature

    def to_fahrenheit(self):

        return (self.temperature * 1.8) + 32

我们可以用这个类产生一个对象,然后按照我们期望的方式改变该对象的温度属性:

>>> # create new object

>>> man = Celsius()

>>> # set temperature

>>> man.temperature = 37

>>> # get temperature

>>> man.temperature

>>> # get degrees Fahrenheit

>>> man.to_fahrenheit()

98.60000000000001

赋值或获取任何对象的属性

每当我们赋值或获取任何对象的属性时,例如上面展示的温度,Python都会从对象的__dict__字典中搜索它。

>>> man.__dict__

{'temperature': 37}

因此,man.temperature在其内部就变成了man.__dict__['temperature']

实例修改:建议温度不能低于-273摄氏度

现在,让我们进一步假设我们的类在客户中很受欢迎,他们开始在其程序中使用这个类。他们对该类生成的对象做了各种操作。有一天,一个受信任的客户来找我们,建议温度不能低于-273摄氏度。

使用Getters和Setters

对于上边的约束,一个很容易想到的解决方案是隐藏其温度属性(使其私有化),并且定义新的用于操作温度属性的getter和setter接口。

我们定义了两个新方法get_temperature()和set_temperature(),此外属性temperature也被替换为了_temperature。

class Celsius:

    def __init__(self, temperature = 0):

        self.set_temperature(temperature)

    def to_fahrenheit(self):

        return (self.get_temperature() * 1.8) + 32

    # new update

    def get_temperature(self):

        return self._temperature

    def set_temperature(self, value):

        if value < -273:

            raise ValueError("Temperature below -273 is not possible")

        self._temperature = value

问题:

1. 最前边的下划线(_)用于指示Python中的私有变量。但是Python中实际上是没有私有变量的。有一些简单的被遵循的规范。Python本身不会应用任何限制。

>>> c._temperature = -300

>>> c.get_temperature()

-300

2. 先前类的客户都必须更改他们的代码

上述更新的最大问题是,所有在他们的程序中使用了我们先前类的客户都必须更改他们的代码:obj.temperature改为obj.get_temperature(),所有的赋值语句也必须更改。更新是不向后兼容地。

Property的使用

对于上边的问题,Python式的解决方式是使用property。

class Celsius:

    def __init__(self, temperature = 0):

        self.temperature = temperature

 

    def to_fahrenheit(self):

        return (self.temperature * 1.8) + 32

 

    def get_temperature(self):

        print("Getting value")

        return self._temperature

 

    def set_temperature(self, value):

        if value < -273:

            raise ValueError("Temperature below -273 is not possible")

        print("Setting value")

        self._temperature = value

 

    temperature = property(get_temperature,set_temperature)

我们在get_temperature()和set_temperature()的内部增加了一个print()函数,用来清楚地观察它们是否正在执行。

代码的最后一行,创建了一个property对象temperature。简单地说,property将一些代码(get_temperature和set_temperature)附加到成员属性(temperature)的访问入口。任何获取temperature值的代码都会自动调用get_temperature(),而不是去字典表(__dict__)中进行查找。

>>> c = Celsius()

Setting value

从上边的代码中我们可以看到,即使当我们创建一个对象时,__init__()方法被调用,有一行代码self.temperature = temperature。这个任务会自动调用set_temperature()方法。

>>> c.temperature

Getting value

同样的,对于属性的任何访问,例如c.temperature,也会自动调用get_temperature()方法。

>>> c.temperature = 37

Setting value

 

>>> c.to_fahrenheit()

Getting value

98.60000000000001

我们可以看到,通过使用property,我们在不需要客户代码做任何修改的情况下,修改了我们的类,并实现了值约束。因此我们的实现是向后兼容的。

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

深入挖掘property

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

property(fget=None, fset=None, fdel=None, doc=None)

这里,fget是一个获取属性值的函数,fset是一个设置属性值的函数,fdel是一个删除属性的函数,doc是一个字符串(类似于注释)。

Property对象有三个方法

getter(), setter()和delete(),用来在对象创建后设置fget,fset和fdel。

temperature = property(get_temperature,set_temperature)可以被分解为:

# make empty property

temperature = property()

# assign fget

temperature = temperature.getter(get_temperature)

# assign fset

temperature = temperature.setter(set_temperature)

它们之间是相互等价的。

作为decorator实现

熟悉Python中装饰器decorator的程序员能够认识到上述结构可以作为decorator实现。

我们可以更进一步,不去定义名字get_temperature和set_temperature,因为他们不是必须的,并且污染类的命名空间。

为此,我们在定义getter函数和setter函数时重用名字temperature。

class Celsius:

    def __init__(self, temperature = 0):

        self._temperature = temperature



    def to_fahrenheit(self):

        return (self.temperature * 1.8) + 32

 

    @property

    def temperature(self):

        print("Getting value")

        return self._temperature

 

    @temperature.setter

    def temperature(self, value):

        if value < -273:

            raise ValueError("Temperature below -273 is not possible")

        print("Setting value")

        self._temperature = value

上边的两种生成property的实现方式,都很简单,推荐使用。

[Python 中的 property 属性]

from:http://blog.csdn.net/pipisorry/article/details/50708616

ref: python类实例计数最优方法

python类:属性的更多相关文章

  1. python 类属性与方法

    Python 类属性与方法 标签(空格分隔): Python Python的访问限制 Python支持面向对象,其对属性的权限控制通过属性名来实现,如果一个属性有双下划线开头(__),该属性就无法被外 ...

  2. Python类属性访问的魔法方法

    Python类属性访问的魔法方法: 1. __getattr__(self, name)- 定义当用户试图获取一个不存在的属性时的行为 2. __getattribute__(self, name)- ...

  3. Python类属性,实例属性

    1.Python类数据属性:定义在类里面但在函数外面的变量,它们都是静态的. #一段很简单的代码,但反应了很多 >>> class A(): a=1 #一个类里面有个属性a > ...

  4. Python类属性详解

    在python开发中,我们常常用到python的类,今天就通过实例和大家扒一扒类的属性,一起来看看吧. 类属性 1.类定义后就存在,而且不需要实例化 2.类属性使得相同类的不同实例共同持有相同变量 类 ...

  5. python 类属性和实例属性

    class AAA(): aaa = 10 # 情形1 obj1 = AAA() obj2 = AAA() print obj1.aaa, obj2.aaa, AAA.aaa # 情形2 obj1.a ...

  6. python 类属性、对象属性

    类的普通属性: dir(Myclass), 返回一个key列表: Myclass.__dir__,返回一个字典: 1.类的数据属性: 2.类的方法: 类的特殊属性: 1.Myclass.__name_ ...

  7. python类属性用法总结

    属性的定义:python中的属性其实是普通方法的衍生. 操作类属性有三种方法: 1.使用@property装饰器操作类属性. 2.使用类或实例直接操作类属性(例如:obj.name,obj.age=1 ...

  8. python类属性和类方法(类的结构、实例属性、静态方法)

    类属性和类方法 目标 类的结构 类属性和实例属性 类方法和静态方法 01. 类的结构 1.1 术语 —— 实例 使用面相对象开发,第 1 步 是设计 类 使用 类名() 创建对象,创建对象 的动作有两 ...

  9. python 类属性 、实例属性,可变数据结构作为类属性需要注意的地方

    1.一些经典的python错误不去阅读和不重视,就会把错误的做法带入到实际项目中来,甚至造成难以排查问题. 2.有一个大笨猪,按java写观察者模式,java写得是直接在类名下声明一个实例属性(不加s ...

  10. 关于Python类属性与实例属性的讨论

    标题名字有点长. 之所以想写这个文章是因为碰巧看到网上一篇关于Pyhon中类属性及实例属性区别的帖子.因为我之前也被这个问题困扰过,今天碰巧看到了这篇帖子,发现帖子的作者只是描述了现象,然后对原因的解 ...

随机推荐

  1. C语言程序设计第二次作业—————顺序结构改

    1.输出带框文字:在屏幕上输出以下3行信息. ************* Welcome ************* 源程序 #include <stido.h> int mian() { ...

  2. [TensorFlow 团队] TensorFlow 数据集和估算器介绍

    发布人:TensorFlow 团队 原文链接:http://developers.googleblog.cn/2017/09/tensorflow.html TensorFlow 1.3 引入了两个重 ...

  3. C#之Action和Func的用法

    以前我都是通过定义一个delegate来写委托的,但是最近看一些外国人写的源码都是用action和func方式来写,当时感觉对这很陌生所以看起源码也觉得陌生,所以我就花费时间来学习下这两种方式,然后发 ...

  4. SpringBoot 中 get/post 请求处理方式,以及requestboy为Json时的处理

    GET.POST方式提时, 根据request header Content-Type的值来判断: application/x-www-form-urlencoded, 可选(即非必须,因为这种情况的 ...

  5. Java锁机制了解一下

    前言 回顾前面: 多线程三分钟就可以入个门了! Thread源码剖析 多线程基础必要知识点!看了学习多线程事半功倍 只有光头才能变强! 本文章主要讲的是Java多线程加锁机制,有两种: Synchro ...

  6. python2.7入门---内置函数

        内置函数     abs() divmod() input() open() staticmethod() all() enumerate() int() ord() str() any() ...

  7. centos7.2中文乱码解决办法

    centos7.2 中文乱码解决办法 1.查看安装中文包: 查看系统是否安装中文语言包 (列出所有可用的公共语言环境的名称,包含有zh_CN) # locale -a |grep "zh_C ...

  8. ActiveMQ消息传递的两种方式

    1.什么是ActiveMQ? ActiveMQ是apache提供的开源的,实现消息传递的一个中间插件,可以和spring整合,是目前最流行的开源消息总线,ActiveMQ是一个完全支持JMS1.1和J ...

  9. Bootstrap3 表格-紧缩表格

    通过添加 .table-condensed 类可以让表格更加紧凑,单元格中的内补(padding)均会减半. <table class="table table-condensed&q ...

  10. C实战:项目构建Make,Automake,CMake

    C实战:项目构建Make,Automake,CMake 在本系列文章<C实战:强大的程序调试工具GDB>中我们简要学习了流行的调试工具GDB的使用方法.本文继续"C实战" ...