2013-10-06 31 views
4

要在類中創建屬性,只需執行self.property = value。我希望能夠讓這個類中的屬性完全依賴於一個參數。讓我們稱這個類爲Foo。在Foo類的Python非常動態的類屬性

情況下將採取的元組的列表:

l = [("first","foo"),("second","bar"),("anything","you get the point")] 
bar = Foo(l) 

現在我們分配給bar將具有以下屬性Foo類的實例:

bar.first 
#foo 
bar.second 
#bar 
bar.anything 
#you get the point 

這是甚至遠程可能?怎麼樣?

+3

看看['setattr'](http://docs.python.org/2/library/functions.html#setattr)。 – BrenBarn

+2

您可能還想查看['namedtuple'](http://docs.python.org/2/library/collections.html#collections.namedtuple)。 –

+0

setattr完美運作!謝謝。我會看看namedtuple –

回答

4

這些被稱爲屬性,而不是屬性。考慮到這一點,該方法setattr()變得更加明顯:

class Foo(object): 
    def __init__(self, l): 
     for k, v in l: 
      setattr(self, k, v) 

這需要每個鍵 - 值對中l並設置屬性k上的Fooself)的新實例v

使用你的例子:

l = [("first","foo"),("second","bar"),("anything","you get the point")] 
bar = Foo(l) 

print bar.first 
#foo 
print bar.second 
#bar 
print bar.anything 
#you get the point 
+1

'setattr(Foo ...'和'setattr(self ...')的區別是什麼? – TerryA

+0

我相信這是因爲self是每個具體的類,其中Foo是通用的,所以它會讓所有的Foo類都有。不知道,我只是猜測 –

+2

@Haidro:'self'爲當前*實例*設置屬性,而不是'class'。 – Johnsyweb

2

這樣的事情?

>>> class Foo: 
...  def __init__(self, mylist): 
...   for k, v in mylist: 
...    setattr(self, k, v) 
... 
>>> l = [("first","foo"),("second","bar"),("anything","you get the point")] 
>>> bar = Foo(l) 
>>> bar.first 
'foo' 
>>> bar.second 
'bar' 
>>> bar.anything 
'you get the point' 

使用setattr你可以通過在列表中,只是通過它遍歷做到這一點。

-1

SETATTR工作。

>>> class Foo: 
... def __init__(self,yahoo): 
...  for k,v in yahoo: 
...  setattr(self,k,v) 
... 
>>> l = [("first","foo"),("second","bar"),("anything","you get the point")] 
>>> bar = Foo(l) 
>>> print bar.first 
foo 
>>> print bar.second 
bar 
>>> print bar.anything 
you get the point 
3

有兩種方法可以做到這一點:

  • 使用setattr這樣。如果您只需要在構建對象時處理初始列表,那麼這種方法是可行的。

    class Foo: 
        def __init__(self, l): 
        for (a, b) in l: 
         setattr(self, a, b) 
    
  • 定義自定義__getattr__方法。您最好將屬性存儲在dict中以加快查找速度,但您也可以搜索原始列表。如果您稍後要修改列表並希望將其反映到對象的屬性中,這會更好。

    class Foo: 
        def __init__(self, l): 
        self.l = l 
        def __getattr__(self, name): 
        for a in self.l: 
         if a[0] == name: 
         return a[1] 
        return None 
    
+1

in'__getattr__'你需要有'self.l',而不是'l' –

+0

謝謝,更正。 –

5

我想另外一個答案,你可以使用使用type()的。這是完全不同的,以我現在的答案,所以我已經添加了不同的答案:

>>> bar = type('Foo',(), dict(l))() 
>>> bar.first 
'foo' 
>>> bar.second 
'bar' 
>>> bar.anything 
'you get the point' 

type()末返回,而不是一個實例,因此額外的()

+2

這是非常有創意和壓縮的... + 1 –

+0

This is cool 。昨天,我學會了用'Function'在javascript中做同樣的事情,今天我學會了用python做的SO:OSM。 – thefourtheye

+1

@thefourtheye:你甚至可以使用'types.FunctionType'實時構建函數。當然你冷杉t需要得到一個代碼對象(編譯一個,從另一個函數借用一個,手動生成字節碼,...)。通常情況下,有更好的方法可以在Python中做到這一點......但幾乎任何你能想到的都是可能的。 – abarnert