内容简介:Python中的类,构造方法,元类
摘要
如无特殊说明,Python的版本都是2.X。
Python中的类
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: <class __main__="" myclass1=""> True True === enter I am method() in MyClass1 exit === </class>
在新式类中,如果类本身没通过 __metaclass__
指定元类,那么则去父类找;...,一直到object,object的元类是type。
以上所述就是小编给大家介绍的《Python中的类,构造方法,元类》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- python面向对象-1方法、构造函数
- 只有你能 new 出来!.NET 隐藏构造函数的 n 种方法(Builder Pattern / 构造器模式)
- Effective Java 第二版笔记之考虑使用静态工厂方法代替构造器
- Effective Java 第二版笔记之考虑使用静态工厂方法代替构造器
- Effective Java in Kotlin第一条: 考虑用静态工厂方法而不是构造器
- [ActionScript 3.0] AS向php发送二进制数据方法之——在URLRequest中构造HTTP协议发送数据
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。