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.