Python的metaclass、`__new()__`、单例模式
2015-10-21 10:38
381 查看
元类的引入
在Python的世界里,一切均是对象,包括函数、class;如果class是用来生成对象的,那么作为对象的class,又是由谁生成的呢?答应就是meta-class,meta-class是用来生成class的class。在python中,有两个默认的meta class,分别是经典类的types.ClassType, 新式类的type元类生成class的过程
type(calss_name, (parent_class,),{‘function_name’:function, 'property_name':property_value})
对于形如下面的class
class Base(object): def fun_base(self): print 'this is base fun' class Foo(Base): def __init__(self): self.a = 1 def fun(self): print 'this is fun'
如果使用meta-class来生成同样的class,其过程
class Base(object): def fun_base(self): print 'this is base fun' def fun(self): print 'This is fun' c = type('Foo', (Base,), {'fun':fun, 'a':1}) c1 = c() print c print c1 print type(c1) c1.fun() c1.fun_base() print c1.a
其输出为,type()的返回值是一个class,由其生成的对象c1 其类型是class Foo,c1可以调用其自己与其父类的成员函数,也可以访问自己的属性。其面向对象的所有属性与上面定义的class Foo一致
<class '__main__.Foo'> <__main__.Foo object at 0x000000000270DF28> <class '__main__.Foo'> <__main__.Foo object at 0x000000000270DF28> This is fun this is base fun 1
当python的解释器遇到语句class的时候,就会寻找该class的meta clas去生成其对象,也就是class本身,其查找meta clas的过程如下:
1.class是否定义属性
__metaclass__
2.class的父类是否定义属性
__metaclass__
3.class所在的模块是否定义
__metaclass__
4.使用默认的metaclass:旧式类 types.ClassType;新式类 type
其实,在python的定义中,meta class不仅仅局限于type和type.ClassType,任何接受参数name,tuple,dict,返回值为class的可调用变量都可以当做meta class
This variable can be any callable accepting arguments for name, bases, and dict. Upon class creation, the callable is used instead of the built-in type().
那么借助这个定义,我们可以对type()做一定的封装,让称为meta class
我们可以定义自己的meta class
class MetaCls(type): def __new__(cls, name, bases, dict): # do customizing here return super(MetaCls, cls).__new__(cls, name, bases, dict)
我们甚至可以把一个函数变成一个meta class
def metacls_func(name, bases, dict): # do customizing here return type(name, bases, dict)
__new()__
与__init()__
在python中,__new()__、
__init()__是与对象生成密切相关的两个magic method,前者完成对象生成过程,后者完成对象的初始化过程。
class C(object): def __new__(cls, *args, **kwargs): # cls is a class, and __new__() returns a object print '__new__ called. args is ', args, 'kwargs is ', kwargs print 'the type of cls is ', type(cls), ' the cls is ', cls c = super(C, cls).__new__(cls, *args, **kwargs) print 'the type of c is ', type(c), ' the c is ', c return c def __init__(self, *args, **kwargs): print '__init__ called. args is ', args, 'kwargs is ', kwargs print 'the type of self is ', type(self), 'the self is ', self c1 = C(1, 2, a=3) print c1 c2 = C(3, 4, b=4) print c2
其输出为
__new__ called. args is (1, 2) kwargs is {'a': 3} the type of cls is <type 'type'> the cls is <class '__main__.C'> the type of c is <class '__main__.C'> the c is <__main__.C object at 0x00000000026ADE48> __init__ called. args is (1, 2) kwargs is {'a': 3} the type of self is <class '__main__.C'> the self is <__main__.C object at 0x00000000026ADE48> <__main__.C object at 0x00000000026ADE48> __new__ called. args is (3, 4) kwargs is {'b': 4} the type of cls is <type 'type'> the cls is <class '__main__.C'> the type of c is <class '__main__.C'> the c is <__main__.C object at 0x00000000026ADE80> __init__ called. args is (3, 4) kwargs is {'b': 4} the type of self is <class '__main__.C'> the self is <__main__.C object at 0x00000000026ADE80> <__main__.C object at 0x00000000026ADE80>
这段代码说明:
__new()__的作用:当调用
c1 = C(1, 2, a=3)时,
class语句会查找
__metaclass__生成
class C,之后
__new()__被调用,通过调用父类的
__new()__生成对象(
super(C, cls).__new__(cls, *args, **kwargs)的返回值是一个Class C的一个对象,类型是class C)
__init()__的作用:当
__new()__返回一个对象之后,会继续调用
__init()__进行对象的初始化过程。(如果
__new()__没有返回一个对象,那么后续的
__init()__也不会被调用)
cls与
self:二者分别是
__new()__、
__init()__的参数,从上面的代码可以看出,
cls就是由
metaclass type生成的
class C,而
self就是
class C生成的对象,在两次调用中,这个对象分别就是
c1 = C(1, 2, a=3) c2 = C(3, 4, b=4)生成的c1和c2(
self和它们的地址是一致的)
__new()__与
__init()__的参数传递: 当调用对象生成语句
c1 = C(1, 2, a=3)的时候,会携带不定参数
(1, 2, a=3),这些参数会分别被传递给
__new()__与
__init()__
python的单例
可以使用metaclass与__new()__的特性,构建python的单例模式
class Singleton(object): def __new__(cls, *args, **kwargs): if not hasattr(cls, '_instance'): cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs) return cls._instance def __init__(self, *args, **kwargs): pass s1 = Singleton() s2 = Singleton() print s1 print s2 print s1 == s2 <__main__.Singleton object at 0x000000000278D080> <__main__.Singleton object at 0x000000000278D080> True
通过增加类属性_instance记录单例对象,每次生成对象的时候,如果对象已经生成过,那么就会将第一次生成对象返回,否则才会生成一个对象,从而实现单例模式。从代码的输出也可以看到,多次生成对象,生成的对象总是同一个
那么meta-class是不是对象呢?(待补充)
相关文章推荐
- python脚本——合并word
- python中的多态
- Python学习之安装WingIDE并破解
- PEP8 Python 编码规范整理
- python函数函数指针用法
- from __future__ import absolute_import
- python -- 抽奖
- Requests+Beautifulsoup+re百度贴吧抓取实例(python3.4逐行解释)
- 怎么解决python "Non-ASCII character"错误
- (1)python基本使用
- Python2.*脚本转换成Python3.*脚本
- leetcode之Search in Rotated Sorted Array
- 【Python】调用WPS V9 API,实现PPT转PDF
- leetcode之Search a 2D Matrix II
- Learn Python The Hard Way(0--26)
- leetcode之Search a 2D Matrix
- python例子-开始一个Django项目
- 零基础学python-19.3 列表解析与矩阵
- 零基础学python-18.8 嵌套lambda与作用域
- 零基础学python-18.1 函数的设计