我正在尝试使用PEP 3115中描述的“有序类” (即,可以按照声明的顺序访问其成员的类)。那里给出的实现是
# The custom dictionary
class member_table(dict):
def __init__(self):
self.member_names = []
def __setitem__(self, key, value):
# if the key is not already defined, add to the
# list of keys.
if key not in self:
self.member_names.append(key)
# Call superclass
dict.__setitem__(self, key, value)
# The metaclass
class OrderedClass(type):
# The prepare function
@classmethod
def __prepare__(metacls, name, bases): # No keywords in this case
return member_table()
# The metaclass invocation
def __new__(cls, name, bases, classdict):
# Note that we replace the classdict with a regular
# dict before passing it to the superclass, so that we
# don't continue to record member names after the class
# has been created.
result = type.__new__(cls, name, bases, dict(classdict))
result.member_names = classdict.member_names
return result
class MyClass(metaclass=OrderedClass):
# method1 goes in array element 0
def method1(self):
pass
# method2 goes in array element 1
def method2(self):
pass
有几件事我很困惑。__prepare__
首先,有一个原因classmethod
吗?该定义不使用metacls
- 这只是一个约定吗?
其次,当我尝试这段代码时,'__module__'
结果是MyClass.member_names
before 'method1'
and ,显然与声称是第一个元素'method2'
的注释相矛盾。'method1'
为什么这个特殊属性最终出现在列表中,而其他属性没有?是否还有其他可能让我感到惊讶(除了__doc__
该类是否有文档字符串,以及我明确定义的任何内容)?
最后,此实现不会member_names
从基类中检索 。如果我想实现这一点,以下更改是否有任何问题__prepare__
(除了它不检查重复项)?
@classmethod
def __prepare__(metacls, name, bases):
prep_dict = member_table()
for base in bases:
try:
prep_dict.member_names.extend(base.member_names)
except AttributeError:
pass
return prep_dict