python 3 黑色魔法元类初探
最近读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 黑色魔法元类初探的更多相关文章
- python基础——使用元类
python基础——使用元类 type() 动态语言和静态语言最大的不同,就是函数和类的定义,不是编译时定义的,而是运行时动态创建的. 比方说我们要定义一个Hello的class,就写一个hello. ...
- Python基础:元类
一.概述 二.经典阐述 三.核心总结 1.类的创建过程 2.元类的使用惯例 四.简单案例 1.默认行为 2.使用元类 五.实践为王 一.概述 Python虽然是多范式的编程语言,但它的数据模型却是 纯 ...
- Python中的元类(metaclass)
推荐+收藏:深刻理解Python中的元类(metaclass) 做一些笔记学习学习: 在大多数编程语言中,类就是用来描述如何生成一个对象的代码段,在Python中类也是一个对象,这个(类)对象自身拥有 ...
- [转]深刻理解Python中的元类(metaclass)以及元类实现单例模式
使用元类 深刻理解Python中的元类(metaclass)以及元类实现单例模式 在看一些框架源代码的过程中碰到很多元类的实例,看起来很吃力很晦涩:在看python cookbook中关于元类创建单例 ...
- 什么是python中的元类
所属网站分类: python高级 > 面向对象 作者:goodbody 原文链接: http://www.pythonheidong.com/blog/article/11/ 来源:python ...
- Python之面向对象元类
Python之面向对象元类 call方法: class People: def __init__(self,name): self.name=name # def __call__(self, *ar ...
- [Python之路] 元类(引申 单例模式)
一.类也是对象 当我们定义一个变量或者函数的时候,我们可以在globals()的返回值字典中找到响应的映射: def A(): print("This is function A" ...
- Python 中的元类到底是什么?这篇恐怕是最清楚的了
类作为对象 在理解元类之前,您需要掌握 Python 的类.Python 从 Smalltalk 语言中借用了一个非常特殊的类概念. 在大多数语言中,类只是描述如何产生对象的代码段.在 Python ...
- Python面向对象06 /元类type、反射、函数与类的区别、特殊的双下方法
Python面向对象06 /元类type.反射.函数与类的区别.特殊的双下方法 目录 Python面向对象06 /元类type.反射.函数与类的区别.特殊的双下方法 1. 元类type 2. 反射 3 ...
随机推荐
- 初探java对象比较
判断两个对象的属性值是否相等的方法, class Book{ private String title; private double price; public Book(String title, ...
- 原生http请求封装
满血复活,今天开始开始更新博客.随着es6的普遍应用,promise属性也随之用之普遍,我们在一些项目中,为了避免引入一些http库,节省空间,就简单将原生http请求做了封装处理,封装代码如下:(其 ...
- mysql之子查询作业
#数据准备drop table if exists class;create table class( class_no int(2) unsigned zerofill primary key ...
- Bootstrap中关闭第二个模态框时出现的问题和解决办法
Bootstrap中关闭第二个模态框时出现的问题和解决办法 1.关闭第二个模态框时,第一个模态框跟着消失. 解决办法: 第二个模态框的代码不要写在第一个模态框里面,确保两个模态框相对独立; 2.关闭第 ...
- Linux使用踩坑记
Ubuntu安装坑: 1.对于新手第一次安装ubuntu,特殊情况会出现因为分辨率问题导致安装界面不全,无法进行下一步操作. 解决方案:使用alt+鼠标左键拖动屏幕Linux文件名乱码问题: 2.因为 ...
- 【NOIP2017 OFO】
·奇怪的标题可能预示着这一篇博文不是讲算法或者分享题目的吧. [一只情绪化的兔子] 今年的11月12日出奇地比去年温暖.两场比赛结束后的我们在临走前去尝试了OFO共享单车,在成都电子科技大学 ...
- 【USACO12JAN】视频游戏的连击Video Game Combos
题目描述 Bessie is playing a video game! In the game, the three letters 'A', 'B', and 'C' are the only v ...
- bzoj2149拆迁队 斜率优化dp+分治
2149: 拆迁队 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 397 Solved: 177[Submit][Status][Discuss] ...
- [51nod1239欧拉函数之和]
来自FallDream的博客,未经允许,请勿转载,谢谢 --------------------------------------------- 给定n,求$S(n)=\sum_{i=1}^{n}\ ...
- Vue2学习结合bootstrapTable遇到的问题
Vue2学习 项目中在使用bootstrapTable的时候,在table里面会有操作结合vue使用过程中点击相应的操作不会起作用 解决办法 1.把事件绑定到父元素上即可,但要判断什么样的需要点击,用 ...