Python 3:将str对象变为可调用对象

16

我有一个Python程序需要接受用户输入。我将用户输入存储在一个名为"userInput"的字符串变量中。我想要能够调用用户输入的字符串...

userInput = input("Enter a command: ")
userInput()

由此,我得到了错误信息:TypeError: 'str' object is not callable。

目前,我的程序类似于以下操作:

userInput = input("Enter a command: ")
if userInput == 'example_command':
    example_command()

def example_command():
     print('Hello World!')

很明显,这不是处理大量命令的非常有效的方式。我想让str对象可调用-有什么方法可以做到这一点吗?


7
我认为你正在寻找的是 eval('string')。但请确保对该字符串进行仔细检查,否则会导致严重的安全问题。另外,你还需要在输入字符串末尾添加 "()"。 - Evan
3
即使进行了严格的检查,对用户输入运行eval也可能不是一个好主意。您要进行的检查是:“这个字符串是否属于批准的集合之一”,此时您可以直接进行字典查找。 - lvc
@Evan 纯属好奇,eval() 是什么,为什么会引起安全问题? - just_a_programmer
2
它试图运行一个字符串。如果黑客想要进入您的系统,这将使其变得非常容易。他们只需要知道要调用哪些函数和您有哪些变量。然后他们就可以随心所欲地进行操作。例如,如果您有一个带有某个变量“size”的链表,则可以调用eval,我认为还有exec,“my_list.size = 0”并更改大小。更多信息请参见Python文档 - Evan
谢谢@Evan,我现在明白了。 - just_a_programmer
2个回答

32

更好的方法可能是使用字典:

def command1():
    pass

def command2():
    pass

commands = {
    'command1': command1,
    'command2': command2
}

user_input = input("Enter a command: ")
if user_input in commands:
    func = commands[user_input]
    func()

    # You could also shorten this to:
    # commands[user_input]()
else:
    print("Command not found.")

本质上,您提供了一个字面命令和您想要运行的函数之间的映射。

如果输入过多,您也可以使用"local"关键字,它将返回当前范围内定义的每个函数、变量等的字典:

def command1():
    pass

def command2():
    pass

user_input = input("Enter a command: ")
if user_input in locals():
    func = locals()[user_input]
    func()

然而,这并不完全安全,因为恶意用户可能会输入与变量名相同或不希望其运行的某些函数相同的命令,从而导致您的代码崩溃。


6
啊!你比我快了8秒。干得好先生,干得好! - inspectorG4dget
你们太聪明了 :) - Sharif Mamun
谢谢你!帮了我很多忙!;) - just_a_programmer

1
你可以使用exec方法来实现。基本上,exec命令执行字符串。
user_input = input()        # example command
exec(user_input + '()')     # append the function parenthesis

您必须记住,允许用户在没有适当验证的情况下执行代码是危险的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接