Python - 这是eval还是exec的可接受用途?还有其他办法吗?

时间:2012-12-28 18:01:32

标签: python python-3.x exec eval

我对Python很陌生,并且一直在寻找一种方法来调用一个函数,该函数的名称由一个字符串和一个变量的组合形成,当用户选择其中一个选项时,该函数会动态填充。

示例:

我使用菜单启动程序,为用户提供某些选项(选择1,2,3或4)

如果用户选择1,变量xyz将填充一个元组或列表中的字符串。

将此字符串分配给变量,我调用另一个函数,它给了我另一个选项。

如果我得到选项1,我的代码会将xyz varible附加到一个预定义的字符串中,该字符串将形成一个函数名称(下一个将被调用的字符串。)。

if int(option) == 1:
#prefixfunc will be that predefined string that will be the prefix for every function  #to be called
    exec('prefixfunc'+xyz'()')
    #or
    #eval('prefixfunc_'+xyz'()')
    #for example, we have xyz as abc, then it calls function prefixfunc_abc()

它在代码中工作正常。我不认为这对用户添加不同输入的情况可能是一种责任。因为变量是通过在列表或元组中使用已定义的字符串来分配的。

我希望我已经清楚了。

为了更清楚:

def maint_car():
print('It Works!!! But did you come until here in a safe way?' )

def veh_func():
func=( "Maintenance", "Prices", "Back", "Quit" )
ord = 0

for i in func:
    ord += 1
    print(ord,'\b)', i)

picked = input('\nOption: ')

if int(picked) == 1:
    exec('maint_'+xyz+'()')




def startprog():

abcd =( "car", "bike", "airplane", "Quit" )
global xyz
ord = 0
for i in abcd:
    ord += 1
    print(ord,'\b)', i)

picked = input('\nVehicle:')

if int(picked) == 1:
    xyz = abcd[0]
    veh_func()

elif int(picked) == 2:
    xyz = abcd[1]
    veh_func()

elif int(picked) == 3:
    xyz = abcd[3]
    veh_func()

elif int(picked) == 4:
    print('\nBye.\n')

startprog()

3 个答案:

答案 0 :(得分:8)

为此我会使用dict将字符串名称映射到函数。

def test():
 print "yay"

funcs = { "test": test }
funcs["test"]()

这提供了一种更好的方法,您可以使用in运算符测试是否要非常轻松地执行该函数。

要回答:您的示例适用于evalexec我会拒绝。如果您认为exec是正确的答案,请查看您的解决方案,看看是否有更可维护,简单或明确的方法来实现您的目标。在这种情况下,基于某些用户输入将用户输入映射到要调用的函数。

答案 1 :(得分:3)

嗯,你可以这样做,但为什么有很多更好的方法呢?如:

funcs = {1: func1, 2: func2, 3: func3, 4: func4}
option = int(raw_input("Enter selection: "))
option in funcs and funcs[option]()

这里的优点是您不必遵循函数的任何特定命名约定。如果选项1是“添加名称”,则可以调用函数addname()而不是func1()。这将使您的代码更容易理解。

答案 2 :(得分:1)

如果您直接知道这些方法的名称,请按照@kindall的建议进行操作。如果不这样做,可以使用getattr()获取调用方法,而不必使用eval()进行编译/计算。

class ZZ(object):
  def fooBar(self):
    print(42)
  def barFoo(self):
    print(-42)

#now make a z
anInstance = ZZ()

#build up a dynamic string
string = 'foo' + 'Bar'

#fetch the attribute bound to string for the instance
method = getattr(anInstance, string)

#now execute the bound method/function (that's what the empty parens do)
method()

# out comes the following! Tada!
>>> 42

# we can inline a lot of this and just do things like
getattr(anInstance, 'bar' + 'Foo')()

# out comes the following! Again with the Tada...
>>> -42