是否可以从外部模块修改元类?

2024-09-30 04:31:28 发布

您现在位置:Python中文网/ 问答频道 /正文

让我们有一个名为fields.py的外部模块,它有一个改变类FieldModel的元类FieldModelMetaclass

# module fields.py
class FieldModelMetaclass(type):
    def __new__(cls, name, bases, attrs):
        # code to alter class creation

class FieldModel(object):
    __metaclass__ = FieldModelMetaclass
    print 'run at parse time BEFORE metaclass applies'

# module consumer.py
import fields

def adjust_metaclass_new(cls, name, bases, attrs):
  # do an extra work on class `cls' and attributes `attrs'

# Is somehow possible from here alter `FieldModelMetaclass.__new__`
# by injection of adjust_metaclass_new to modify FieldModel
# before it gets instantiated ?
mymodel = fields.FieldModel()

据我所知,类的元类在compile运行时起作用,因此在导入已定义的模块时,类已经受到影响

如何在从外部模块创建类时拦截元类的效果


Tags: 模块tonamepyfieldsnewdefattrs
1条回答
网友
1楼 · 发布于 2024-09-30 04:31:28

在这种情况下,您无法轻松拦截元类的使用。导入模块时,FieldModelMetaclass.__new__方法在class FieldModel主体完成后立即调用(因此在运行时,而不是编译时)

理论上,您可以使用^{} hook在元类创建之后,但在class语句执行之前,注入额外的Python代码,但这种方式是疯狂的

另一种理论上的选择是解析模块源代码,重写它(使用^{} module),但同样,这种方式更疯狂

如果您只想拦截新实例的创建,则只需向元类添加__call__方法或向使用元类创建的每个类添加__new__方法即可:

import fields

def metaclass__call__(cls, *args, **kw):
    instance = super(FieldModelMetaclass, cls).__call__(*args, **kw)
    # do something to the instance
    return instance

FieldModelMetaclass.__call__ = metaclass__call__

如果您的目标是改变FieldModelMetaclass生成类对象的方式,那么最好的选择就是在导入之后再次更改类对象。您可以随时向类添加更多属性,或者使用自己的元类将类替换为其他属性

相关问题 更多 >

    热门问题