2016-07-31 45 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) 

OUTPUTWie Metaklasse (__call__) in diesem Fall funktioniert?

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 

Ich habe einige innerhalb Code eingebettet Fragen [hier nicht setzen, wie es Frage mehr länger machen wird]

Antwort

0

Das erste Argument einer Methode der Instanz ist. Eine Instanz einer Metaklasse ist eine Klasse, weshalb wir das Argument cls nennen.

super() benötigt die Instanz, damit sie MRO ordnungsgemäß verfolgen kann. Ihre Methoden sind bereits an eine geeignete Instanz gebunden und benötigen daher nicht, dass die Instanz explizit übergeben wird.

+0

Dank ignacio, ersten Teil habe ich verstanden, warum wir es 'cls' nennen. aber der zweite Teil ist nicht klar, kann b dumme Fragen 'tut Typ() löst Typ .__ Call__' wie alle anderen Callables? ? und hat "__new__" eine explizite Anforderung für cls, weshalb wir es bereitstellen? –

+0

Alle callables enthalten die '__call __()' Methode direkt oder auf andere Weise. '__new __()' ist [so definiert] (https://docs.python.org/2/reference/datamodel.html#object.__new__). –