[英]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.