为什么全局变量 __metaclass__ 不起作用?
why global variable __metaclass__ not working?
我在这里定义了一些函数,它将把所有用户定义的属性都变成大写
def up(name, parent, attr):
user_defined_attr = ((k, v) for k, v in attr.items() if not k.startswith('_'))
up_attr = {k.upper(): v for k,v in user_defined_attr}
return type(name, parent, up_attr)
例如:
my_class = up('my_class', (object,), {'some_attr': 'some_value'})
hasattr(my_class, 'SOME_ATTR')
True
这是 python 文档中关于 元类
的一些文字
https://docs.python.org/2/reference/datamodel.html?highlight=metaclass#metaclass
The appropriate metaclass is determined by the following precedence rules:
If dict['__metaclass__'] exists, it is used.
Otherwise, if there is at least one base class, its metaclass is used (this looks for a __class__ attribute first and if not found, uses its type).
Otherwise, if a global variable named __metaclass__ exists, it is used.
Otherwise, the old-style, classic metaclass (types.ClassType) is used.
所以我做了一些测试
>>> def up(name, parent, attr):
... user_defined_attr = ((k, v) for k, v in attr.items() if not k.startswith('_'))
... up_attr = {k.upper(): v for k,v in user_defined_attr}
... return type(name, parent, up_attr)
...
>>>
>>>
>>> __metaclass__ = up
>>>
>>> class C1(object):
... attr1 = 1
...
>>> hasattr(C1, 'ATTR1')
False
不适用于全局 var 情况,为什么?
如果您在 Python 2,您的问题是您将 object
列为 C1
的基础 class,而全局 __metaclass__
回退是 lower-priority 而不是基础 class 的元 class.
如果您使用 Python 3,您的问题是全局 __metaclass__
不再执行任何操作。
似乎只有old-style classes使用全局__metaclass__
变量。它们是 old-style 的事实与此无关,但这是它们的定义方式。 New-style classes 显式继承自带有 meta-class 的 class 而 old-style classes 则没有。
class Meta(type):
pass
__metaclass__ = Meta
class NewStyle(object):
pass
class OldStyle:
pass
print "new style", type(NewStyle)
print "old style", type(OldStyle)
此代码打印:
new style <type 'type'>
old style <class '__main__.Meta'>
这似乎与您列出的规则一致。 NewStyle
有基础 class object
而 class 有自己的元 class type
。所以对于 new-style classes type
是根据秒规则选择的。
我在这里定义了一些函数,它将把所有用户定义的属性都变成大写
def up(name, parent, attr):
user_defined_attr = ((k, v) for k, v in attr.items() if not k.startswith('_'))
up_attr = {k.upper(): v for k,v in user_defined_attr}
return type(name, parent, up_attr)
例如:
my_class = up('my_class', (object,), {'some_attr': 'some_value'})
hasattr(my_class, 'SOME_ATTR')
True
这是 python 文档中关于 元类
的一些文字https://docs.python.org/2/reference/datamodel.html?highlight=metaclass#metaclass
The appropriate metaclass is determined by the following precedence rules:
If dict['__metaclass__'] exists, it is used.
Otherwise, if there is at least one base class, its metaclass is used (this looks for a __class__ attribute first and if not found, uses its type).
Otherwise, if a global variable named __metaclass__ exists, it is used.
Otherwise, the old-style, classic metaclass (types.ClassType) is used.
所以我做了一些测试
>>> def up(name, parent, attr):
... user_defined_attr = ((k, v) for k, v in attr.items() if not k.startswith('_'))
... up_attr = {k.upper(): v for k,v in user_defined_attr}
... return type(name, parent, up_attr)
...
>>>
>>>
>>> __metaclass__ = up
>>>
>>> class C1(object):
... attr1 = 1
...
>>> hasattr(C1, 'ATTR1')
False
不适用于全局 var 情况,为什么?
如果您在 Python 2,您的问题是您将 object
列为 C1
的基础 class,而全局 __metaclass__
回退是 lower-priority 而不是基础 class 的元 class.
如果您使用 Python 3,您的问题是全局 __metaclass__
不再执行任何操作。
似乎只有old-style classes使用全局__metaclass__
变量。它们是 old-style 的事实与此无关,但这是它们的定义方式。 New-style classes 显式继承自带有 meta-class 的 class 而 old-style classes 则没有。
class Meta(type):
pass
__metaclass__ = Meta
class NewStyle(object):
pass
class OldStyle:
pass
print "new style", type(NewStyle)
print "old style", type(OldStyle)
此代码打印:
new style <type 'type'>
old style <class '__main__.Meta'>
这似乎与您列出的规则一致。 NewStyle
有基础 class object
而 class 有自己的元 class type
。所以对于 new-style classes type
是根据秒规则选择的。