Why does a class have the attributes of its metaclass?
我有一个像这样的超类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | class UpperMeta(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(UpperMeta, cls).__new__(cls, clsname, bases, uppercase_attr) def echo(cls): return 'echo' class B(object): __metaclass__ = UpperMeta assert hasattr(B, 'echo') assert B.echo() == 'echo' assert not issubclass(B, UpperMeta) |
我的问题是:
why class B have method of echo, B is not subclass of UpperMeta, it
should not have echo attr?
号
如果您看到什么是Python中的元类?或者定制类创建,您会看到(引用自python文档)
if
__metaclass__ is defined then the callable assigned to it will be
called instead of type().
号
埃多克斯1〔14〕
is essentially a dynamic form of the class statement. The name string
is the class name and becomes the__name__ attribute; the bases
tuple itemizes the base classes and becomes the__bases__ attribute;
and the dict dictionary is the namespace containing definitions for
class body and becomes the__dict__ attribute. For example, the
following two statements create identical type objects:
1
2
3
4 >>> class X(object):
... a = 1
...
>>> X = type('X', (object,), dict(a=1))
号
这就是"就像"类扩展。这也可以回答
What attribute class get from metaclass?
号
几乎所有的事情。
请注意:
If you wonder whether you need them, you don't (the people who
actually need them know with certainty that they need them, and don't
need an explanation about why).
号
但在@sebastian发布的视频中,他说
Q: Can you have too much of [metaprogramming]
A: No
号
所以他认为学习很重要。
因此,
1 2 3 | >>> 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__'] |
在这里:
1 2 | >>> print dir(B.__class__) ['__abstractmethods__', '__base__', ..., 'echo', 'mro'] |
号
从文档中:
The default behavior for attribute access is to get, set, or delete
the attribute from an object’s dictionary. For instance, a.x has a
lookup chain starting with a.dict['x'], then
type(a).dict['x'], and continuing through the base classes of
type(a) excluding metaclasses.
号
最后,这有点令人困惑"…排除元类….",这实际上意味着类型(A)的元类,因此,如果元类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | 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元编程。你只有前80分钟左右。