python函数对象的属性_python:python对象属性及属性函数property()

python对象属性

Python一切皆对象(object),每个对象都可能有多个属性(attribute)。Python的属性有一套统一的管理方案。

属性的__dict__系统

对象的属性可能来自于其类定义,叫做类属性(class attribute)。类属性可能来自类定义自身,也可能根据类定义继承来的。一个对象的属性还可能是该对象实例定义的,叫做对象属性(object attribute)。

对象的属性储存在对象的__dict__属性中。__dict__为一个词典,键为属性名,对应的值为属性本身。

python自省和反射

自省表示给予你某种能力来进行像“手工类型检查”的工作,它也被称为反射。这个性质展示了某对象是如何在运行期取得自身信息的。如果传一个对象给你,你可以查出它有什么

能力,这样的功能不是很好吗?

如果 Python 不支持某种形式的自省功能,dir()和 type()内建函数,将很难正常工作。请密切关注这些调用,还有那些特殊属性,像__dict__,__name__及__doc__。

Python属性property

Python中有个很赞的概念,叫做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的实现方式,都很简单,推荐使用。

皮皮blog

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

class Celsius:

def __init__(self, temperature = 0):

self.temperature = temperature

def to_fahrenheit(self):

return (self.temperature * 1.8) + 32

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

>>> man = Celsius()

>>> man.temperature = 37

>>> man.temperature

>>> 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对象,是用来为这个私有变量提供接口的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值