Python通过字符串来执行函数甚至代码!这么顶的操作快来了解下!

一、前言

最近有个需求,想在数据库中存入函数名的字符串,通过传递它来控制不同函数的执行以便业务流程的控制。

简单来说就是通过字符串来直接调用函数,经过查阅后,发现了四种比较可行的方法

二、方法介绍

1.eval

python内置的eval函数不仅可将符合字典、列表、元祖格式的字符串转换成字典、列表和元祖 (在实际开发的时候,如果需要把json字符串转字典或列表尽量使用json.loads来转化,详情可查看我之前分享的博文:python处理json字符串,建议使用json.loads而不是eval()

还可以直接将字符串形式的代码直接转化成可执行的代码!

例如如下代码,会将print(10000)这个字符串直接执行:

str1='print(10000)'
eval(str1)

输出结果
在这里插入图片描述


同理,我们可以通过eval来执行一个函数

def test(x, y):
    print(x + y)
eval('test(1,2)')

输出结果
在这里插入图片描述


但eval是把双刃剑,如果用户传递的字符串是一些能够获取隐秘信息或者带来安全问题的代码就可能带来极大的问题!
例如:用户传入了一个删除当前目录所有文件的代码字符串,那你就等着跑路吧!
在这里插入图片描述


因此eval虽然强大,但是也很危险!所以要慎用!!

2.locals()和globals()

locals() 和 globals() 是python的两个内置函数,通过它们可以以字典的方式访问局部和全局变量。

两个函数的区别在于locals 是只读的,不可修改,而globals可以修改,例如:

y = 1
def test():
    x = 1
    locals()['x'] = 2
    globals()['y'] = 2
    print('locals无法对变量进行修改,所以x的值还为:', x)
    print('globals可以对全局变量进行修改,所以y的值被改为:', y)
test()

执行结果

在这里插入图片描述


原因是locals()实际上没有返回局部名字空间,它返回的是一个拷贝。所以对它进行修改,修改的是拷贝,而对实际的局部名字空间中的变量值并无影响。
globals()返回的是实际的全局名字空间,而不是一个拷贝: 与 locals 的行为完全相反。

回到主题,通过locals和globals调用字符串来执行函数:

def test(x, y):
    print(x + y)
locals()['test'](1, 2)
print("-----------------")
globals()['test'](1, 2)

执行结果
在这里插入图片描述


3.getattr()

getattr() 是python的内建函数,也就是我们常说的反射。

getattr(Test,'func_1') 就相当于返回Test类中的func_1方法!

但是这里 func_1可以为变量,比如一个表示方法名字符串的变量。

例如:

class Test:
    def fuc_1(self, x,y):
        print(x+y)
getattr(Test(), 'fuc_1')(1,2)

输出结果
在这里插入图片描述


如果getattr没有找到这个str的方法,会抛出异常,相比eval和locals()、globals()要安全一些!
在这里插入图片描述


4.operator模块的methodcaller函数

operator模块是python中的标准运算符替代函数,它提供了一套与Python的内置运算符对应的高效率函数。例如,operator.add(x, y) 与表达式 x+y 相同。

通过它来实现字符串访问函数:

from operator import methodcaller
class Test:
    def func_1(self, x, y):
        print("func_1")
        print(x + y)

    def func_2(self):
        print("func_2")
methodcaller('func_1', 1, 2)(Test())  # 传递参数
methodcaller('func_2')(Test())  # 不传递参数

输出结果
在这里插入图片描述


通过查看methodcaller函数的源码可以发现,它是对getattr进行了一层封装
在这里插入图片描述


分享暂时到这里,小伙伴们点赞、收藏、评论是对我最大的支持!!

评论 53
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

曲鸟

不要打赏,没必要!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值