2011-09-10 94 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 
相關問題