我有一个像这样的元类
GroupMember
我的问题是:
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
attr?答案 0 :(得分: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']
属性访问的默认行为是获取,设置或删除 来自对象字典的属性。例如,a.x有一个 查找链以。 dict [' x']开头,然后 键入(a)。 dict [' x'],并继续通过基类 (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分钟左右。
答案 1 :(得分:1)
为什么B类有echo方法,B不是UpperMeta的子类,它 不应该有回音?
如果您查看What is a metaclass in Python?或Customizing class creation,就会看到(来自python docs的引用)
如果定义了
__metaclass__
,则分配给它的可调用对象将是 调用而不是type()。
本质上是类语句的动态形式。名称字符串 是类名,并成为
__name__
属性;基地 tuple逐项列出基类并成为__bases__
属性; dict字典是包含定义的命名空间 class body并成为__dict__
属性。例如, 以下两个语句创建相同的类型对象:>>> class X(object): ... a = 1 ... >>> X = type('X', (object,), dict(a=1))
这就是“就像”类扩展一样。这也回答了
什么属性类来自元类?
几乎所有东西。
如果你想知道你是否需要它们,你就不会(那些人 实际上需要他们肯定地知道他们需要他们,而不是 需要解释为什么)。
然而在video posted by @Sebastian,他说
问:你有太多的[元编程] 答:没有
所以他认为重要的是要学习。