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实现一个简单的线程池
Apr 07 Python
Python基于递归算法实现的走迷宫问题
Aug 04 Python
Python基于回溯法子集树模板解决选排问题示例
Sep 07 Python
python实现二叉树的遍历
Dec 11 Python
Python中摘要算法MD5,SHA1简介及应用实例代码
Jan 09 Python
利用Django-environ如何区分不同环境
Aug 26 Python
Python3内置模块pprint让打印比print更美观详解
Jun 02 Python
Djang的model创建的字段和参数详解
Jul 27 Python
python十进制转二进制的详解
Feb 07 Python
PyCharm 2020 激活到 2100 年的教程
Mar 25 Python
tensorflow实现从.ckpt文件中读取任意变量
May 26 Python
python语言的优势是什么
Jun 17 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
实现dedecms全站URL静态化改造的代码
2007/03/29 PHP
php 404错误页面实现代码
2009/06/22 PHP
php SQL Injection with MySQL
2011/02/27 PHP
基于curl数据采集之正则处理函数get_matches的使用
2013/04/28 PHP
php获取参数的几种方法总结
2014/02/18 PHP
[原创]PHP实现SQL语句格式化功能的方法
2017/07/28 PHP
laravel5.4利用163邮箱发送邮件的步骤详解
2017/09/22 PHP
js操作ajax返回的json的注意问题!
2010/02/23 Javascript
jQuery源码解读之addClass()方法分析
2015/02/20 Javascript
js立即执行函数: (function ( ){})( ) 与 (function ( ){}( )) 有什么区别?
2015/11/18 Javascript
jquery对所有input type=text的控件赋值实现方法
2016/12/02 Javascript
浅析Jquery操作select
2016/12/13 Javascript
jquery 禁止鼠标右键并监听右键事件
2017/04/27 jQuery
jQuery实现动态删除LI的方法
2017/05/30 jQuery
微信小程序实现给嵌套template模板传递数据的方式总结
2017/12/18 Javascript
Angular实现下拉框模糊查询功能示例
2018/01/03 Javascript
微信小程序实时聊天WebSocket
2018/07/05 Javascript
详解Angular模板引用变量及其作用域
2018/11/23 Javascript
详解JS实现系统登录页的登录和验证
2019/04/29 Javascript
Angular6使用forRoot() 注册单一实例服务问题
2019/08/27 Javascript
Node.js设置定时任务之node-schedule模块的使用详解
2020/04/28 Javascript
[09:34]2018DOTA2国际邀请赛寻真——永不放弃的iG
2018/08/14 DOTA
使用python Django做网页
2013/11/04 Python
Python实现类似jQuery使用中的链式调用的示例
2016/06/16 Python
Python中的错误和异常处理简单操作示例【try-except用法】
2017/07/25 Python
Python 中的Selenium异常处理实例代码
2018/05/03 Python
Flask框架响应、调度方法和蓝图操作实例分析
2018/07/24 Python
详解Python requests 超时和重试的方法
2018/12/18 Python
Django网络框架之HelloDjango项目创建教程
2019/06/06 Python
python之生成多层json结构的实现
2020/02/27 Python
html5通过postMessage进行跨域通信的方法
2017/12/04 HTML / CSS
中国梦的演讲稿
2014/01/08 职场文书
聚美优品陈欧广告词
2014/03/14 职场文书
法人委托书范本
2014/04/04 职场文书
2016年幼儿园教师师德承诺书
2016/03/25 职场文书
深入理解pytorch库的dockerfile
2022/06/10 Python