最近读django源码,发现必须了解元类才能理解一些很神奇的行为.

发现元类实际上是控制class的创建过程.比如类B继承某个看似平淡无奇的类A之后,你在类B中定义的属性或方法可能会遭到彻底改变.

假设我们想实现这么一种需求:

创建一个类Child,在这个类中定义的种种字符串属性,都可以当做对应的函数那样调用.例如:

class Child():

f1='print'

随后,Child.f1就完全和内建函数print等价了.Child.f1('abc')能够打印出abc这个字符串.

这样来说,元类的用途看起来可以是:一些高手设计了一个在幕后做了很多工作的元类,另一些开发人员只需要简单地继承这个元类或者这个元类的子类,敲几个属性定义的代码,就能实现很多复杂的功能.django就是这样的.比如它的model.Models就充分利用了这种魔法.

下面从代码层面展示元类具体是怎么运作的:

class MyMeta(type):
def __new__(cls, name, parents, attrs):
for k,v in locals().items():
if isinstance(v,dict):
for k2,v2 in v.items():
print(k,'|',k2,'|',type(v2),'|',v2)
else:
print(k,'|',v)
return type.__new__(cls, name, parents, attrs) class Parent1(type):
pass class Parent2(object):
pass class Parent3():
pass class AbstractChild(Parent1,Parent2,Parent3,metaclass=MyMeta):
pass class Child(AbstractChild): f1 = 1
f2 = sorted
f3 = int class classinchild():
pass @staticmethod
def stcm():
pass @classmethod
def clsm(cls):
pass def insm(self):
pass print('-'*60) class EvalMeta(type):
def __new__(cls, name, parents, attrs):
new_attrs={}
for k,v in attrs.items():
if not k.startswith('__') and isinstance(v,str):
new_attrs[k] = eval(v)
else:
new_attrs[k] = v
return type.__new__(cls, name, parents, new_attrs) class AbstractChild(metaclass=EvalMeta):
pass class Child(AbstractChild):
f1='print'
f2='sorted' if __name__=='__main__':
x=Child()
x.f1('invoke f1 as print function')
print('invoke f2 as sorted function:',Child.f2([3,2,1]))

结果:

>>>
name | AbstractChild
cls | <class '__main__.MyMeta'>
parents | (<class '__main__.Parent1'>, <class '__main__.Parent2'>, <class '__main__.Parent3'>)
attrs | __module__ | <class 'str'> | __main__
attrs | __qualname__ | <class 'str'> | AbstractChild
name | Child
cls | <class '__main__.MyMeta'>
parents | (<class '__main__.AbstractChild'>,)
attrs | stcm | <class 'staticmethod'> | <staticmethod object at 0x0000000003075C50>
attrs | clsm | <class 'classmethod'> | <classmethod object at 0x000000000309CA58>
attrs | __module__ | <class 'str'> | __main__
attrs | insm | <class 'function'> | <function Child.insm at 0x0000000003139400>
attrs | __qualname__ | <class 'str'> | Child
attrs | f1 | <class 'int'> | 1
attrs | f3 | <class 'type'> | <class 'int'>
attrs | f2 | <class 'builtin_function_or_method'> | <built-in function sorted>
attrs | classinchild | <class 'type'> | <class '__main__.Child.classinchild'>
------------------------------------------------------------
invoke f1 as print function
invoke f2 as sorted function: [1, 2, 3]
>>>

python 3 黑色魔法元类初探的更多相关文章

  1. python基础——使用元类

    python基础——使用元类 type() 动态语言和静态语言最大的不同,就是函数和类的定义,不是编译时定义的,而是运行时动态创建的. 比方说我们要定义一个Hello的class,就写一个hello. ...

  2. Python基础:元类

    一.概述 二.经典阐述 三.核心总结 1.类的创建过程 2.元类的使用惯例 四.简单案例 1.默认行为 2.使用元类 五.实践为王 一.概述 Python虽然是多范式的编程语言,但它的数据模型却是 纯 ...

  3. Python中的元类(metaclass)

    推荐+收藏:深刻理解Python中的元类(metaclass) 做一些笔记学习学习: 在大多数编程语言中,类就是用来描述如何生成一个对象的代码段,在Python中类也是一个对象,这个(类)对象自身拥有 ...

  4. [转]深刻理解Python中的元类(metaclass)以及元类实现单例模式

    使用元类 深刻理解Python中的元类(metaclass)以及元类实现单例模式 在看一些框架源代码的过程中碰到很多元类的实例,看起来很吃力很晦涩:在看python cookbook中关于元类创建单例 ...

  5. 什么是python中的元类

    所属网站分类: python高级 > 面向对象 作者:goodbody 原文链接: http://www.pythonheidong.com/blog/article/11/ 来源:python ...

  6. Python之面向对象元类

    Python之面向对象元类 call方法: class People: def __init__(self,name): self.name=name # def __call__(self, *ar ...

  7. [Python之路] 元类(引申 单例模式)

    一.类也是对象 当我们定义一个变量或者函数的时候,我们可以在globals()的返回值字典中找到响应的映射: def A(): print("This is function A" ...

  8. Python 中的元类到底是什么?这篇恐怕是最清楚的了

    类作为对象 在理解元类之前,您需要掌握 Python 的类.Python 从 Smalltalk 语言中借用了一个非常特殊的类概念. 在大多数语言中,类只是描述如何产生对象的代码段.在 Python ...

  9. Python面向对象06 /元类type、反射、函数与类的区别、特殊的双下方法

    Python面向对象06 /元类type.反射.函数与类的区别.特殊的双下方法 目录 Python面向对象06 /元类type.反射.函数与类的区别.特殊的双下方法 1. 元类type 2. 反射 3 ...

随机推荐

  1. 修改 iOS AppIcon

    有一次看到亚马逊的客户端打开后,就提示 icon 改变了,回桌面一看,竟然真的变了.然后就上网搜索是怎么实现的,参照着写了一个小 demo ,权当笔记. 首先,导入图片到项目的中,如下图.不要导入到 ...

  2. [UOJ 41]【清华集训2014】矩阵变换

    Description 给出一个 $N$ 行 $M$ 列的矩阵A, 保证满足以下性质: $M > N$. 矩阵中每个数都是 $[0, N]$ 中的自然数. 每行中, $[1, N]$ 中每个自然 ...

  3. [SCOI2016]背单词

    题目描述 Lweb 面对如山的英语单词,陷入了深深的沉思,”我怎么样才能快点学完,然后去玩三国杀呢?“.这时候睿智的凤老师从远处飘来,他送给了 Lweb 一本计划册和一大缸泡椒,他的计划册是长这样的: ...

  4. [HNOI2001]求正整数

    题目描述 对于任意输入的正整数n,请编程求出具有n个不同因子的最小正整数m. 例如:n=4,则m=6,因为6有4个不同整数因子1,2,3,6:而且是最小的有4个因子的整数. 输入输出格式 输入格式: ...

  5. Codeforces Round #430 C. Ilya And The Tree

    Ilya is very fond of graphs, especially trees. During his last trip to the forest Ilya found a very ...

  6. hdu 4031 attack 线段树区间更新

    Attack Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others)Total Subm ...

  7. VC++6.0连接MySQL数据库(MySQL API)

    一.MySQL的安装   Mysql的安装去官网下载就可以...最新的是5.7版本..二.VC6.0的设置(1)打开VC6.中选0 工具栏Tools菜单下的Options选项,在Directories ...

  8. Windows提示dll组件丢失

    我们在运行一些软件时,常常会遇到这种问题.下面就来提供解决办法: 登陆网址:www.dll-files.com. 找到页面的搜索部分,并且进行相关搜索: 下图显示了相关的dll下载链接. 下载解压即可 ...

  9. dev gridcontrol 无法编辑 解决方案

    1.确认表格打开编辑 gridView1.OptionsBehavior.Editable = True 2.确认列打开编辑 gridView1.Columns("Name").O ...

  10. 好久没用IJ写Java 之 《求输入的一个数中包含奇数、偶数、零的个数》

    /** *Created by xuzili at 22:12 on 2018/4/4 */ // 以上注释使用了IntelliJ Idea的File-Settings-Editor-Live Tem ...