最近了解了一下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. 每天一个linux命令(46)--rcp命令

    rcp代表“remote file copy”(远程文件拷贝).该命令用于在计算机之间拷贝文件.rcp命令有两种格式.第一种格式用于文件到文件的拷贝,第二种格式用于文件或目录拷贝到另一个目录中. 1. ...

  2. 超出区域文字显示为省略号或者剪切效果——CSS的生僻操作

    每门语言总有那么一些不太常用,却又不可或缺的语法操作.下面说一下,在HTML文件中,如何设置用 "省略号" 和 "剪切" 代替大量文字的效果. 以下是HTML的 ...

  3. 利用CSS3 animation绘制动态卡通人物,无需使用JS代码

    此外博主原创,转载请注明出处:谢谢~ 效果图: 其中云.风车.尾巴是动态的: 以下是代码: <!DOCTYPE html> <html lang="en"> ...

  4. c#基础语句——分支语句

    一.if...else... if是如果的意思,else是另外的意思,if后面跟(),括号内为判断条件,如果符合条件则进入if语句执行命令.如果不符合则不进入if语句.else后不用加条件,但是必须与 ...

  5. 1602: [Usaco2008 Oct]牧场行走

    1602: [Usaco2008 Oct]牧场行走 Time Limit: 5 Sec  Memory Limit: 64 MB Submit: 1211  Solved: 616 [Submit][ ...

  6. git merge 冲突

    当前分支为 master 然后操作时: git merge dev 发现有文件冲突. 当我们倾向于使用dev 分支的代码时,可以使用以下命令: git checkout --theirs src/ma ...

  7. GreenDao 工具类 --- 使用 Json 快速生成 Bean、表及其结构,"炒鸡"快!

    作者:林冠宏 / 指尖下的幽灵 掘金:https://juejin.im/user/587f0dfe128fe100570ce2d8 博客:http://www.cnblogs.com/linguan ...

  8. 关于Trie KMP AC自动机

    个人认为trie,KMP,AC自动机是思想非常明确的,AC自动机的性质是与KMP算法的思想类似的(失配后跳转) 而KMP是线性的,AC自动机是在tire树上跑KMP,为方便那些不会用指针的小朋友(我也 ...

  9. 樱花的季节,教大家用canvas画出飞舞的樱花树

    又到了樱花的季节,教大家使用canvas画出飞舞的樱花树效果. 废话少说,先看效果. 演示效果地址:http://suohb.com/work/tree4.htm 查看演示效果 第一步,我们先画出一棵 ...

  10. C#实现GridView导出Excel

    using System.Data;using System.Web;using System.Web.UI;using System.Web.UI.WebControls;using System. ...