遇到一个根据字符串名称调用 Python 方法的问题,考虑了几种可行的方式(函数名字符串+元组字符串 + 字典字符串,或者直接使用带参函数名字符串)。

1 函数名 字符串 + [参数元组 字符串] + [参数字典 字符串]

class TestClass:
    @staticmethod
    def test_method(x, y, z):
        print(x, y, z)
        
# 方式 1, 反射
from ast import literal_eval

def call_method(str_method, str_args, str_kw):
    getattr(TestClass, str_method)(*literal_eval(str_args), **literal_eval(str_kw))

call_method('test_method', '(2,3)', "{'z':4}")

# 方式 2,methodcaller
# 使用 operator.methodcaller(str_method,*args,**kw)(classname), 不细述

# 不安全的方式:简单粗暴使用 eval

2 带参 函数名 字符串 / 函数名 字符串 + [参数 字符串]

class TestClass:
    @staticmethod
    def test_method(x, y, z):
        print(x, y, z)
        
# 方式 1,解析参数
import re
from ast import literal_eval

def call_method(str_method_with_param):
    str_method, str_param = str_method_with_param.split('(', 1)[:-1] # 或正则
    re_kw = re.search(r'([^,\'\"]*=.*)', str_param)
    if re_kw:
        list_kw = (kv.split('=', maxsplit=1) for kv in re_kw[0].strip(',').split(','))
        kw = {k:literal_eval(v) for k,v in list_kw}
        args = literal_eval(str_param.rstrip(re_kw[0]))
    else:
        kw = {}
        if str_param and not str_param.endswith(','):
            str_param += ','
        args = literal_eval(str_param)
    getattr(TestClass, str_method)(*args, **kw)
    
call_method('test_method(2,3,z=4)')

# 不安全的方式:简单粗暴使用 eval('TestClass.' + method_with_param)

<推广> 本站使用 NameSilo 提供的域名服务。