我编写了一个元类,用于在我的 python 项目中进行日志记录。它使每个班级自动记录所有活动。唯一的问题是我不想进入每个文件并且必须添加:
__metaclass__ = myMeta
有没有办法在顶级文件夹中设置元类,以便下面的所有文件都使用该元类?
我编写了一个元类,用于在我的 python 项目中进行日志记录。它使每个班级自动记录所有活动。唯一的问题是我不想进入每个文件并且必须添加:
__metaclass__ = myMeta
有没有办法在顶级文件夹中设置元类,以便下面的所有文件都使用该元类?
不可以,您只能为每个类或每个模块指定元类。您不能为整个包设置它。
在 Python 3.1 及更高版本中,您可以拦截builtins.__build_class__
钩子并以编程方式插入元类,请参阅在 Python 运行之前覆盖默认的 type() 元类。
在 Python 2.7 中,您可以替换__builtins__.object
为使用您的元类的子类。就像builtins.__build_class__
钩子一样,这是高级骇客,破坏你的代码就像让你的元类无处不在。
通过替换模块object
上的引用来做到这一点:__builtin__
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()
来限制效果。
这是一个简单的技术。只需使用子类中的属性对类本身进行子类化。__metaclass__
这个过程可以自动化。
实用程序.py
class A(object):
def __init__(self, first, second):
self.first = first
self.second = second
def __str__(self):
return '{} {}'.format(self.first, self.second)
主文件
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')