在这种情况下,元类.__ call__如何工作?

时间:2016-07-31 14:31:39

标签: python call super metaclass

import inspect

class meta(type):
   def __new__(cls, t_name, bases, argdict):
       print "inside meta __new__"
       return super(meta, cls).__new__(cls, t_name, bases, argdict)

   def __init__(self, t_name, bases, argdict): 
       print "inside __init__ of meta"

   def __call__(cls, *args, **kwargs):
       print "*************************"
       print "inside __call__ of meta"
       print cls, args, kwargs #--> cls is A
       # How cls is passed as __call__ does not take cls param? through super/how? Why super requires cls?
       inst = super(meta, cls).__call__(*args, **kwargs) # why no cls to call? how super works here
       #inst = type.__call__(cls, *args, **kwargs) # this works well
       print inst, "instance inside meta"
       print "*************************"
       return inst


class A(object):
    __metaclass__ = meta # this line triggers metaclass

    def __new__(cls, *args, **kwargs):
        print "inside A __new__"
        print cls, args, kwargs # we get cls here as A
        inst = super(A, cls).__new__(cls, *args, **kwargs)
        print inst, "instance inside A"
        return inst

    def __init__(self, *args, **kwargs):
        print "inside A __init___"
        self.attr = args[0]

    def __call__(self, *args, **kwargs):
        print "inside A __call__ "
        print self, args, kwargs



a = A("simple arg") # this is type(A).__call__(A, ... ) ==           meta.__call__(A, ...)
print a
a("param")  # type(a).__call__(a), ...
print type(A)

OUTPUT

inside meta __new__
inside __init__ of meta
*************************
inside __call__ of meta
<class '__main__.A'> ('simple arg',) {}
inside A __new__
<class '__main__.A'> ('simple arg',) {}
<__main__.A object at 0x7ff0010f2c10> instance inside A
inside A __init___
<__main__.A object at 0x7ff0010f2c10> instance inside meta
*************************
<__main__.A object at 0x7ff0010f2c10>
inside A __call__ 
<__main__.A object at 0x7ff0010f2c10> ('param',) {}
<class '__main__.meta'>
<type 'type'>
True

我在代码中嵌入了一些问题[没有放在这里因为它会使问题更长一些]。

1 个答案:

答案 0 :(得分:2)

方法的第一个参数是实例。元类的实例是一个类,这就是为什么我们将参数命名为cls

super()需要该实例,以便它可以正确地跟踪MRO。它的方法已绑定到适当的实例,因此不需要明确传递实例。