2016-07-31 88 views
0
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) 

OUTPUTmetaclass(__call__)如何在這種情況下工作?

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 

我有嵌入到代碼中的一些問題[不要把這裏作爲它會使問題更加長]

回答

0

的方法的第一個參數是實例。元類的一個實例是一個類,這就是爲什麼我們將參數命名爲cls

super()需要實例,以便它可以正確地跟蹤MRO。它的方法已經綁定到一個合適的實例,所以不需要顯式傳遞實例。

+0

感謝ignacio,第一部分我明白了爲什麼我們將其命名爲'cls'。但第二部分不清楚,可能是笨的問題'type()觸發類型.__ call__'像所有其他可調用? ?並且'__new__'是否明確要求cls這就是我們提供它的原因? –

+0

所有可調用對象直接或以其他方式涉及'__call __()'方法。 '__new __()'是[定義這種方式](https://docs.python.org/2/reference/datamodel.html#object.__new__)。 –

相關問題