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行信息. 将源代码输入编译器 运行程序发现错误 错误信息1: 错误原因:将stido.h拼写错误 改正方法:将stido.h改为stdio.h 错误信息 ...

  2. Java HttpClient伪造请求之简易封装满足HTTP以及HTTPS请求

    HttpClient简介 HTTP 协议可能是现在 Internet 上使用得最多.最重要的协议了,越来越多的 Java 应用程序需要直接通过 HTTP 协议来访问网络资源.虽然在 JDK 的 jav ...

  3. 混合式应用开发之Cordova+vue(1)

    一.Cordova创建应用 cordova create oneApp Cordova创建应用出错 Cordova安装时不能使用cnpm 应该使用npm,cnpm虽然快但是后期出的错绝对比这省下来的时 ...

  4. 用ECMAScript4 ( ActionScript3) 实现Unity的热更新 -- CustomYieldInstruction 自定义中断指令

    ActionScript3脚本引擎为了方便热更新逻辑开发,提供的从脚本继承Unity类库功能在一些情况下可以提供开发的便利. 这次来建立一个示例,演示一下如何在脚本中自定义协程中断指令 Unity中的 ...

  5. 预习视频day1

    课前预习 编译型和解释型语言优缺点 python2,pyhon3的宏观(大环境下)区别 python的种类 python编码规则 变量命名规范,常量 注释 1.编译型语言:将源码一次性转化为二进制代码 ...

  6. 详解BLE连接建立过程

    同一款手机,为什么跟某些设备可以连接成功,而跟另外一些设备又连接不成功?同一个设备,为什么跟某些手机可以建立连接,而跟另外一些手机又无法建立连接?同一个手机,同一个设备,为什么他们两者有时候连起来很快 ...

  7. Python列表函数&方法

    Python包含以下函数: 序号 函数 1 cmp(list1, list2)比较两个列表的元素 2 len(list)列表元素个数 3 max(list)返回列表元素最大值 4 min(list)返 ...

  8. mybatis常用配置

    前面两篇博客我们简单介绍了mybatis的使用,但是在mybatis的配置问题上我们只是使用了最基础的配置,本文我们就来说说其他一些常用的配置.如果小伙伴对mybatis尚不了解,可以先参考这两篇博客 ...

  9. 操作系统内核Hack:(一)实验环境搭建

    操作系统内核Hack:(一)实验环境搭建 三四年前,心血来潮,入手<Orange's:一个操作系统的实现>学习操作系统内核,还配套买了王爽的<汇编语言(第二版)>和<80 ...

  10. Github Atom开源文本代码编辑器- 由 Github 打造的下一代编程开发利器

    个人理解:Github 热度超凡的一个项目Atom,electron是整个atom的核心,对于electron可以理解成 electron =io.js + Chromium    通过 Electr ...