[英]python dynamically set non-instance class attributes
我正在嘗試動態添加類屬性,而不是在實例級別。 例如,我可以手動執行以下操作:
class Foo(object):
a = 1
b = 2
c = 3
我希望能夠處理:
class Foo(object):
dct = {'a' : 1, 'b' : 2, 'c' : 3}
for key, val in dct.items():
<update the Foo namespace here>
我希望能夠做到這一點,而無需從類外部調用類(因此它是可移植的),或者沒有其他類/裝飾器。 這可能嗎?
從示例代碼來看,您想在創建類的同時執行此操作。 在這種情況下,假設您使用的是CPython,則可以使用locals()
。
class Foo(object):
locals().update(a=1, b=2, c=3)
之所以起作用,是因為在定義類時, locals()
引用了類名稱空間。 它是特定於實現的行為,可能無法在更高版本的Python或替代實現中使用。
下面顯示了一個使用類工廠的污穢程度較低的版本。 基本思想是將字典通過type()
構造函數轉換為類,然后將其用作新類的基類。 為了方便用最少的語法定義屬性,我使用了**
約定來接受屬性。
def dicty(*bases, **attrs):
if not bases:
bases = (object,)
return type("<from dict>", bases, attrs)
class Foo(dicty(a=1, b=2, c=3)):
pass
# if you already have the dict, use unpacking
dct = dict(a=1, b=2, c=3)
class Foo(dicty(**dct)):
pass
這實際上只是您自己調用type()
語法糖。 可以正常工作,例如:
class Foo(type("<none>", (object,), dict(a=1, b=2, c=3))):
pass
你的意思是這樣的:
def update(obj, dct):
for key, val in dct.items():
obj.setattr(key, val)
那你去吧
update(Foo, {'a': 1, 'b': 2, 'c': 3})
這行得通,因為類也是對象;)
如果要將所有內容移入該類,請嘗試以下操作:
class Foo(object):
__metaclass__ = lambda t, p, a: return type(t, p, a['dct'])
dct = {'a': 1, 'b': 2, 'c': 3}
這將創建一個新類,其成員位於dct
,但其他所有屬性均不存在- 因此 ,您想要更改最后一個參數的type
以包括所需的內容。 我在這里發現了如何執行此操作: Python中的元類是什么?
可接受的答案是一個不錯的方法。 但是,不利的一面是,您最終在MRO繼承鏈中獲得了一個額外的父對象,這並不是真正必要的,甚至可能會造成混淆:
>>> Foo.__mro__
(<class '__main__.Foo'>, <class '__main__.<from dict>'>, <class 'object'>)
另一種方法是使用裝飾器。 像這樣:
def dicty(**attrs):
def decorator(cls):
vars(cls).update(**attrs)
return cls
return decorator
@dicty(**some_class_attr_namespace)
class Foo():
pass
這樣,您可以避免繼承鏈中的其他對象。 @decorator
語法只是一個漂亮的說法:
Foo = dicty(a=1, b=2, c=3)(Foo)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.