我正在创建一个类似shell的环境。我处理用户输入的原始方法是使用字典映射命令(字符串)到各种类的方法,利用函数是python中的第一类对象这一事实。
为了灵活性(主要用于解析命令),我正在考虑更改我的设置,以便我使用getattr(命令),获取我需要的方法,然后在我的解析器末尾将参数传递给它。这种方法的另一个优点是每次添加新方法/命令时都不必更新我的(当前静态实现的)命令字典。
我的问题有两个问题。首先,getattr和eval有同样的问题吗?第二,我是否会对我的shell的效率产生影响?我有多少方法/命令是否重要?我目前正在查看30个命令,最终可能会翻倍。
答案 0 :(得分:23)
直接属性访问和使用getattr()之间的区别应该是相当微不足道的。您可以通过使用Python的dis
模块来比较两种方法来区分两个版本的字节码:
>>> import dis
>>> dis.dis(lambda x: x.foo)
1 0 LOAD_FAST 0 (x)
3 LOAD_ATTR 0 (foo)
6 RETURN_VALUE
>>> dis.dis(lambda x: getattr(x, 'foo'))
1 0 LOAD_GLOBAL 0 (getattr)
3 LOAD_FAST 0 (x)
6 LOAD_CONST 0 ('foo')
9 CALL_FUNCTION 2
12 RETURN_VALUE
但是,这听起来像是在开发一个与Python库cmd
执行命令行shell的方式非常相似的shell。 cmd
允许您通过将命令名称与cmd.Cmd
对象上定义的函数匹配来创建执行命令的shell,如下所示:
import cmd
class EchoCmd(cmd.Cmd):
"""Simple command processor example."""
def do_echo(self, line):
print line
def do_EOF(self, line):
return True
if __name__ == '__main__':
EchoCmd().cmdloop()
上阅读有关该模块的更多信息
答案 1 :(得分:7)
getattr和eval有同样的问题吗?
否 - 使用eval()
的代码维护起来非常烦人,并且可能存在严重的安全问题。调用getattr(x, "foo")
只是写x.foo
的另一种方式。
我是否会对我的shell的效率产生影响
如果找不到命令,它将在不知不觉中变慢,但不够重要。如果做基准测试,你只会注意到它,有成千上万的条目。