Python-深入理解元类(metaclass)
1.使用 type 动态创建类(type 是一个类, 用来创建类对象的元类, 所以也可以继承)
type("Person", (), {"name": "John"})
2.元类
Python 中类也是对象, 元类就是创建这些类对象的类, 可以理解为
MyClass = MetaClass()
MyObject = MyClass()
3.type实际上是一个元类, type就是Python在背后用来创建所有类的元类, 类似 str 是创建字符串对象的类, int 是创建整数的类, type 就是创建类的类
4.Python 中所有东西都是对象!
>>> age = 35
>>> age.__class__
<type 'int'>
>>> name = 'bob'
>>> name.__class__
<type 'str'>
>>> def foo(): pass
>>>foo.__class__
<type 'function'>
>>> class Bar(object): pass
>>> b = Bar()
>>> b.__class__
<class '__main__.Bar'>
那么对于任何一个 __class__ 的 __class__ 属性又是什么呢?
>>> a.__class__.__class__
<type 'type'>
>>> age.__class__.__class__
<type 'type'>
>>> foo.__class__.__class__
<type 'type'>
>>> b.__class__.__class__
<type 'type'>
结论: 元类就是创建类这种对象的东西, type就是Python的内建元类(xx.__class__.__class__为 type )
5.__metaclass__ 属性
可以在写一个类的时候为其添加 __metaclass__ 属性
class Foo(object):
__metaclass__ = something…
pass
如果你这么做了, Python就会用元类来创建类Foo, 小心点, 这里面有些技巧, 你首先写下class Foo(object), 但是类对象Foo还没有在内存中创建, Python会在类的定义中寻找__metaclass__属性, 如果找到 了, Python就会用它来创建类Foo, 如果没有找到, 就会用内建的type来创建这个类
6.深入理解下上一步中的 __metaclass__
class Foo(Bar):
pass
Foo中有__metaclass__这个属性吗?如果是, Python会在内存中通过__metaclass__创建一个名字为Foo的类对象(我说的是类对象, 请紧跟我的思路), 如果Python没有找到__metaclass__, 它会继续在Bar(父类)中寻找__metaclass__ 属性, 并尝试做和前面同样的操作, 如果Python在任何父类中都找不到__metaclass__, 它就会在模块层次中去寻找 __metaclass__, 并尝试做同样的操作, 如果还是找不到__metaclass__, Python就会用内置的type来创建这个类对象
现在的问题就是, 你可以在__metaclass__中放置些什么代码呢?答案就是: 可以创建一个类对象的东西, 那么什么可以用来创建一个类呢?type, 或者任何使用到type或者子类化type的东东都可以(像1中使用type创建类对象)
7.自定义元类
条件:模块里所有的类的属性都应该是大写形式
实现(__metaclass__实际上可以被任意调用, 它并不需要一定是一个正式的类):
# 元类会自动将你通常传给‘type’的参数作为自己的参数传入
def upper_attr(future_class_name, future_class_parents, future_class_attr):
'''返回一个类对象,将属性都转为大写形式'''
# 选择所有不以'__'开头的属性
attrs = ((name, value) for name, value in future_class_attr.items() if not name.startswith('__'))
# 将它们转为大写形式
uppercase_attr = dict((name.upper(), value) for name, value in attrs) # 通过'type'来做类对象的创建
return type(future_class_name, future_class_parents, uppercase_attr) __metaclass__ = upper_attr # 这会作用到这个模块中的所有类 class Foo(object):
# 我们也可以只在这里定义__metaclass__,这样就只会作用于这个类中
bar = 'bip' print hasattr(Foo, 'bar')
# 输出: False
print hasattr(Foo, 'BAR')
# 输出:True f = Foo()
print f.BAR
# 输出:'bip'
用OOP实现:
# 请记住,'type'实际上是一个类,就像'str'和'int'一样
# 所以,你可以从type继承
class UpperAttrMetaClass(type):
# __new__ 是在__init__之前被调用的特殊方法
# __new__是用来创建对象并返回之的方法
# 而__init__只是用来将传入的参数初始化给对象
# 你很少用到__new__,除非你希望能够控制对象的创建
# 这里,创建的对象是类,我们希望能够自定义它,所以我们这里改写__new__
# 如果你希望的话,你也可以在__init__中做些事情
# 还有一些高级的用法会涉及到改写__call__特殊方法,但是我们这里不用
def __new__(upperattr_metaclass, future_class_name, future_class_parents, future_class_attr):
attrs = ((name, value) for name, value in future_class_attr.items() if not name.startswith('__'))
uppercase_attr = dict((name.upper(), value) for name, value in attrs)
return type(future_class_name, future_class_parents, uppercase_attr)
8.为什么要使用元类?
现在回到我们的大主题上来, 究竟是为什么你会去使用这样一种容易出错且晦涩的特性?好吧, 一般来说, 你根本就用不上它:
“元类就是深度的魔法,99%的用户应该根本不必为此操心。如果你想搞清楚究竟是否需要用到元类,那么你就不需要它。那些实际用到元类的人都非常清楚地知道他们需要做什么,而且根本不需要解释为什么要用元类。” —— Python界的领袖 Tim Peters
元类的主要用途是创建API, 一个典型的例子是Django ORM, 它允许你像这样定义:
class Person(models.Model):
name = models.CharField(max_length=30)
age = models.IntegerField()
但是如果你像这样做的话:
guy = Person(name='bob', age='')
print guy.age
这并不会返回一个IntegerField对象, 而是会返回一个int, 甚至可以直接从数据库中取出数据, 这是有可能的, 因为 models.Model定义了__metaclass__, 并且使用了一些魔法能够将你刚刚定义的简单的Person类转变成对数据库的一个复杂hook, Django框架将这些看起来很复杂的东西通过暴露出一个简单的使用元类的API将其化简, 通过这个API重新创建代码, 在背后完成真正的工作
9.小结
Python中的一切都是对象, 它们要么是类的实例, 要么是元类的实例, 除了type, type实际上是它自己的元类
摘抄自:http://python.jobbole.com/21351/
Python-深入理解元类(metaclass)的更多相关文章
- [转]深刻理解Python中的元类(metaclass)以及元类实现单例模式
使用元类 深刻理解Python中的元类(metaclass)以及元类实现单例模式 在看一些框架源代码的过程中碰到很多元类的实例,看起来很吃力很晦涩:在看python cookbook中关于元类创建单例 ...
- Python中的元类(metaclass)
推荐+收藏:深刻理解Python中的元类(metaclass) 做一些笔记学习学习: 在大多数编程语言中,类就是用来描述如何生成一个对象的代码段,在Python中类也是一个对象,这个(类)对象自身拥有 ...
- 深刻理解Python中的元类metaclass(转)
本文由 伯乐在线 - bigship 翻译 英文出处:stackoverflow 译文:http://blog.jobbole.com/21351/ 译注:这是一篇在Stack overflow上很热 ...
- 深刻理解Python中的元类(metaclass)
译注:这是一篇在Stack overflow上很热的帖子.提问者自称已经掌握了有关Python OOP编程中的各种概念,但始终觉得元类(metaclass)难以理解.他知道这肯定和自省有关,但仍然觉得 ...
- [转] 深刻理解Python中的元类(metaclass)
非常详细的一篇深入讲解Python中metaclass的文章,感谢伯乐在线-bigship翻译及作者,转载收藏. 本文由 伯乐在线 - bigship 翻译.未经许可,禁止转载!英文出处:stacko ...
- 深刻理解Python中的元类(metaclass)【转】
译注:这是一篇在Stack overflow上很热的帖子.提问者自称已经掌握了有关Python OOP编程中的各种概念,但始终觉得元类(metaclass)难以理解.他知道这肯定和自省有关,但仍然觉得 ...
- 深刻理解Python中的元类(metaclass)以及元类实现单例模式
在理解元类之前,你需要先掌握Python中的类.Python中类的概念借鉴于Smalltalk,这显得有些奇特.在大多数编程语言中,类就是一组用来描述如何生成一个对象的代码段.在Python中这一点仍 ...
- 深入理解Python中的元类(metaclass)
原文 译注:这是一篇在Stack overflow上很热的帖子.提问者自称已经掌握了有关Python OOP编程中的各种概念,但始终觉得元类(metaclass)难以理解.他知道这肯定和自省有关,但仍 ...
- python——深刻理解Python中的元类(metaclass)
译注:这是一篇在Stack overflow上 很热的帖子.提问者自称已经掌握了有关Python OOP编程中的各种概念,但始终觉得元类(metaclass)难以理解.他知道这肯定和自省有关,但仍然觉 ...
- python中的元类metaclass
本文是一个转载的,因为原文写的太好了,所以直接copy过来吧. 原文请看:http://blog.jobbole.com/21351/ 译注:这是一篇在Stack overflow上 很热的帖子.提问 ...
随机推荐
- 【LIS】【递推】Gym - 101246H - ``North-East''
x坐标排序,y坐标当权值,同一个x坐标的,y从大到小排. 求f(i)表示以i结尾的LIS以后,从后向前枚举,不断更新一个max数组,max(i)代表最长上升子序列为i时,当前的 结尾的最大值是多少. ...
- 【贪心】hdu5969 最大的位或
对于右端点r和左端点l,考虑他们的二进制位从高到低,直到第一位不同的为止. 更高的都取成相同的,更低的都取成1. 比如 101011110001 101011101001 101011111111 # ...
- [JZOJ5425]数论
题目大意: 给你$n,m$,求$\displaystyle{\sum_{i=1}^{n}\sum_{j=1}^{m}}\min(\lfloor\frac{n}{i}\rfloor,\lfloor\fr ...
- 浙南联合训练赛 H - The number of positions
Petr stands in line of n people, but he doesn't know exactly which position he occupies. He can say ...
- Codeforces Round #345 (Div. 2) B. Beautiful Paintings 暴力
B. Beautiful Paintings 题目连接: http://www.codeforces.com/contest/651/problem/B Description There are n ...
- HDU 5631 Rikka with Graph 暴力 并查集
Rikka with Graph 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5631 Description As we know, Rikka ...
- 使用Javascript实现ajax示例
使用原始的javascript实现ajax <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"& ...
- 原生js封装的一些jquery方法
用js封装一些常用的jquery方法 记录一下 hasClass:判断是否有class function hasClass(ele, cls) { if (!ele || !cls) return f ...
- Linux设备模型(总结)
转:http://www.360doc.com/content/11/1219/16/1299815_173418267.shtml 看了一段时间的驱动编程,从LDD3的hello wrod到后来的字 ...
- 四种有能力取代Cookies的客户端Web存储方案
目前在用户的网络浏览器中保存大量数据需要遵循几大现有标准,每一种标准都拥有自己的优势.短板.独特的W3C标准化状态以及浏览器支持级别.但无论如何,这些标准的实际表现都优于广泛存在的cookies机制. ...