python黑魔法之metaclass
最近了解了一下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的更多相关文章
- Python 黑魔法 --- 描述器(descriptor)
Python 黑魔法---描述器(descriptor) Python黑魔法,前面已经介绍了两个魔法,装饰器和迭代器,通常还有个生成器.生成器固然也是一个很优雅的魔法.生成器更像是函数的行为.而连接类 ...
- (转)Python黑魔法 --- 异步IO( asyncio) 协程
转自:http://www.jianshu.com/p/b5e347b3a17c?from=timeline Python黑魔法 --- 异步IO( asyncio) 协程 作者 人世间 关注 201 ...
- python 黑魔法 ---上下文管理器(contextor)
所谓上下文 计算机上下文(Context)对于我而言,一直是一个很抽象的名词.就像形而上一样,经常听见有人说,但是无法和现实认知世界相结合. 最直观的上下文,莫过于小学的语文课,经常会问联系上下文,推 ...
- Python 黑魔法(持续收录)
Python 黑魔法(持续收录) zip 对矩阵进行转置 a = [[1, 2, 3], [4, 5, 6]] print(list(map(list, zip(*a)))) zip 反转字典 a = ...
- python 黑魔法收集--已结
awesome python 中文大全 Fabric , pip, virtualenv 内建函数好文 awesome python 奇技淫巧 一句话求阶乘 from functools import ...
- python 中的metaclass和baseclasses
提前说明: class object 指VM中的class 对象,因为python一切对象,class在VM也是一个对象,需要区分class对象和 class实例对象. class instance ...
- python中的metaclass
首先看下面的代码: # coding: utf-8 class Test(object): pass print Test.__class__ # type print Test.__base__ # ...
- python 元类——metaclass
from stack overflow:http://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python Classes ...
- python——type()、metaclass元类和精简ORM框架
1.type()函数 if __name__ == '__main__': h = hello() h.hello() print(type(hello)) print(type(h)) Hello, ...
随机推荐
- MongoDB分布式
结构: ShardServer1:27020 ShardServer2:27021 ShardServer3:27022 ShardServer4:27023 ConfigServer:27100 R ...
- [PKU2389]Bull Math (大数运算)
Description Bulls are so much better at math than the cows. They can multiply huge integers together ...
- AVFoundation自定义拍照
0.AVCapture <AVFoundation/AVFoundation.h> 媒体采集需要的几个对象: 1.AVCaptureDevice: 代表抽象的硬件设备(如前置摄像头,后置 ...
- swift -- 静态变量static
import UIKit class ViewController: UIViewController { //静态变量 swift中的static静态变量,只能在这里声明,不能在方法中声明 ...
- iOS UI控件总结(全)
1.UIButton UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect]; btn.frame = CGRectMake ...
- SQL基本编程,分支语句,循环语句,存储过程,触发器
基本编程: 定义变量 declare @变量名 数据类型 赋值 set @变量名 = 值 select @变量名 = 值 取值打印 select @变量名 print @变量名 映射到结果集 打印到消 ...
- FDG内存分配器笔记
FDG: 大规模并行系统中的动态内存分配器由于需要全局同步(记账) ,导致性能急剧下降. 代码解析 1.superblock 类中包含两个变量,两个函数.默认superblock大小为2048 ite ...
- 如何修改vsftpd的默认根目录/var/ftp/pub到另一个目录?
修改ftp的根目录只要修改/etc/vsftpd/vsftpd.conf文件即可: 加入如下几行: local_root=/var/www/html chroot_local_user=YES ano ...
- iOS 文本转语音(TTS)详解:Swift
上一篇博客讲解了iOS的speech FrameWork语音识别的功能:http://www.cnblogs.com/qian-gu-ling/p/6599670.html,对应的这篇博客就写一下文本 ...
- 按条件生成j随机json包:randomjson
前端开发中,在做前后端分离的时候,经常需要手写json数据,有2个问题特别揪心: 1,数据是写死的,不能按一定的条件随机生成长度不一,内容不一的数据 2,写数组的时候,如果有很多条,需要一条一条地写, ...