首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

第6.6节 Python动态执行小结

  • 23-09-22 19:01
  • 3937
  • 13899
blog.csdn.net

一、    Python动态执行支持通过输入数据流或文件传入Python源代码串,进行编译后执行,可以通过这种方式扩展Python程序的功能;
二、    动态执行方法可能导致恶意攻击,因此使用时需要限定使用范围,注意安全风险;
三、    如果采用先编译后动态执行的方式,注意编译模式必须与执行模式对应;
四、    动态执行可以指定代码的执行空间,动态执行最好在指定的全局名字空间和局部名字空间中执行:
1.    如果省略了可选参数,代码将在当前范围内执行;
2.    如果提供了 globals 参数,就必须是字典类型,而且会被用作全局和局部变量的名字空间;
3.    如果同时提供了 globals 和 locals 参数,它们分别被用作全局和局部变量的名字空间;
4.    动态执行查找变量时的顺序依次为:局部名字空间->全局名字空间->调用exec或eval的代码执行环境的名字空间;
5.    建议所有动态执行都指定单独的执行空间,以保证动态执行不会无意中损害调用方的环境。
五、    在模块层级(通常是动态执行的调用方),全局和局部变量是相同的字典,内置 globals() 和 locals() 函数各自返回当前的全局和局部字典,因此可以将它们传递给 exec() 的第二个和第三个实参,但实际上与这两个参数不传参效果是一样的,因为不传值用的就是在当前调用方所在模块的空间执行,而这两个函数也是返回当前模块的空间,而在模块层级这两个函数返回的值是一样的。
六、    补充知识
1.    动态执行时,如果执行时指定了全局名字空间或局部名字空间,则可以在执行前通过字典键值访问值的模式给对应变量赋值;
举例:
 
这个例子中,要编译的表达式字符串为‘x+y’,但在编译代码中没有给x和y赋值,通过全局名字空间给x和y赋值的,计算时就取到了对应变量值。
2.    在启动Python解释器之后,即使没有创建任何的变量或者函数,还是会有许多函数可以使用, 我们把这些函数称为内建常量和内建函数,是因为它们不需要我们程序员作任何定义,在启动Python解释器的时候,会首先加载内建名字空间,内建名字空间有许多名字到对象之间映射,而这些名字其实就是内建函数和常量的名称,对象就是这些内建函数和常量本身。这些名字空间由__builtins__模块中的名字构成;
3.    __builtins__:对于动态执行时的全局名字空间字典,如果不包含 __builtins__ 键值,则将为该键插入对内建 builtins 模块字典的引用。因此,在将执行的代码传递给 exec() 之前,可以通过将自己的 __builtins__ 字典插入到 globals 中来控制可以使用哪些内置代码。本点老猿没有深入研究,暂时不展开说明。

七、    例子
1.    动态执行全局空间使用调用方的例子

  1. s='''
  2. person=['张三','李四']
  3. for p in person:
  4. print('name=',p)
  5. while(True):
  6. s=input("I will exit,are you ready(y/n)?")
  7. if s=='Y': break;
  8. if s=='y': break;
  9. '''
  10. exec(s,globals(),locals())


此时执行的语句执行效果与exec(s)的执行效果完全相同,执行后s的值被输入改变。
2.    用eval动态执行实现的cal函数
第五章介绍的的cal函数的例子,如果使用动态执行方法的实现代码会简单许多,具体代码如下:

  1. def cal(number1,number2,*numbers,calmethod='+'):
  2. print('number1=',number1,',number2=',number2,',numbers=',numbers,', calmethod=',calmethod)
  3. calmethod=calmethod.strip()
  4. if len(calmethod)!=1: raise ValueError('运算符必须是+-*/中的一个,分别对应加、减、乘、除')
  5. if '+-*/'.find(calmethod)==-1 :raise ValueError('运算符必须是+-*/中的一个,分别对应加、减、乘、除')
  6. if not isinstance(number1,int): raise TypeError('第1个参数必须为整数')
  7. if not isinstance(number2,int): raise TypeError('第2个参数必须为整数')
  8. s=str(number1)+calmethod+str(number2)
  9. for i,n in enumerate(numbers):
  10. if isinstance(n,int): #判断n是否为整数
  11. s+=calmethod+str(n)
  12. else:raise TypeError('第'+str(i+3)+'个参数必须为整数')
  13. return eval(s)


代码及执行样例截屏如下:
 
上述代码的实现细节在此不再赘述,相信大家都能明白。
3.    以exec定义的cal函数,所有代码全部存储在字符串codebuff中

  1. >>> codebuff='''
  2. def cal(number1,number2,*numbers,calmethod='+'):
  3.    print('number1=',number1,',number2=',number2,',numbers=',numbers,', calmethod=',calmethod)
  4.    calmethod=calmethod.strip()
  5.    if len(calmethod)!=1: raise ValueError('运算符必须是+-*/中的一个,分别对应加、减、乘、除')
  6.    if '+-*/'.find(calmethod)==-1 :raise ValueError('运算符必须是+-*/中的一个,分别对应加、减、乘、除')
  7.    if not isinstance(number1,int): raise TypeError('第1个参数必须为整数')
  8.    if not isinstance(number2,int): raise TypeError('第2个参数必须为整数')
  9.    s=str(number1)+calmethod+str(number2)
  10.    for i,n in enumerate(numbers):
  11.        if  isinstance(n,int): #判断n是否为整数
  12.            s+=calmethod+str(n)
  13.        else:raise TypeError('第'+str(i+3)+'个参数必须为整数')
  14.    return eval(s)
  15. '''
  16. >>> ns={}
  17. >>> exec(codebuff,ns)
  18. >>> ns['cal'](1,2,3,calmethod='+')
  19. number1= 1 ,number2= 2 ,numbers= (3,) , calmethod= +
  20. 6
  21. >>> add=ns['cal']
  22. >>> add(1,2,3,calmethod='+')


执行截图:
 
上面这段代码是将第2个例子全部改成动态代码来实现,第一步将所有函数定义放到字符串codebuff缓冲区中,然后定义一个函数执行的名字空间ns,并通过exec执行函数定义的语句,在ns中就生成了函数定义,该函数可以通过名字空间ns以函数名作为键值获取,获取后可以直接执行函数调用,也可以赋值给一个变量add,再通过变量进行调用。

本节对动态执行方法相关的内容进行了总结,并补充说明了传递的全局名字空间和本地名字空间相关的内容。
老猿Python(https://blog.csdn.net/LaoYuanPython)系列文章用于逐步介绍老猿学习Python后总结的学习经验,这些经验有助于没有接触过Python的程序员可以很容易地进入Python的世界。
欢迎大家批评指正,谢谢大家关注!

文章知识点与官方知识档案匹配,可进一步学习相关知识
Python入门技能树首页概览333596 人正在系统学习中
老猿Python
微信公众号
专注Python相关语言、图像音视频处理、AI
注:本文转载自blog.csdn.net的LaoYuanPython的文章"https://blog.csdn.net/LaoYuanPython/article/details/91049728"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2024 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top