2011-09-10 71 views

回答

116

属性是一种特殊的属性。基本上,当遇到的Python以下代码:

spam = SomeObject() 
print(spam.eggs) 

它查找eggsspam,然后检查eggs,看它是否具有__get____set__,或者__delete__方法  — 如果是这样,它是一个属性。如果的属性,而不是只返回eggs对象(因为它会为任何其他属性),它会调用__get__方法(因为我们在做查询),并返回无论该方法返回。

更多有关Python's data model and descriptors

+8

整个集合的最佳答案 - 至少因为它提供了关于Python本身如何在后端处理这些问题的具体细节。 +1。 :) –

17

总体上看方面的属性和属性是一样的。但是,Python中有一个属性装饰器,它提供getter/setter访问属性(或其他数据)的属性。

class MyObject(object): 
    # This is a normal attribute 
    foo = 1 

    @property 
    def bar(self): 
     return self.foo 

    @bar.setter 
    def bar(self, value): 
     self.foo = value 


obj = MyObject() 
assert obj.foo == 1 
assert obj.bar == obj.foo 
obj.bar = 2 
assert obj.foo == 2 
assert obj.bar == obj.foo 
+0

请你也提到这个代码的预期结果? –

+0

你是什么意思?这不是代码的底部吗? – six8

28

有一个属性,你可以完全控制他的getter,setter和deleter方法,你没有的东西(如果没有使用警告)和一个属性。

class A(object): 
    _x = 0 
    '''A._x is an attribute''' 

    @property 
    def x(self): 
     ''' 
     A.x is a property 
     This is the getter method 
     ''' 
     return self._x 

    @x.setter 
    def x(self, value): 
     """ 
     This is the setter method 
     where I can check it's not assigned a value < 0 
     """ 
     if value < 0: 
      raise ValueError("Must be >= 0") 
     self._x = value 

>>> a = A() 
>>> a._x = -1 
>>> a.x = -1 
Traceback (most recent call last): 
    File "ex.py", line 15, in <module> 
    a.x = -1 
    File "ex.py", line 9, in x 
    raise ValueError("Must be >= 0") 
ValueError: Must be >= 0 
+0

这个(“完全控制”)也可以通过“非属性”属性来完成,尽管没有这样简单的装饰器。 – 2011-09-10 21:41:39

+1

我所谓的警告... – neurino

+3

我喜欢这个答案提供了一个现实和有用的例子。我觉得在这个网站上太多的答案不必要地解释了后端的工作方式,却没有说明用户应该如何与之交互。如果不明白为什么/何时使用某些功能,就不知道它是如何在幕后操作的。 – Tom

11

属性可以让你得到像您这样的设定值将正常的属性,但骨子里有一种被称为其转换为一个getter和setter你的方法。这只是一个方便,可以减少调用getter和setter的样板。

比方说,例如,你有这样的一些持有x和你需要的东西y坐标的一类。要设置他们,你可能想要做这样的事情:

myObj.x = 5 
myObj.y = 10 

这是很容易看,想想比写:

myObj.setX(5) 
myObj.setY(10) 

的问题是,如果有一天你的类变化,你需要用某个值来抵消你的x和y?现在您需要进入并更改您的类定义以及调用它的所有代码,这可能非常耗时且容易出错。该属性允许您使用前一种语法,同时为您提供后者更改的灵活性。

在Python中,你可以定义的getter,setter方法,并删除与物业功能的方法。如果你只是想要读取属性,也可以在你的方法上面添加@property装饰器。

http://docs.python.org/library/functions.html#property

1

我学到德·克莱因的site 2倍的差异,总结:

1.房产是做数据封装更方便的方法。

例如:如果你有对象的公共属性lenght,以后,你的项目需要你来封装它,我。E:将其更改为私人和提供getter和setter =>你必须改变你的许多以前写过的代码:

#Old codes 
obj1.length=obj1.length+obj2.length 
#New codes(Using private attibutes and getter and setter) 
obj1.set_lenght(obj1.get_length()+obj2.get_length()) #=> this is ugly 

如果使用@property和@ lenght.setter =>你不需要改变那些旧代码

2.一种属性可以封装多个属性

class Person: 
    def __init__(self, name, physic_health, mental_health): 
    self.name=name 
    self.__physic_health=physic_health #physic_health is real value in range [0, 5.0] 
    self.__mental_health=mental_health #mental_health is real value in range [0, 5.0] 
    @property 
    def condition(self): 
    health=self.__physic_health+self.__mental_health 
    if(health<5.0): 
     return "I feel bad!" 
    elif health<8.0: 
     return "I am ok!" 
    else: 
     return "Great!" 

在这个例子中,__physic_health__mental_health是私有和不能从出SID直接访问E,课外与他们互动的唯一方式就是throught财产condition

0

还有,我使用缓存或刷新数据,我们常常连接到类属性功能的一个无明显差异。举例来说,我需要这样的价值被缓存读取文件一次,并且保持分配给该属性的内容:

class Misc(): 
     def __init__(self): 
      self.test = self.test_func() 

     def test_func(self): 
      print 'func running' 
      return 'func value' 

cl = Misc() 
print cl.test 
print cl.test 

输出:

func running 
func value 
func value 

我们访问的属性两次,但我们的函数被解雇了一次。更改上面的例子中使用属性将导致属性值,每次刷新你访问它:

class Misc(): 

    @property 
    def test(self): 
     print 'func running' 
     return 'func value' 

cl = Misc() 
print cl.test 
print cl.test 

输出:

func running 
func value 
func running 
func value 
相关问题