模块级别的python元类

时间:2011-08-11 09:55:49

标签: python python-3.x metaclass

我看了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中创建模块级元类?

2 个答案:

答案 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.