关于Python的默认类型__call__ 与 call __new__ 和 __init__?

Does the default type.__call__ do more than call __new__ and __init__?

我正在编写一个元类,我希望在uu new_uuu和uu init_uuu之间调用一个额外的方法。

如果我在"new"之前或"init"之后调用该方法,我可以编写例如

1
2
3
4
class Meta(type):
    def __call__(cls):
        ret = type.__call__()
        ret.extraMethod()

我的诱惑是写作

1
2
3
4
5
6
class Meta(type):
    def __call__(cls):
        ret = cls.__new__(cls)
        ret.extraMethod()
        ret.__init__()
        return ret

只需复制类型的功能。但我担心可能会有一些微妙的类型。uuu调用_uuuu我省略了,这将导致我的元类实现时的意外行为。

我不能从uu init_uuuu或uuu new_uuu调用ExtraMethod,因为我希望我的元类用户能够像在普通的python类中那样重写u init_uuuu和uuu new_uuuu,但仍然可以在ExtraMethod中执行重要的设置代码。

谢谢!


如果你真的想按照你说的做,我可以建议你以下的解决方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
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()

此代码将生成以下结果:

1
2
3
new
custom_method
init