python之property属性1

1.1.3 Property的作用对于上边的问题,Python式的解决方式是使用property。这里是我们已经实现了的一个版本:Python 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

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_temperatureset_temperature)附加到成员属性(temperature)的访问入口。任何获取temperature值的代码都会自动调用get_temperature(),而不是去字典表(__dict__)中进行查找。同样的,任何赋给temperature值的代码也会自动调用set_temperature()。这是Python中一个很酷的功能。我们实际演示一下。Python 

1

2

>>> c = Celsius()

Setting value

从上边的代码中我们可以看到,即使当我们创建一个对象时,set_temperature()也会被调用。你能猜到为什么吗?原因是,当一个对象被创建时,__init__()方法被调用。该方法有一行代码self.temperature = temperature。这个任务会自动调用set_temperature()方法。Python 

1

2

3

>>> c.temperature

Getting value

0

同样的,对于属性的任何访问,例如c.temperature,也会自动调用get_temperature()方法。这就是property所作的事情。这里有一些额外的实例。Python 

1

2

3

4

5

6

>>> c.temperature = 37

Setting value

 

>>> c.to_fahrenheit()

Getting value

98.60000000000001

我们可以看到,通过使用property,我们在不需要客户代码做任何修改的情况下,修改了我们的类,并实现了值约束。因此我们的实现是向后兼容的,这样的结果,大家都很高兴。最后需要注意的是,实际温度值存储在私有变量_temperature中。属性temperature是一个property对象,是用来为这个私有变量提供接口的。1.1.4 深入挖掘property在Python中,property()是一个内置函数,用于创建和返回一个property对象。该函数的签名为:Python 

1

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

这里,fget是一个获取属性值的函数,fset是一个设置属性值的函数,fdel是一个删除属性的函数,doc是一个字符串(类似于注释)。从函数实现上看,这些函数参数都是可选的。所以,可以按照如下的方式简单的创建一个property对象。Python 

1

2

>>> property()

<property object at 0x0000000003239B38>

Property对象有三个方法,getter(), setter()和delete(),用来在对象创建后设置fget,fset和fdel。这就意味着,这行代码:temperature = property(get_temperature,set_temperature)可以被分解为:Python 

1

2

3

4

5

6

# make empty property

temperature = property()

# assign fget

temperature = temperature.getter(get_temperature)

# assign fset

temperature = temperature.setter(set_temperature)

它们之间是相互等价的。熟悉Python中装饰器decorator的程序员能够认识到上述结构可以作为decorator实现。我们可以更进一步,不去定义名字get_temperature和set_temperature,因为他们不是必须的,并且污染类的命名空间。为此,我们在定义getter函数和setter函数时重用名字temperature。下边的代码展示如何实现它。Python 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

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时,你很可能会遇到这种类似的代码结构。

相关内容推荐