http://stackoverflow.com/a/6581949
Python does the following:
- Is there a __metaclass__ attribute in Foo?
- If yes, create in memory a class object (I said a class object, stay with me here), with the name Foo by using what is in __metaclass__.
- If Python can't find __metaclass__, it will look for a __metaclass__ at the MODULE level, and try to do the same (but only for classes that don't inherit anything, basically old-style classes).
- Then if it can't find any __metaclass__ at all, it will use the Bar's (the first parent) own metaclass (which might be the default type) to create the class object.
- Be careful here that the __metaclass__ attribute will not be inherited, the metaclass of the parent (Bar.__class__) will be.
- If Bar used a __metaclass__ attribute that created Bar with type() (and not type.__new__()), the subclasses will not inherit that behavior.
""" Metaclass code explain """ class ModelMeta(type): def __new__(cls, name, bases, attrs): print("in new") print(name) # Test2 print(bases) # (<class '__main__.Test'>,) print(cls) # <class '__main__.ModelMeta'> """ If not using type.__new__, derived class won't use metaclass to create type instance. """ result = type.__new__(cls, name, bases, attrs) # result = type(name, bases, attrs) print(dir(result)) """ ['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__metaclass__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__'] """ print(result.__metaclass__) # <class '__main__.ModelMeta'> return result def __call__(cls, *args, **kwargs): print("in call") print(cls) instance = type.__call__(cls, *args, **kwargs) return instance class Test(object): __metaclass__ = ModelMeta class Test2(Test): pass class Test3(Test2): pass if __name__ == "__main__": t2 = Test2() # call ModelMeta. __call__Another perspect
""" Metaclass code explain """ class ModelMeta(type): def __new__(cls, name, bases, attrs): print("in new") print("name:{0}".format(name)) # Test2 print("bases:{0}".format(bases)) # (<class '__main__.Test'>,) print("cls:{0}".format(cls)) # <class '__main__.ModelMeta'> print("attrs:{0}".format(attrs)) # <class '__main__.ModelMeta'> # Class Test 將擁有空的bases集合 parents = [b for b in bases if isinstance(b, ModelMeta)] print("parents:{0}".format(parents)) """ If not using type.__new__, derived class won't use metaclass to create type instance. """ result = type.__new__(cls, name, bases, attrs) # there will be no inheritence affect if using simply type constructor # result = type(name, bases, attrs) print(dir(result)) """ ['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__metaclass__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__'] """ print(result.__metaclass__) # <class '__main__.ModelMeta'> return result def __call__(cls, *args, **kwargs): print("in call") print(cls) instance = type.__call__(cls, *args, **kwargs) return instance class Test(object): __metaclass__ = ModelMeta aa = 1 class Test2(Test): a = 2 class Test3(Test2): a = 3 if __name__ == "__main__": t2 = Test2() # call ModelMeta. __call__ print(t2.a)
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.