簡體   English   中英

python動態設置非實例類屬性

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

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