默认类型 .__call__ 是不是比调用 __new__ 和 __init__ 更多?
Posted
技术标签:
【中文标题】默认类型 .__call__ 是不是比调用 __new__ 和 __init__ 更多?【英文标题】:Does the default type.__call__ do more than call __new__ and __init__?默认类型 .__call__ 是否比调用 __new__ 和 __init__ 更多? 【发布时间】:2014-03-31 18:09:36 【问题描述】:我正在编写一个元类,我希望在 __new__ 和 __init__ 之间调用一个附加方法。
如果我在 __new__ 之前或 __init__ 之后调用该方法,我可以写例如
class Meta(type):
def __call__(cls):
ret = type.__call__()
ret.extraMethod()
我的诱惑是写作
class Meta(type):
def __call__(cls):
ret = cls.__new__(cls)
ret.extraMethod()
ret.__init__()
return ret
然后自己重现 type.__call__ 的功能。但是我担心 type.__call__ 可能会有些微妙,我已经省略了,这会导致在实现我的元类时出现意外行为。
我不能从 __init__ 或 __new__ 调用 extraMethod,因为我希望我的元类的用户能够像在普通 Python 类中那样覆盖 __init__ 和 __new__,但仍能在 extraMethod 中执行重要的设置代码。
谢谢!
【问题讨论】:
重写方法的标准做法是调用基类的重写方法(通常通过调用super()
)这不足以确保您的类的__init__()
或__new__()
代码被处决?
一方面,除非cls.__new__(cls)
返回的值为cls
,否则不会调用__init__()
。
【参考方案1】:
如果你真的想完全按照你说的做,我可以建议你以下解决方案:
def call_after(callback, is_method=False):
def _decorator(func):
def _func(*args, **kwargs):
result = func(*args, **kwargs)
callback_args = (result, ) if is_method else ()
callback(*callback_args)
return result
return _func
return _decorator
class Meta(type):
def __new__(mcs, class_name, mro, attributes):
new_class = super().__new__(mcs, class_name, mro, attributes)
new_class.__new__ = call_after(
new_class.custom_method,
is_method=True
)(new_class.__new__)
return new_class
class Example(object, metaclass=Meta):
def __new__(cls, *args, **kwargs):
print('new')
return super().__new__(cls, *args, **kwargs)
def __init__(self):
print('init')
def custom_method(self):
print('custom_method')
if __name__ == '__main__':
Example()
此代码将生成以下结果:
new
custom_method
init
【讨论】:
以上是关于默认类型 .__call__ 是不是比调用 __new__ 和 __init__ 更多?的主要内容,如果未能解决你的问题,请参考以下文章
详解Python中的__new__、__init__、__call__三个特殊方法