如无特殊说明,Python的版本都是2.X。
Python中有两种类:经典类 和 新式类。
新式类直接或间接继承自object类,也就是说新式类都是object类的子类;其他的类都是经典类。
# coding: utf8 import types class Classic: pass class NewStyle(object): def __new__(cls, *a, **kw): instance = super(NewStyle, cls).__new__(cls, *a, **kw) return instance def __init__(self, *a, **kw): pass if __name__ == "__main__": # 经典类是ClassType类型的 print isinstance(Classic, types.ClassType) # True # 新式类是TypeType类型的 print isinstance(NewStyle, types.TypeType) # True # 经典类 和 新式类的 mro 顺序也是不一样的 # 经典类的实例是InstanceType类型的,新式类的实例不是 print type(Classic()) == types.InstanceType # True print type(NewStyle()) == types.InstanceType # False
新式类有2个与对象构造相关的魔术方法:
__init__(self, ...)
__new__(cls, ...)
大多数人会以为__init__
方法是构造方法,其实不然。__init__
方法其实可以叫做初始化方法,它的作用是在对象被创建!!!之后!!!,对对象的属性进行初始化。新式类的真正的构造方法是__new__
方法,__new__
方法是一个静态方法,哪怕在定义它的时候,并没有使用@staticmethod
装饰器。
[root@iZj6chejzrsqpclb7miryaZ ~]# cat test.py # coding: utf8 class NewStyle(object): # 注意:一定要是新式类 def __new__(cls, *a, **kw): print 'instance will be created...' # 调用父类的 构造方法 instance = super(NewStyle, cls).__new__(cls, *a, **kw) print 'instance is created...' return instance def __init__(self, *a, **kw): print '__init__ is invoked...' if __name__ == "__main__": print NewStyle() [root@iZj6chejzrsqpclb7miryaZ ~]# python test.py instance will be created... instance is created... __init__ is invoked... <__main__.NewStyle object at 0x7f0e1b255690>
如果本类中,没有定义__new__
构造方法,那么会去父类中找;...,一直到object类。
通常情况下,很少使用__new__
方法。在使用元类的时候,会用到__new__
方法。
在Python中一切皆对象。类的实例是对象,类本身也是对象。类是用来创建对象的,而元类是用来创建类的。
下面看一下,我们怎么在Python创建类:
[root@iZj6chejzrsqpclb7miryaZ ~]# cat test.py class MyClass1(object): @staticmethod def sm(): print "sm() in MyClass1" print MyClass1 MyClass1.sm() def sm(): print "sm() in MyClass2" MyClass2 = type("MyClass2", (object,), {"sm": staticmethod(sm)}) print MyClass2 MyClass2.sm() [root@iZj6chejzrsqpclb7miryaZ ~]# python test.py <class '__main__.MyClass1'> sm() in MyClass1 <class '__main__.MyClass2'> sm() in MyClass2
我们可以看到,第一种是定义类的标准语法,使用class
关键字;第二种使用了type
这个类(!!!type
不是内建方法,是一个类,而且是所有新式类的最终的元类,也就是说所有的新式类,都是type的实例,都是通过type创建的!!!)。
下面看一个例子:
# coding: utf8 class NewStyle(object): pass # 新式类的__class__属性,指向其元类 print NewStyle.__class__ == type # True # 新式类的对象的__class__属性,指向创建它的类 print NewStyle().__class__ == NewStyle # True
下面,看一个使用元类的例子:
[root@iZj6chejzrsqpclb7miryaZ ~]# cat test.py # coding: utf8 import types def log_deco(f): def _inner(*a, **kw): print "enter" try: return f(*a, **kw) finally: print "exit" return _inner class MetaClass1(type): # 注意:继承type类,而不是object类 def __new__(cls, name, bases, attrs): # 我们可以在这里做一些hack。比如给类中所有的方法 # + 都加上一个打印日志的装饰器 for attr_name, attr in attrs.iteritems(): if isinstance(attr, types.FunctionType): attrs[attr_name] = log_deco(attr) # 调用父类的__new__方法,最终会调用到type.__new__方法 clazz = super(MetaClass1, cls).__new__(cls, name, bases, attrs) print "class is created at: %r" % clazz return clazz class MyClass1(object): # 通过__metaclass__类属性,为类指定元类 __metaclass__ = MetaClass1 def method(self): print "I am method() in MyClass1" # 类是元类的对象~ print isinstance(MyClass1, MetaClass1) # True # 类的实例是类的对象 print isinstance(MyClass1(), MyClass1) # True print "===" MyClass1().method() print "===" [root@iZj6chejzrsqpclb7miryaZ ~]# python test.py class is created at:True True === enter I am method() in MyClass1 exit ===
在新式类中,如果类本身没通过__metaclass__
指定元类,那么则去父类找;...,一直到object,object的元类是type。