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.