Python骚操作之动态定义函数


Posted in Python onMarch 26, 2019

在 Python 中,没有可以在运行时简化函数定义的语法糖。然而,这并不意味着它就不可能,或者是难以实现。

from types import FunctionType

foo_code = compile('def foo(): return "bar"', "<string>", "exec")
foo_func = FunctionType(foo_code.co_consts[0], globals(), "foo")

print(foo_func())

输出:bar

剖析

逐行检视代码,你会发现语言/解释器的屏障是多么脆弱。

>>> from types import FunctionType

Python 文档通常不会列出那些非用于手动创建的类的特征(这是完全合理的)。有三种方法可以解决这个问题:help()、inspect(无法查看内置方法)、以及最后的解决方案,即查看 CPython 源代码。

在本例中,help() 与 inspect 都可以完成工作,但是查看实际的源代码,则会揭示出关于数据类型的更多细节。

>>> from inspect import signature
>>> signature(FunctionType)
<Signature (code, globals, name=None, argdefs=None, closure=None)>

1. code

内部是一个PyCodeobject,作为types.CodeType对外开放。非内置方法拥有一个__code__属性,该属性保存了相应的代码对象。利用内置 compile() 方法,可以在运行期创建types.CodeType对象。

2. globals

如果一个函数引用的变量不是在局部定义的,而是作为参数转入、由默认参数值提供、或者通过闭包上下文提供,则它会在 globals 字典中查找。

内置的 globals() 方法会返回一个对当前模块的全局符号表(global symbol table)的引用 ,因此能被用来提供一个总是与当前表的状态相一致的字典。传入任意其它的字典也是可以的(FunctionType((lambda: bar).__code__, {"bar" : "baz"}, "foo")() == "baz")。

3. name(可选)

控制所返回的函数的__name__ 属性。只真正对 lambdas 有用(由于匿名性,它们通常没有名称),并且重命名函数。

4. argdefs(可选)

通过传入一个包含任意类型的对象的元组,提供一个方式来供应默认参数值(def foo(bar="baz"))。(FunctionType((lambda bar: bar).__code__, {}, "foo", (10,))() == 10)。

5. closure(可选)

(如果需要在 CPython(PyPy,Jython,…)以外的其它 Python VM 中执行,可能不应该触及,因为它严重地依赖于实现细节)。

一个cell 对象的元组。创建 cell 对象并非完全是直截了当的,因为需要调用 CPython 的内部组件,但有一个库可以令它更加方便:exalt(无耻的广告)。(译注:这个库是作者开发的。)

>>> foo_code = compile('def foo(): return "bar"', "<string>", "exec")

compile() 是一个内置方法,因此同时也是文档丰富的。

exec 模式被用到,因为定义函数需用多个语句。

>>> foo_func = FunctionType(foo_code.co_consts[0], globals(), "foo")

聚合全部内容,并将动态创建的函数指定给一个变量。

那个被前一句代码编译成的函数,成为了生成的代码对象的第一个常量,因此仅仅指向 foo_code 是不充分的。这是 exec 模式的直接后果,因为生成的代码对象可以包含多个常量。

>>> print(foo_func())

动态生成的函数可以像其它函数一样被调用。

结尾

除了做实验,需要用到动态创建函数的场景很少。

玩耍(Toying around) Python 的内部构件是一种深入学习这门语言的好方法。

如果需要,可以毫不费力地越过解释器/语言的界线。

还是一如既往地:不要滥用语言 (好吧,一点点也无妨,对吧?)

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python深入学习之内存管理
Aug 31 Python
python写入xml文件的方法
May 08 Python
好用的Python编辑器WingIDE的使用经验总结
Aug 31 Python
python中的字符串内部换行方法
Jul 19 Python
python 快速把超大txt文件转存为csv的实例
Oct 26 Python
ZABBIX3.2使用python脚本实现监控报表的方法
Jul 02 Python
Python 多个图同时在不同窗口显示的实现方法
Jul 07 Python
初次部署django+gunicorn+nginx的方法步骤
Sep 11 Python
解决TensorFlow训练内存不断增长,进程被杀死问题
Feb 05 Python
python中plt.imshow与cv2.imshow显示颜色问题
Jul 16 Python
关于python3.9安装wordcloud出错的问题及解决办法
Nov 02 Python
Requests什么的通通爬不了的Python超强反爬虫方案!
May 20 Python
python 将有序数组转换为二叉树的方法
Mar 26 #Python
浅谈Python爬虫基本套路
Mar 25 #Python
我用Python抓取了7000 多本电子书案例详解
Mar 25 #Python
详解python:time模块用法
Mar 25 #Python
Python minidom模块用法示例【DOM写入和解析XML】
Mar 25 #Python
Python实例方法、类方法、静态方法的区别与作用详解
Mar 25 #Python
详解Python装饰器
Mar 25 #Python
You might like
php中数据库连接方式pdo和mysqli对比分析
2015/02/25 PHP
php检查日期函数checkdate用法实例
2015/03/19 PHP
PHP实现文件上传和多文件上传
2015/12/24 PHP
laravel实现按时间日期进行分组统计方法示例
2019/03/23 PHP
通过PHP实现获取访问用户IP
2020/05/09 PHP
ExtJS GridPanel 根据条件改变字体颜色
2010/03/08 Javascript
js三种排序算法分享
2012/08/16 Javascript
JavaScript实现控制打开文件另存为对话框的方法
2015/04/17 Javascript
常用的JQuery函数及功能小结
2016/03/24 Javascript
浅谈javascript中的Function和Arguments
2016/08/30 Javascript
js实现显示手机号码效果
2017/03/09 Javascript
详解vue跨组件通信的几种方法
2017/06/15 Javascript
nodejs开发微信小程序实现密码加密
2017/07/11 NodeJs
Vue-Router基础学习笔记(小结)
2018/10/15 Javascript
JavaScript根据json生成html表格的示例代码
2018/10/24 Javascript
uni-app之APP和小程序微信授权方法
2019/05/09 Javascript
VUE项目中加载已保存的笔记实例方法
2019/09/14 Javascript
Vue实现base64编码图片间的切换功能
2019/12/04 Javascript
[51:29]完美世界DOTA2联赛循环赛 Matador vs Forest BO2第一场 11.05
2020/11/05 DOTA
朴素贝叶斯算法的python实现方法
2014/11/18 Python
Python 动态导入对象,importlib.import_module()的使用方法
2019/08/28 Python
基于python3的socket聊天编程
2020/02/17 Python
使用SQLAlchemy操作数据库表过程解析
2020/06/10 Python
python用什么编辑器进行项目开发
2020/06/17 Python
应届毕业生自我鉴定范文
2013/12/27 职场文书
护理个人求职信范文
2014/01/08 职场文书
作弊检讨书1000字
2014/02/01 职场文书
索桥的故事教学反思
2014/02/06 职场文书
高等教育学自荐书范文
2014/02/10 职场文书
《童趣》教学反思
2014/02/19 职场文书
希特勒的演讲稿
2014/05/23 职场文书
上课迟到检讨书范文
2015/05/06 职场文书
安全教育的主题班会
2015/08/13 职场文书
2015年小学体育教师工作总结
2015/10/23 职场文书
Python 中的Sympy详细使用
2021/08/07 Python
动作冒险《Hell Is Us》将采用虚幻5 消灭怪物探索王国
2022/04/13 其他游戏