【Python基础】Python面向对象 - 8 - 元类2
2015-09-12 10:55
781 查看
metaclass基础
一般情况下,如果要用类来实现metaclass的话,该类需要继承与 type ,而且通常会重写 type 的 __new__方法老控制创建过程。在metaclass里面定义的方法会成为类的方法,可以直接通过类名来调用。如何使用metaclass
用类的形式:类继承于 type, 例如 class Meta(type): pass
将需要使用metaclass来构建的类的__metaclass__属性赋值为 Meta。
metaclass原理
metaclass的原理其实是这样的:当定义好类之后,创建类的时候其实是调用了 type 的 __new__ 方法为这个类分配内存空间。创建好了之后再调用 type 的 __init__ 方法初始化。__new__方法
__new__(cls, name, bases, attrs)cls: 将要创建的类,类似于self,但是self指向的是Instance,而这里cls指向的是class
name: 类的名字,也就是我们通常用类名__name__获取的
base: 基类
attrs: 属性的dict,dict的内容可以是变量(类属性),也可以是函数(类方法)
所以在创建类的过程,我们可以在这个函数里面修改name, bases, attrs的值来自由的达到我们的功能。
metaclass的使用示例
修改/增加/删除类或者实例中的方法或属性
#!/usr/bin/python #coding :utf-8 def ma(cls): print 'method a' def mb(cls): print 'method b' method_dict = { 'ma': ma, 'mb': mb, } class DynamicMethod(type): def __new__(cls, name, bases, dct): if name[:3] == 'Abc': dct.update(method_dict) return type.__new__(cls, name, bases, dct) def __init__(cls, name, bases, dct): super(DynamicMethod, cls).__init__(name, bases, dct) class AbcTest(object): __metaclass__ = DynamicMethod def mc(self, x): print x * 3 class NotAbc(object): __metaclass__ = DynamicMethod def md(self, x): print x * 3 def main(): a = AbcTest() a.mc(3) a.ma() print dir(a) b = NotAbc() print dir(b) if __name__ == '__main__': main()
通过metaclass这个元类,可以在那些指定了__metaclass__属性的类里面,根据类名字,如果是以Abc开头的就给它们加上ma和mb方法。
只要我们能操作__new__方法里面的其中一个参数attrs,就可以动态添加东西了。
批量的对某些方法使用decorator,而不需要每次都在方法的上面加上@decorator_func
比如需要验证登陆或者是否有权限的,只有通过验证通过之后才可以操作,那么如果有很多个操作都需要这样做,我们一般情况下可以手动在每个方法的前头用@login_required类似这样的方法。如果使用了metaclass的使用的话,可以这样做:#!/usr/bin/python #coding :utf-8 from types import FunctionType def login_required(func): print 'login check logic here' return func class LoginDecorator(type): def __new__(cls, name, bases, dct): for name, value in dct.iteritems(): if name not in ('__metaclass__', '__init__', '__module__') and\ type(value) == FunctionType: value = login_required(value) dct[name] = value return type.__new__(cls, name, bases, dct) class Operation(object): __metaclass__ = LoginDecorator def delete(self, x): print 'deleted %s' % str(x) def main(): op = Operation() op.delete('test') if __name__ == '__main__': main()
这样就可以不用在delete函数上面写@login_required,也能达到decrator的效果了。
相关文章推荐
- python安装第三方库的命令
- 无开发经验,初学python
- Python编码问题
- python-类属性访问规则
- python模块psutil的使用——获取系统状态
- 零基础学python-16.1 作用域快速入门
- 零基础学python-16.1 作用域快速入门
- python 爬虫4 一些编程注意项目
- Python介绍和安装
- Python __call__内置函数的作用和用法
- Python读取中文txt乱码问题
- python 常用代码
- Python多版本管理软件pyenv的安装应用及pip的使用讲解
- 【转】python经典面试题目
- Python连接MySQL
- python学习笔记14 list列表数组
- python的关键字,数据类型、操作符、转义字符和格式化字符串
- 使用Python2.7批量查询云窗IP
- 零基础学python-15.4 函数的多态vs对象的多态
- 零基础学python-15.4 函数的多态vs对象的多态