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, ...
随机推荐
- php 手动搭建环境
php手动搭建环境有好多种组合,版本号不一致,会导致搭建失败. 我搭建的组合是: php5.6+MySQL5.6+Apache2.4的组合. 一.PHP语言包下载 首先从官网上下载php5.6 htt ...
- VS2010 MSDN的介绍
5 cout << temp; 博客园第一篇文章的开始. VS2010 MSDN的文档介绍 https://msdn.microsoft.com/zh-cn/library/dd8 ...
- php和js中,utf-8编码转成base64编码
1.php下转化base64编码 php中,文本文件的编码决定了程序变量的编码,比如以下代码在不同编码的php文件中,展示的效果也是不一样的 <?php $word = '严'; echo ba ...
- iOS回顾笔记(03) -- 自定义View的封装和xib文件的使用详解
iOS回顾笔记(03) -- 自定义View的封装和xib文件的使用详解 iOS开发中,我们常常将一块View封装起来,以便于统一管理内部的子控件.如iOS回顾笔记(02)中的"书" ...
- Filebeat issue 排查--single.go:140: ERR Connecting error publishing events (retrying): dial tcp ****:5044: i/o timeout
我个人用docker搭建了一套日志分析平台:ELK+Filebeat 在正常跑了半个多月之后,Kibana刷新日志时突然发现日志不在更新了,停在某个时刻,就再也没有新log. 首先我查看了elk,lo ...
- C#中运算符的应用
c#中的运算符(只说我自己熟悉和常用的)一.算数运算:加 +减 -乘 *除 / (整型的除法是不算小数点的,也就是说结果是整数,余数舍去了,求余数看下面)求余数 % 加减乘好理解,整型的除法和求余数因 ...
- HTTP 返回状态代码详解
1xx(临时响应)表示临时响应并需要请求者继续执行操作的状态代码. 100(继续)请求者应当继续提出请求. 服务器返回此代码表示已收到请求的第一部分,正在等待其余部分:101(切换协议)请求者已要求服 ...
- Python中的日期和时间
感觉C语言作为一门编程的入门语言还是很好的,相比较之下,Python为代表的一些语言,适合很多非计算机专业的编程入门学习. Python 日期和时间 Python 程序能用很多方式处理日期和时间,转换 ...
- iOS回顾笔记(08) -- 自定义Cell的类型和创建步骤总结
iOS回顾笔记(08) -- 自定义Cell的类型和创建步骤总结 项目中我们常见的自定义cell主要分为两种 等高cell:如应用列表.功能列表 非等高cell:如微博列表.QQ聊天页面 下面对这 ...
- Android使用Sugar ORM创建数据库报no such table:...的解决方法
在学习使用Android开源框架Sugar ORM时,只是做了开始的创建数据库的操作就报出如下的异常信息 android.database.sqlite.SQLiteException: no suc ...