How to convert a string to a function in python?
例如,如果我有一个名为add like的函数
1 2 | def add(x,y): return x+y |
我希望能够将字符串或输入转换为直接指向函数
1 | w=raw_input('Please input the function you want to use') |
或
1 | w='add' |
有没有办法用w来引用函数add?
由于您正在接受用户输入,最安全的方法是准确定义什么是有效输入:
1 2 3 4 5 6 | dispatcher={'add':add} w='add' try: function=dispatcher[w] except KeyError: raise ValueError('invalid input') |
如果要计算像
1 | eval('add(3,4)',{'__builtins__':None},dispatcher) |
当应用于用户输入时,由于
警告:即使是
一种安全的方法是从名称映射到函数。它比使用
1 2 3 4 5 6 7 8 9 10 | function_mappings = { 'add': add, } def select_function(): while True: try: return function_mappings[raw_input('Please input the function you want to use')] except KeyError: print 'Invalid function, try again.' |
UNUTBU的解决方案是我通常使用的,但为了完整起见:
如果您指定的是函数的确切名称,则可以使用
1 | eval("add")(x,y) |
内置的函数
如果预定义函数的数量有限,则应避免使用
如果您正在实现一个类似shell的应用程序,其中用户输入一些命令(如add)和应用程序响应(返回sum),那么您可以使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | #!/usr/bin/env python import cmd import shlex import sys class MyCmd(cmd.Cmd): def do_add(self, arguments): '''add - Adds two numbers the print the sum''' x, y = shlex.split(arguments) x, y = int(x), int(y) print x + y def do_quit(self, s): '''quit - quit the program''' sys.exit(0) if __name__ == '__main__': cmd = MyCmd() cmd.cmdloop('type help for a list of valid commands') |
以下是一个运行会话示例:
$ python cmd_tryout.py
type help for a list of valid commands
(Cmd) help add
add - Adds two numbers the print the sum
(Cmd) add 5 3
8
(Cmd) quit
在提示(cmd)下,您可以免费发出
注意,HELP命令显示函数的docstring。docstring是紧跟在函数声明之后的字符串(例如,请参见
这个示例程序应该足以让您开始。有关详细信息,请参阅cmd帮助页。定制提示和程序的其他方面是很琐碎的。
只需使用函数引用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | def pwr(x, y): return x ** y def add(x, y): return x + y dispatcher = { 'pwr' : pwr, 'add' : add} def call_func(x, y, func): try: return dispatcher[func](x, y) except: return"Invalid function" call_func(2, 3, 'add') |
简单安全。
在很多情况下,我需要在django模板中将字符串与int进行比较,反之亦然。
我创建了一个过滤器,允许我传入函数名并使用eval()转换它。
例子:
模板:
1 | {% ifequal string int|convert:'str' %} do something {% endifequal %} |
模板筛选器(我在其中使用字符串调用函数名):
1 2 3 4 5 6 7 | @register.filter def convert(value, funcname): try: converted = eval(funcname)(value) return converted except: return value |
[我通过一个重复的问题来到这里。我的第一个想法是使用
您可以使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | import argparse import shlex def hello(name): print('hello,', name) def main(): parser = argparse.ArgumentParser() subparsers = parser.add_subparsers() hello_parser = subparsers.add_parser('hello') hello_parser.add_argument('name') hello_parser.set_defaults(func=hello) print('Enter q to quit') while True: command = input('command> ') command = command.strip() if not command: continue if command.lower() == 'q': break words = shlex.split(command) try: args = parser.parse_args(words) except SystemExit: # argparse will sys.exit() on -h and errors; prevent that continue func_args = {name: value for name, value in vars(args).items()} del func_args['func'] args.func(**func_args) if __name__ == '__main__': try: main() except KeyboardInterrupt: print() |