【问题标题】:python metaclasses at module level模块级别的python元类
【发布时间】:2011-10-24 20:01:01
【问题描述】:

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

【问题讨论】:

  • 可能你需要的是一个类装饰器而不是一个元类。
  • @Sven Marnach: __metaclass__ 可能确实绑定到一个函数。该函数只需要接受与元类的__init__() 方法相同的参数并返回一个类型对象。
  • @Sven Marnach:需要接受与元类的 __init__() 方法相同的参数 - 即 self 除外。
  • @pillmuncher:你基本上是对的,除了它与元类的__new__() 方法的参数相同。我不知道这一点,尽管实际上很明显任何可调用对象都可以。 (请注意,可调用对象甚至不需要返回类型对象。可调用对象返回的任何对象都将绑定到类名。)
  • 那么, 模块级元类的python3等价物是什么?似乎没有人回答你的实际问题。该功能是否已被废弃?有求知欲的人想知道。

标签: python python-3.x metaclass


【解决方案1】:

模块级元类并不是真正的“模块级”,它与类初始化的工作方式有关。创建类时,类创建将查找变量"__metaclass__",如果它不在本地环境中,它将在全局环境中查找。因此,如果您有一个“模块级别”__metaclass__,之后将用于每个类,除非它们有明确的元类。

在 Python 3 中,您改为在类定义中使用 metaclass= 指定元类。因此没有模块级元类。

那你是做什么的?简单:您为每个类明确指定它

这实际上并没有太多额外的工作,如果你真的有数百个类并且不想手动进行,你甚至可以通过一个很好的正则表达式搜索和替换来完成。

【讨论】:

  • 我建议你使用模块范围的超类,例如class Base(object, metaclass=upper): pass 然后将所有相关类都基于这个基类。
【解决方案2】:

如果您想将所有属性更改为大写,您可能应该使用__init__ 方法,而不是使用元类。

元类是比 99% 的用户所担心的更深层次的魔法。如果您想知道自己是否需要它们,那您就不需要(真正需要它们的人肯定知道他们需要它们,并且不需要解释为什么)。

-- Python 大师Tim Peters

如果您需要更深入的内容,还应该使用Class Decorators 进行评估。

只要你想做一些你可以使用类装饰器或初始化来做的事情,使用元类和理解类是如何创建的都是不必要的。

也就是说,如果您真的想使用元类,请将其作为关键字参数传递给该类。

class Foo(object, metaclass=UpperCaseMetaClass)

其中UpperCaseMetaClass 是扩展type 的类,而不是方法。

class UpperCaseMetaClass(type):
    def __new__():
        #Do your Magic here.

【讨论】:

猜你喜欢
  • 2022-08-03
  • 2012-02-20
  • 2021-11-24
  • 2015-07-26
  • 2017-08-28
  • 1970-01-01
  • 2018-01-13
相关资源
最近更新 更多