2017-08-28 53 views
2

我有下面的類:如何獲得一個類的屬性,不知道他們的名字

class TestClass(object): 
def __init__(self, **kwargs): 
    for key, value in kwargs.items(): #items return list of dict 
     setattr(self, key, value) 

實施例一使用:

obj = MessageItem(**{"testkey1":"tval1", "tkey2":"tval2", "tkey3":"tval3"}) 

我如何可以遍歷這個結構不知道的名字屬性? Python的爲我們提供了內置方法__getattribute__,但我還需要知道所請求的屬性的名稱:

print(obj.__getattribute__("testkey1")) 
+3

你爲什麼要故意將自己置於這種情況下而不是將其存儲爲'dict'? –

+0

@JonClements Personaly,我不知道,我的領導者以這種方式規劃了這個,我必須實施:D –

+1

好吧,隨意告訴他們這不是好設計,它有點危險......人們將能夠破壞你已經使用過的名字,打破事情並在稍後調試將會非常糟糕。 –

回答

3

__dict__屬性保存你想要什麼。 類有它:

>>> class Foo: 
...  def __init__(self, x): 
...    self.x = x 
... 
>>> Foo.__dict__ 
mappingproxy({'__module__': '__main__', '__init__': <function Foo.__init__ at 
0x000001CC1821EEA0>, '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': 
<attribute '__weakref__' of 'Foo' objects>, '__doc__': None}) 

而且任何情況下都有它還有:

>>> f = Foo(2) 
>>> f.__dict__ 
{'x': 2} 

你應該通過vars內建函數訪問這個屬性。 致電vars(foo)將返回foo.__dict__。 看到這個相關的文章:Use __dict__ or vars()?

Documentation for vars

瓦爾([對象])

返回的__dict__屬性爲一個模塊,類,實例,或具有__dict__屬性的任何其他對象。

諸如模塊和實例的​​對象具有可更新的__dict__屬性;但是,其他對象可能對其屬性具有寫入限制(例如,類使用types.MappingProxyType來防止直接字典更新)。

沒有參數,vars()的行爲就像locals()。請注意,當地人字典僅對讀取有用,因爲字典忽略了對當地人 字典的更新。


另外,我想,寫您可能感興趣的一個裝飾。 這是一個類裝飾器,它爲它所裝飾的類添加initKwargs。 此外,它還包含該類的__init__方法,以便將它收到的kwargs字典附加到類'initKwargs屬性。

def class_wrapper(cls): 
    cls.initKwargs = [] 
    f = cls.__init__ 

    def wrapped_init(instance, **kwargs): 
     cls.initKwargs.append(kwargs) 
     return f(instance, **kwargs)    
    cls.__init__ = wrapped_init 

    return cls 

@class_wrapper 
class Foo: 
    def __init__(self, **kwargs): 
     for k, v in kwargs.items(): 
      setattr(self, k, v) 

示範:

>>> f1 = Foo() 
>>> f2 = Foo(a=1, b=2) 
>>> f3 = Foo(a=1, b=2, c=3, d=4) 
>>> Foo.initKwargs 
[{}, {'a': 1, 'b': 2}, {'a': 1, 'b': 2, 'c': 3, 'd': 4}] 

我發現這種方法更清潔,使用vars,因爲你知道你在訪問什麼,因爲你自己定義。 它給你更多的控制類的行爲。

+2

如果你打算建議,那麼建議使用'vars(f)' - 這裏幾乎不需要直接訪問'__dict__',它可能並不總是如預期的那樣。 –

+0

@JonClements考慮文檔中關於'vars'的說法,它與'__dict__'有什麼不同?我想我記得讀過'__dict__'不太好,但我不記得爲什麼...... –

+0

我不記得*正好*離開我的頭頂......但是變量(...) '會做正確的事情,而直接訪問'__dict__'可能會失敗。儘管我現在稍微懷疑自己...但是有些東西敲響了鐘聲:)除此之外 - 至少在代碼中沒有dunder方法訪問,在沒有必要的情況下總是很好。 –

相關問題