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工厂设计模式初步
没有利用反射机制定义的简单工厂类 interface Fruit{ public void eat(); } class Apple implements Fruit{ public void eat ...
- openSUSE设置局域网的时间同步
- [USACO 13NOV]No Change
Description Farmer John is at the market to purchase supplies for his farm. He has in his pocket K c ...
- [USACO17JAN]Promotion Counting晋升者计数
题目描述 奶牛们又一次试图创建一家创业公司,还是没有从过去的经验中吸取教训--牛是可怕的管理者! 为了方便,把奶牛从 1 \cdots N(1 \leq N \leq 100, 000)1⋯N(1≤N ...
- UVA11795 Mega Man's Mission
状压dp #include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> ...
- 计蒜客NOIP2017提高组模拟赛(五)day1-展览
传送门 发现这题选或不选对状态的优劣程度不会产生影响,如果已经确定了两个数a和b,那么最优的首项和公比也都是唯一确定的, 与对于后面的数x,加进去也好不加进去也好,首项和公比依旧是原来的 于是我们用尺 ...
- 2015 多校联赛 ——HDU5350(huffman)
Problem Description MZL is a mysterious mathematician, and he proposed a mysterious function at his ...
- 使用WebStorm进行javascript调试
曾经的选择是使用火狐浏览器的Firebug插件,具体的用法到时候在细说,这篇文章登场的是开发静态网页及javascript的利器--webstorm. 一.相关软件安装和配置 安装WebStorm ...
- 运行C++程序是出现错误:cannot open Debug/1.exe for writing
今天,打开VC6.0环境编了个小程序,谁知给我报了“cannot open Debug/1.exe for writing”这样一个错,然后,我就纳闷了,这是什么错丫? 想了半天,后想通,为什么会这样 ...
- Python与C的简单比较(Python3.0)
Python可以说是目前最火的语言之一了,人工智能的兴起让Python一夜之间变得家喻户晓,Python号称目前最最简单易学的语言,现在有不少高校开始将Python作为大一新生的入门语言.本萌新也刚开 ...