最近了解了一下python的metaclass,在学习的过程中,把自己对metaclass的理解写出来和大家分享。

首先, metaclass 中文叫元类,这个元类怎么来理解呢。我们知道,在Python中,一切都是对象。我们定义一个类,然后实例化,得到了一个类的实例对象。我们可以把类理解成创建实例对象的模板。其实,这个模板,也就是类本身,也是一个对象。既然类也是对象,那么我们就可以对他进行很多操作。比如,把类作为函数的参数,创建类的引用等等。那么创建类的模板,就是元类。

在Python中,我们很早就接触了一个函数 type,用来返回对象的类型。比如

In [1]: print(type(1))
<type 'int'>
In [2]: print(type(""))
<type 'str'>
In [3]: def foo():pass
In [4]: print (type(foo))
<type 'function'>
In [5]: class Foo():pass
In [6]: print(type(Foo()))
<type 'instance'>
In [7]: print(type(Foo))
<type 'classobj'>

其实 type函数还有另外一个用处,那就是用来创建类,用法就是

type(classname,(superclassname,),{attrs}),我们来看一下:

MyClass = type("MyClass",(),{})

其实等效于

class MyClass():
pass

我们说过,metaclass是创建类的类,所以,type就是一个metaclass。我们来验证一下

In [23]: age.__class__
Out[23]: int
In [24]: name.__class__
Out[24]: str
In [25]: MyClass().__class__
Out[25]: __main__.MyClass
In [26]: MyClass().__class__.__class__
Out[26]: type
In [29]: age.__class__.__class__
Out[29]: type
In [30]: name.__class__.__class__
Out[30]: type

type是内置的metaclass,我们也可以自己定义自己的元类。在定义类的时候,定义 __metaclass__属性,这种情况下,Python就会使用metaclass 来创建类。具体模式如下:

在创建类时,Python会寻找有没有定义__metaclass__,如果有,就用定义好的metaclass来创建类。

如果在当前类找不到 __metaclass__,Python会在当前模块下寻找__metaclass__

如果还是找不到,Python会寻找当前类第一个父类的__metaclass__,直到最后的内建函数type()

那么__metaclass__定义到底是什么呢?

是任何能够创建类的,比如type或者type的子类

所以metaclass的目的在类创建的时候自动的修改类,举个例子,我们想把一个类里所有的属性前面都加一个my_前缀,使用metaclass的方式就比较简单

class MyAttrMetaclass(type):
def __new__(cls, clsname, bases,dct):
my_attr = {}
for name, val in dct.items():
if not name.startswith('__'):
my_attr["my_"+name] = val
else:
my_attr[name] = val
return type.__new__(cls, clsname, bases, my_attr) class Foo():
__metaclass__= MyAttrMetaclass
test_age = 1
test_name = "test" print(hasattr(Foo,"test_age"))
False
print(hasattr(Foo,"my_test_age"))
True

可以看到通过元类的方式,我们的类Foo的属性被修改了。

最后一个问题就是我们在什么情况下会用到metaclass呢?

常见的例子有Django ORM 的Model类,

我们定义一个Person类集成Model

class Person(Model):
name = models.CharField(max_length=30)
age = models.IntegerField() p = person(name="haha",age="31")

p.age 返回的是int 而不是IntegerField(),这就是因为在Model中使用的metaclass动态修改类

本文总结了黑魔法metaclass的定义,用法,主要参考了http://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python

python黑魔法之metaclass的更多相关文章

  1. Python 黑魔法 --- 描述器(descriptor)

    Python 黑魔法---描述器(descriptor) Python黑魔法,前面已经介绍了两个魔法,装饰器和迭代器,通常还有个生成器.生成器固然也是一个很优雅的魔法.生成器更像是函数的行为.而连接类 ...

  2. (转)Python黑魔法 --- 异步IO( asyncio) 协程

    转自:http://www.jianshu.com/p/b5e347b3a17c?from=timeline Python黑魔法 --- 异步IO( asyncio) 协程 作者 人世间 关注 201 ...

  3. python 黑魔法 ---上下文管理器(contextor)

    所谓上下文 计算机上下文(Context)对于我而言,一直是一个很抽象的名词.就像形而上一样,经常听见有人说,但是无法和现实认知世界相结合. 最直观的上下文,莫过于小学的语文课,经常会问联系上下文,推 ...

  4. Python 黑魔法(持续收录)

    Python 黑魔法(持续收录) zip 对矩阵进行转置 a = [[1, 2, 3], [4, 5, 6]] print(list(map(list, zip(*a)))) zip 反转字典 a = ...

  5. python 黑魔法收集--已结

    awesome python 中文大全 Fabric , pip, virtualenv 内建函数好文 awesome python 奇技淫巧 一句话求阶乘 from functools import ...

  6. python 中的metaclass和baseclasses

    提前说明: class object  指VM中的class 对象,因为python一切对象,class在VM也是一个对象,需要区分class对象和 class实例对象. class instance ...

  7. python中的metaclass

    首先看下面的代码: # coding: utf-8 class Test(object): pass print Test.__class__ # type print Test.__base__ # ...

  8. python 元类——metaclass

    from stack overflow:http://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python Classes ...

  9. python——type()、metaclass元类和精简ORM框架

    1.type()函数 if __name__ == '__main__': h = hello() h.hello() print(type(hello)) print(type(h)) Hello, ...

随机推荐

  1. [bzoj1500][NOI2005]维修数列——splay

    题目 题解 这道题可以说是数列问题的大BOSS,也算是这一周来学习splay等数据结构的一个总结. 我们一个一个地看这些操作. 对于操作1,我们首先建一棵子树,直接接上原树即可. 对于操作2,我们找到 ...

  2. poj 2236

    Wireless Network Time Limit: 10000MS   Memory Limit: 65536K Total Submissions: 25817   Accepted: 107 ...

  3. HA高可用集群

     准备2台机器:主:master:192.168.254.140从:slave:192.168.254.141 1.主上安装:wget www.lishiming.net/data/attachmen ...

  4. Debian安装Oracle Java步骤

    在Debian下安装OpenJDK使用apt命令非常方便的安装,但安装Oracle就需要手动了,这里需了解ln和update-alternatvies命令. ln链接 首先我们来说说linux的链接, ...

  5. ceph-deploy install时,远端节点在执行apt-get update命令时失败

    环境 OS:Ubuntu 16.04 背景 使用ceph-deploy部署Ceph集群,调用ceph-deploy install命令在远端节点安装ceph环境,执行apt-get update命令时 ...

  6. JavaScript实现评论点赞功能

    通过分析评论功能的逻辑关系,学会如何使用JavaScript实现评论.回复.点赞等各种功能 1.学会JavaScript处理日期和时间. 2.掌握Dom操作中的添加/删除子节点方法. 3.使用setT ...

  7. WeMall商城系统的Android app商城中的wemall-mobile代码

    wemall-mobile是基于WeMall的android app商城,只需要在原商城目录下上传接口文件即可完成服务端的配置,客户端可定制修改. [适合研究学习,支持wemall3.x版本] 1.快 ...

  8. PHP语言开发微信公众平台(订阅号)之注册

    1.百度搜索"微信公众平台" 2.选择微信公众平台官网并单击打开 3.进入官网页面,单击 "立即注册" 进入注册页面 4.进入注册页面,单击订阅号 5.进入订阅 ...

  9. adt的问题An internal error has occurred. After scene creation, #init() must be called

    这个问题困扰了我好久,我也尝试去百度.google无济于事啊,让我寝食难安,太难受了,我把它贴出来,希望后人不绕弯子... 解决办法: 即可,解决这一个问题,现在酣畅淋漓,挥洒自如的capy代码了

  10. 机器学习基石 1 The Learning Problem

    机器学习基石 1 The Learning Problem Introduction 什么是机器学习 机器学习是计算机通过数据和计算获得一定技巧的过程. 为什么需要机器学习 1 人无法获取数据或者数据 ...