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上 很热的帖子.提问 ...
随机推荐
- 【树形dp】hdu6035 Colorful Tree
非常棒的题解,我就不复述了:http://blog.csdn.net/Bahuia/article/details/76141574 O(n) #include<cstdio> #incl ...
- 【分块】【树套树】bzoj2141 排队
考虑暴力更新的情况,设swap的是L,R位置的数.swap之后的逆序对数应该等于:之前的逆序对数+[L+1,R-1]中比 L位置的数 大的数的个数-[L+1,R-1]中比 L位置的数 小的数的个数-[ ...
- segmentfault hackthon比赛感悟
之前本来是打算用node好好系统的写下程序,写下博客. 这两天因为segmentfault hackthon比赛,所以就没更新.写这篇博客的目的,是为了说明自己參赛的感悟. 今天比赛,能够说自己特别失 ...
- java 从网络Url中下载文件
转自:http://blog.csdn.net/xb12369/article/details/40543649 /** * 从网络Url中下载文件 * @param urlStr * @param ...
- Linux Shell编程与编辑器使用详解
<Linux Shell编程与编辑器使用详解> 基本信息 作者: 刘丽霞 杨宇 出版社:电子工业出版社 ISBN:9787121207174 上架时间:2013-7-22 出版日期:201 ...
- docker部署golang+redis聊天室
博客地址:http://www.niu12.com/article/7#####1.项目源码: https://github.com/ZQCard/webchat#####2.项目构成 websock ...
- lua调试的工具选择
近期看到一个关于vs的lua调试插件, 装了vs2012试了下, 忍不住发此文总结下lua各种调试工具 Decoda 这是现今地球上调试lua5.1最方便的工具, 没有之中的一个. 强大的注入式调试, ...
- 【好】strong-password-checker,我自己做出来的:)
我自己做出来的,分了几种情况来考虑.(再后面有加了注释的版本) https://leetcode.com/problems/strong-password-checker/ // 加油! public ...
- Index 和 Type 的区别
原文: Index vs. Type By Adrien Grand 译者: fengchang 对于 ES 的新用户来说,有一个常见的问题:要存储一批新的数据时,应该在已有 index 里新建一个 ...
- 第二章:ES索引说明
1."_boost": 20评分的权重(排序) 2."analyzer": "ik"中文分词 "analyzer": & ...