什么时候执行元类的 __prepare__ 方法,什么使用它的 return 值?
When is the __prepare__ method of a metaclass excuted and what uses its return value?
PEP 3115 有以下使用 metaclass 的 __prepare__
方法的示例(print
语句是我的):
# The custom dictionary
class member_table(dict):
def __init__(self):
self.member_names = []
def __setitem__(self, key, value):
print(f'in __setitem__{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
print('in __prepare__')
return member_table()
# The metaclass invocation
def __new__(cls, name, bases, classdict):
print('in __new__')
# 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
print('before MyClass')
class MyClass(metaclass=OrderedClass):
print('in MyClass 1')
# method1 goes in array element 0
def method1(self):
pass
print('in MyClass 2')
# method2 goes in array element 1
def method2(self):
pass
print('in MyClass 3')
运行 这个,打印这个:
before MyClass
in __prepare__
in __setitem__('__module__', '__main__')
in __setitem__('__qualname__', 'MyClass')
in MyClass 1
in __setitem__('method1', <function MyClass.method1 at 0x7fa70414da60>)
in MyClass 2
in __setitem__('method2', <function MyClass.method2 at 0x7fa70414daf0>)
in MyClass 3
in __new__
所以看起来当 MyClass
被执行时,执行首先进入 class 的 metaclass 的 __prepare__
方法 return s member_table()
(who/what 使用这个 return 值?),然后设置 class 的 __module__
和 __qualname__
,然后执行 class body,它设置 class 的方法(method1
和 method2
),然后 __new__
方法用 return 的值调用__prepare__
作为 classdict
参数值传递给 __new__
(who/what 正在传递这个值?)。
我试图在 thonny 的调试器中单步执行,但出现错误。我还尝试在 pythontutor.com 中逐步执行,但这不够精细。我 pdb'
编辑了它,但很难理解发生了什么。最后,我添加了一些 print
语句,这些语句出现在上面的代码中。
prepare()
的结果是传递给 __new__
的 namespace
参数。它是计算 class 主体的命名空间(参见 [1])。
因此在新创建的 class 中,您可以看到 MyClass.__module__
、MyClass.__qualname__
等值,因为它们是在 MyClass
的命名空间对象中分配的.
metaclasses 的大多数使用都不需要 prepare()
,而是使用普通的命名空间。
PEP 3115 有以下使用 metaclass 的 __prepare__
方法的示例(print
语句是我的):
# The custom dictionary
class member_table(dict):
def __init__(self):
self.member_names = []
def __setitem__(self, key, value):
print(f'in __setitem__{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
print('in __prepare__')
return member_table()
# The metaclass invocation
def __new__(cls, name, bases, classdict):
print('in __new__')
# 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
print('before MyClass')
class MyClass(metaclass=OrderedClass):
print('in MyClass 1')
# method1 goes in array element 0
def method1(self):
pass
print('in MyClass 2')
# method2 goes in array element 1
def method2(self):
pass
print('in MyClass 3')
运行 这个,打印这个:
before MyClass
in __prepare__
in __setitem__('__module__', '__main__')
in __setitem__('__qualname__', 'MyClass')
in MyClass 1
in __setitem__('method1', <function MyClass.method1 at 0x7fa70414da60>)
in MyClass 2
in __setitem__('method2', <function MyClass.method2 at 0x7fa70414daf0>)
in MyClass 3
in __new__
所以看起来当 MyClass
被执行时,执行首先进入 class 的 metaclass 的 __prepare__
方法 return s member_table()
(who/what 使用这个 return 值?),然后设置 class 的 __module__
和 __qualname__
,然后执行 class body,它设置 class 的方法(method1
和 method2
),然后 __new__
方法用 return 的值调用__prepare__
作为 classdict
参数值传递给 __new__
(who/what 正在传递这个值?)。
我试图在 thonny 的调试器中单步执行,但出现错误。我还尝试在 pythontutor.com 中逐步执行,但这不够精细。我 pdb'
编辑了它,但很难理解发生了什么。最后,我添加了一些 print
语句,这些语句出现在上面的代码中。
prepare()
的结果是传递给 __new__
的 namespace
参数。它是计算 class 主体的命名空间(参见 [1])。
因此在新创建的 class 中,您可以看到 MyClass.__module__
、MyClass.__qualname__
等值,因为它们是在 MyClass
的命名空间对象中分配的.
metaclasses 的大多数使用都不需要 prepare()
,而是使用普通的命名空间。