首页 > 解决方案 > 如何在 python 中执行与字符串具有相同“文本”的变量

问题描述

我有一个变量 ,abc定义为'batting_stats'并想要运行一行代码'pyb.batting_stats(2020)'. 我想使用字符串语法通过加入 abc 来创建该行,'pyb.'然后'(2020)'运行该行代码 - 我该怎么做?我似乎正在创建一个更大的字符串实例,而不是可运行的代码行。干杯!

标签: pythonstring

解决方案


您可能不想这样做;这是可能的,但在绝大多数情况下,这是一个坏主意。

选项:

  • 如果可能的话,尝试重写代码,这样你就根本不需要按名字查找了;例如,您可以更改其他代码,使其存储pyb.batting_stats为函数而不是字符串

    abc = pyb.batting_stats  # note no brackets
    
    # later
    result = abc(2020)
    
  • 如果确实需要按名称查找,可以使用getattr,如下所示:

    # At the top of the script
    ALLOWED_NAMES = ['batting_stats', ...]
    
    # in the code where you need it
    if abc not in ALLOWED_NAMES:
        raise ValueError("Invalid name passed: %s" % abc)
    result = getattr(pyb, abc)(2020)
    
  • 可能更好的方法是使用字典作为调度表:

    dispatch_table = {
         'batting_stats': pyb.batting_stats,
         ...: ...,
    }
    result = dispatch_table[abc](2020)
    

    如果传递了意外的名称,这会自动引发异常。

    它还有一个好处是您可以在abc变量中使用与方法名称不同的字符串;例如,如果您需要重命名函数但在 API 中保留名称,反之亦然:

    dispatch_table = {
         'battingstats': pyb.batting_stats,  # legacy name
         'batting_stats': pyb.batting_stats,
         ...: ...,
    }
    result = dispatch_table[abc](2020)
    
  • 如果您绝对必须从字符串运行一段代码,您可以使用evalexec内置函数;然而,这几乎总是一个坏主意。

    使用evalandexec经常是危险和不安全的(Common Weakness #95),最好完全避免它。幸运的是,至少在 Python 中,几乎总是有替代方案。此外,这些替代方案通常更清洁、更灵活、运行更快且更易于调试。没有其他选择的情况非常罕见。


推荐阅读