我看了What is a metaclass in Python?
我试图复制示例中的上层元类,发现这并不适用于所有情况:
def upper(cls_name, cls_parents, cls_attr):
""" Make all class attributes uppper case """
attrs = ((name, value) for name, value in cls_attr.items()
if not name.startswith('__'))
upper_atts = dict((name.upper(), value) for name, value in attrs)
return type(cls_name, cls_parents, upper_atts)
__metaclass__ = upper #Module level
class Foo:
bar = 1
f = Foo()
print(f.BAR) #works in python2.6
以上在python3中失败(带有属性错误),我认为这很自然,因为python3中的所有类都已经将对象作为父对象,并且元类分辨率进入了对象类。
问题:
如何在python3中创建模块级元类?
答案 0 :(得分:11)
模块级元类不是真正的“模块级”,它与类初始化的工作方式有关。类创建将在创建类时查找变量"__metaclass__"
,如果它不在本地环境中,则它将在全局中查找。因此,如果你有一个“模块级别”__metaclass__
,之后将用于每个类,除非他们有明确的元类。
在Python 3中,您改为在类定义中指定具有metaclass=
的元类。因此,没有模块级元类。
那你做什么?简单:您为每个类明确指定。
这真的没有太多额外的工作,你甚至可以通过一个很好的正则表达式搜索来实现它,如果你真的有数百个类并且不想手动完成它,那就替换它。
答案 1 :(得分:4)
如果要将所有属性更改为大写,则应该使用__init__
方法来执行此操作,而不是使用元类。
元类比99%的用户应该担心的更深刻。如果你想知道你是否需要它们,你就不会(实际需要它们的人肯定知道他们需要它们,并且不需要解释原因)。
- Python Guru Tim Peters
如果您需要更深入的内容,还应使用Class Decorators进行评估。
使用MetaClasses并了解如何创建类是非常不必要的,只要你想做一些你可以使用类装饰器或初始化做的事情。
那就是说,如果你真的想要使用Metaclass,那么将它作为关键字参数传递给该类。
class Foo(object, metaclass=UpperCaseMetaClass)
其中UpperCaseMetaClass
是一个扩展type
而不是方法的类。
class UpperCaseMetaClass(type):
def __new__():
#Do your Magic here.