Using the __call__ method of a metaclass instead of __new__?

前端 未结 5 1350
情歌与酒
情歌与酒 2020-11-30 21:40

When discussing metaclasses, the docs state:

You can of course also override other class methods (or add new methods); for example defining a custom

5条回答
  •  余生分开走
    2020-11-30 22:20

    One difference is that by defining a metaclass __call__ method you are demanding that it gets called before any of the class's or subclasses's __new__ methods get an opportunity to be called.

    class MetaFoo(type):
        def __call__(cls,*args,**kwargs):
            print('MetaFoo: {c},{a},{k}'.format(c=cls,a=args,k=kwargs))
    
    class Foo(object):
        __metaclass__=MetaFoo
    
    class SubFoo(Foo):
        def __new__(self,*args,**kwargs):
            # This never gets called
            print('Foo.__new__: {a},{k}'.format(a=args,k=kwargs))
    
     sub=SubFoo()
     foo=Foo()
    
     # MetaFoo: , (),{}
     # MetaFoo: , (),{}
    

    Notice that SubFoo.__new__ never gets called. In contrast, if you define Foo.__new__ without a metaclass, you allow subclasses to override Foo.__new__.

    Of course, you could define MetaFoo.__call__ to call cls.__new__, but that's up to you. By refusing to do so, you can prevent subclasses from having their __new__ method called.

    I don't see a compelling advantage to using a metaclass here. And since "Simple is better than complex", I'd recommend using __new__.

提交回复
热议问题