【问题标题】:Python: Setting the metaclass for all files in a folderPython:为文件夹中的所有文件设置元类
【发布时间】:2013-04-17 05:00:55
【问题描述】:

我编写了一个元类,用于在我的 python 项目中进行日志记录。它使每个班级自动记录所有活动。唯一的问题是我不想进入每个文件并且必须添加:

__metaclass__ = myMeta

有没有办法在顶级文件夹中设置元类,以便下面的所有文件都使用该元类?

【问题讨论】:

  • @slashdottir: 好了,答案更新到 2.7。这又是一个 hack。

标签: python package project environment-variables metaclass


【解决方案1】:

不,您只能为每个类或每个模块指定元类。您不能为整个包设置它。

在 Python 3.1 及更高版本中,您可以拦截builtins.__build_class__ 挂钩并以编程方式插入元类,请参阅Overriding the default type() metaclass before Python runs

在 Python 2.7 中,您可以将 __builtins__.object 替换为使用您的元类的子类。就像builtins.__build_class__ 钩子一样,这是高级黑客,它破坏你的代码就像让你的元类无处不在。

通过替换__builtin__ module 上的object 引用来做到这一点:

import __builtin__


class MetaClass(type):
    def __new__(mcls, name, *args):
        # do something in the metaclass
        return super(MetaClass, mcls).__new__(mcls, name, *args)


orig_object = __builtin__.orig_object


class metaobject(orig_object):
    __metaclass__ = MetaClass


def enable():
    # *replace* object with one that uses your metaclass
    __builtin__.object = metaobject

def disable():
    __builtin__.object = orig_object

在导入你的包之前运行enable()这个,所有新风格的类(那些可以支持元类的)都会有你的元类。请注意,当您的包导入代码时,此行为现在将传播到 所有 尚未加载的 Python 代码,包括标准库。您可能想使用:

enable()
import package
disable()

限制效果。

【讨论】:

    【解决方案2】:

    这是一个简单的技巧。只是 subclass class 本身在子类中有__metaclass__ 属性。这个过程可以自动化。

    util.py

    class A(object):
        def __init__(self, first, second):
            self.first = first
            self.second = second
    
        def __str__(self):
            return '{} {}'.format(self.first, self.second)
    

    main.py

    from datetime import datetime
    from util import A
    
    def meta(*args):
        cls = type(*args)
        setattr(cls, 'created', datetime.now().ctime())
        return cls
    
    try:
        print(A.created)
    except AttributeError as e:
        print(e)
    
    class A(A):
        __metaclass__ = meta
    
    print(A.created, str(A('Michael', 'Jackson')))
    

    测试;

    $ python main.py 
    type object 'A' has no attribute 'created'
    ('Wed Mar  9 22:58:16 2016', 'Michael Jackson')
    

    【讨论】:

      猜你喜欢
      • 2018-06-07
      • 1970-01-01
      • 1970-01-01
      • 2020-11-08
      • 1970-01-01
      • 1970-01-01
      • 2014-02-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多