2010-01-23 53 views
13

考慮下面的類定義的Python:多個屬性,一個二傳手/吸氣

class of2010(object): 
    def __init__(self): 
     self._a = 1 
     self._b = 2 
     self._c = 3 

    def set_a(self,value): 
     print('setting a...') 
     self._a = value 
    def set_b(self,value): 
     print('setting b...') 
     self._b = value 
    def set_c(self,value): 
     print('setting c...') 
     self._c = value 
    a = property(fset=self.set_a) 
    b = property(fset=self.set_b) 
    c = property(fset=self.set_c) 

注意set_[a|b|c]()做同樣的事情。有沒有辦法做定義:

def set_magic(self,value): 
    print('setting <???>...') 
    self._??? = value 

一次使用它的A,B,C如下

a = property(fset=self.set_magic) 
b = property(fset=self.set_magic) 
c = property(fset=self.set_magic) 

回答

20
def attrsetter(attr): 
    def set_any(self, value): 
    setattr(self, attr, value) 
    return set_any 

a = property(fset=attrsetter('_a')) 
b = property(fset=attrsetter('_b')) 
c = property(fset=attrsetter('_c')) 
+0

它是財產(fset = ...),但否則我會使用類似的東西。 – olt 2010-01-23 15:20:29

+0

@olt:謝謝,修復。 – 2010-01-23 15:22:56

1

可能是你正在尋找 __setattr__(self, name, value)

看看here

2
class... 
def __setattr__(self, name, value): 
    print 'setting', name 
    self.__dict__[name] = value 

就是這樣。

+1

此建議已過時。根據https://docs.python.org/2/reference/datamodel.html#customizing-attribute-access,「對於新式類,而不是訪問實例字典,」__setattr__「應該調用基類方法相同的名稱,例如'object .__ setattr __(self,name,value)'。「請注意OP正在使用新式課程。 – 2014-04-02 21:17:47

5

我看到你的二傳手只是記錄一條消息,然後簡單地賦值 - 事實上,你接受的答案只是賦值。你是否使用這種模式,因爲它是一些其他語言的接受練習/傳統智慧,也許是名字以「J」開頭的語言?如果是這樣,那麼請了解到,Python化的方法來此相同的設計是簡單得多:

class Of2010(object): 
    def __init__(self): 
     self.a = 1 
     self.b = 2 
     self.c = 3 

沒有什麼也不做的制定者,沒有中間的函數調用只是分配一個值。 「你說的話? 「公開接觸成員變量?!!」那麼,是的其實。

從客戶端代碼的角度來看這些類。要使用你的類,客戶端創建一個對象,然後「一」使用指派屬性:

obj = Of2010() 
obj.a = 42 

值得注意的是,這是5襯墊類我上面貼的完全相同的代碼。

爲什麼J語言鼓勵更詳細的屬性風格?在未來需求發生變化時保留類接口。如果在某個時間點,對象的某個其他值必須隨着對a的任何更改而改變,那麼您必須實現屬性機制。可悲的是,J語言將屬性訪問機制的本質暴露給客戶端代碼,因此在將來某個時候引入屬性是一種侵入式重構任務,需要重建所有使用該類的客戶端和它的「a」屬性。

在Python中,情況並非如此。訪問對象的「a」屬性是在調用程序運行時確定的。由於直接訪問和屬性訪問都「看起來」相同,即使實際機制不同,您的Python類也會保留此接口。重要的是,就客戶代碼而言,它是相同的。

所以在Java中,一個引入該屬性的複雜性,從這個班的成立權(事實上,通過接受實踐的所有類),在關閉的機會,它可能會變得必要的某一天未來。使用Python,可以從實現可能工作的最簡單的事情開始,也就是直接訪問簡單的成員變量,在未來的時間裏留下複雜的方法,這些額外的東西實際上是必需的和有價值的。由於那一天可能永遠不會到來,所以這是讓你的代碼的第一個工作版本走出去的巨大跳躍。

+0

我希望在某個類的(某個實例)的某些成員被設置時發生一個動作。我想爲這些成員(我的例子:打印成員的名字)發生同樣的動作而不重複他們的setter。這是我需要制定者的原因。否則,正如你明智地表示的那樣。我不會使用它們,因爲它們在python中是不必要的 – bandana 2010-01-23 16:16:43

+0

如果它在每次調用時打印一個名稱都很簡單,那麼爲什麼不將它編碼到父節點__init __()中,該節點總是由每個實例調用? – 2014-03-25 22:07:35