为啥一个类具有它的元类的属性?
Posted
技术标签:
【中文标题】为啥一个类具有它的元类的属性?【英文标题】:Why does a class have the attributes of its metaclass?为什么一个类具有它的元类的属性? 【发布时间】:2016-02-02 01:46:35 【问题描述】:我有一个这样的元类
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)
我的问题是:
-
为什么
B
类有echo
方法?如果B
不是UpperMeta
的子类,它不应该有echo
属性吗?
类从元类中获得哪些属性?
【问题讨论】:
【参考方案1】: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 分钟左右。
【讨论】:
【参考方案2】:为什么B类有echo的方法,B不是UpperMeta的子类,它 不应该有 echo attr 吗?
如果您查看 What is a metaclass in Python? 或 Customizing class creation,您会看到(引用自 python 文档)
如果定义了
__metaclass__
,那么分配给它的可调用对象将是 调用而不是 type()。
type()
本质上是类语句的动态形式。名称字符串 是类名并成为
__name__
属性;基地 tuple 逐项列出基类并成为__bases__
属性; 并且 dict 字典是包含定义的命名空间 类主体并成为__dict__
属性。例如, 以下两个语句创建相同类型的对象:>>> class X(object): ... a = 1 ... >>> X = type('X', (object,), dict(a=1))
这是,它“就像”类扩展。这也回答了
从元类中得到什么属性类?
几乎所有东西。
也请be aware that
如果你想知道自己是否需要它们,你就不需要(那些 实际上需要他们确定地知道他们需要他们,而不是 需要解释原因)。
但在video posted by @Sebastian,他说
问:你会不会有太多的 [元编程] 答:没有
所以他认为学习很重要。
【讨论】:
我找不到报价!谢谢。 @Sebastian:不客气。就在开始之后。谢谢你的视频。以上是关于为啥一个类具有它的元类的属性?的主要内容,如果未能解决你的问题,请参考以下文章