這可能會也可能不會很聰明,但在技術上可以爲此使用元類。與Joran的方法不同,我使用一個屬性,以便保留完整的動態性質(即,如果在定義類後修改任何類的私人_PARAM_NAMES
列表,則其他派生類的相應PARAM_NAME
屬性反映該更改)。基於這個原因,我在基類上放了一個add_param
方法。
這裏假設Python 3,PARAM_NAMES
屬性返回set
以避免重複的項目。
class ParamNameBuilderMeta(type):
def __new__(mcl, name, bases, dct):
names = dct.get("PARAM_NAMES", [])
names = {names} if isinstance(names, str) else set(names)
dct["_PARAM_NAMES"] = names
dct["PARAM_NAMES"] = property(lambda s: type(s).PARAM_NAMES)
return super().__new__(mcl, name, bases, dct)
@property
def PARAM_NAMES(cls):
# collect unique list items ONLY from our classes in the MRO
return set().union(*(c._PARAM_NAMES for c in reversed(cls.__mro__)
if isinstance(c, ParamNameBuilderMeta)))
用法:
class ParamNameBuilderBase(metaclass=ParamNameBuilderMeta):
@classmethod
def add_param(self, param_name):
self._PARAM_NAMES.add(param_name)
class A(ParamNameBuilderBase):
PARAM_NAMES = 'blah1'
class B(A):
PARAM_NAMES = 'blah1', 'blah2'
class C(B):
pass
檢查,以確保它可以在兩個類和實例及其:
assert C.PARAM_NAMES == {'blah1', 'blah2'}
assert C().PARAM_NAMES == {'blah1', 'blah2'}
檢查,以確保它仍然是動態的:
C.add_param('blah3')
assert C.PARAM_NAMES == {'blah1', 'blah2', 'blah3'}
這種方式怎麼了? – 2015-03-03 00:15:18