簡體   English   中英

Python結合了setattr和getattr

[英]Python combining setattr and getattr

我想動態更新類的屬性,但似乎setattr和getattr的組合不起作用,因為我想使用它。

這是我的主要課程:

class Container(object):
    def __init__(self):
        pass
container = Container()
attributes = ['a', 'b', 'c', 'd']
values = [[1, 2, 3, 4, 5], [True, False], ['red', 'blue', 'green'], [0, 1, -1, -5, 99]]

請注意,出於該示例的目的,我明確地構造了屬性列表及其各自的值。 但是,在這段代碼的實際應用中,我事先並不知道。 他們的號碼,名字或價值觀都沒有。 這需要動態地執行此操作。

這是代碼的其余部分:

for key, value in zip(attributes, values):
    setattr(container, key, [])
    for val in value:
        setattr(container, key, getattr(container, key).append(val))

當我運行代碼時,這部分不起作用。 我可以將getattr部分保存在tmp變量中,然后在調用setattr之前調用列表的append方法,但我想在可能的情況下壓縮它。

任何人都可以解釋為什么這不起作用? 我有什么選擇?

謝謝你的幫助

您將就地附加到列表中。 像所有就地變異函數一樣, .append()返回None ,所以你的最后一行:

setattr(container, key, getattr(container, key).append(val))

最終評估為:

setattr(container, key, None)

只需在課程上設置列表的副本:

for key, value in zip(attributes, values):
    setattr(container, key, values[:])

其中[:]通過以簡寫符號從0切換到len(values)而不需要循環來創建values的副本。

如果您只想創建一個提供鍵和值作為屬性的對象(就像dict還具有屬性訪問而不是項訪問權限),您還可以使用:

class Container(object):
    def __init__(self, names, values):
        self.__dict__.update(zip(names, values))

然后運行:

Container(attributes, values)

這消除了在循環中調用setattr()的需要。

如果您可以觀察每個步驟的進度,它可能會幫助您了解正在發生的事情:

class Container(object):
    def __init__(self):
        pass
    def __str__(self):
        return '%s(%s)' % (self.__class__.__name__,
            ', '.join(['%s = %s' % (attr, getattr(self, attr))
                for attr in self.__dict__]))

現在你可以print container 如果你在嵌套循環中執行此操作,您將看到在第一次嘗試setattr您已經破壞了存儲在container.a的原始列表(如Martijn所說):

for key, value in zip(attributes, values):
    setattr(container, key, [])
    for val in value:
        print 'before:', container
        setattr(container, key, getattr(container, key).append(val))
        print 'after:', container

before: Container(a = [])
after: Container(a = None)
before: Container(a = None)
Traceback (most recent call last): ...

這樣做的“最佳”方式顯然取決於真正的問題 - 考慮到Martijn的版本非常合適的縮小問題,但是在創建一些初始container實例之后的某個時刻,你可能需要追加一個項目,或者擴展多個項目。 。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM