class 对象 B 属于 type UpperMeta。
这导致UpperMeta 的所有类方法在类B 上都可用。该属性不在B 类上,而是从B 的类代理(B 是类,而不是B 的实例)
>>> print dir(B)
# General lack of echo()
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__metaclass__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
在这里:
>>> print dir(B.__class__)
['__abstractmethods__', '__base__', ..., 'echo', 'mro']
来自documentation:
属性访问的默认行为是获取、设置或删除
对象字典中的属性。例如, a.x 有一个
以 a.dict['x'] 开头的查找链,然后
type(a).dict['x'],并继续遍历
type(a) 不包括元类。
这有点令人困惑“...不包括元类..”,这实际上意味着类型(a)的元类,因此说如果你的元类UpperMeta有一个元类TopMeta 和TopMeta 定义sos(),不会被查找:
class TopMeta(type):
def __new__(cls, clsname, bases, dct):
uppercase_attr = {}
for name, val in dct.items():
if not name.startswith('__'):
uppercase_attr[name.upper()] = val
else:
uppercase_attr[name] = val
return super(TopMeta, cls).__new__(cls, clsname, bases, uppercase_attr)
def sos(cls):
return 'sos'
class UpperMeta(type):
__metaclass__ = TopMeta
def __new__(cls, clsname, bases, dct):
uppercase_attr = {}
for name, val in dct.items():
if not name.startswith('__'):
uppercase_attr[name.upper()] = val
else:
uppercase_attr[name] = val
return super(UpperMeta, cls).__new__(cls, clsname, bases, uppercase_attr)
class B(object):
__metaclass__ = UpperMeta
assert not hasattr(B, 'sos')
唯一正确解释元类的演讲:David Beazley - Python 3 Metaprogramming。你只有前 80 分钟左右。