广泛使用python的getattr是不好的做法吗?

Wil*_*uck 9 python shell performance getattr

我正在创建一个像shell一样的环境.我处理用户输入的原始方法是使用字典映射命令(字符串)到各种类的方法,利用函数是python中的第一类对象的事实.

为了灵活性(主要用于解析命令),我正在考虑更改我的设置,以便我使用getattr(命令),获取我需要的方法,然后在我的解析器末尾将参数传递给它.这种方法的另一个优点是每次添加新方法/命令时都不必更新我的(当前静态实现的)命令字典.

我的问题是双重的.首先,getattr和eval有同样的问题吗?第二,我是否会对我的shell的效率产生影响?我有多少方法/命令是否重要?我目前正在查看30个命令,最终可能翻倍.

146*_*146 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  
Run Code Online (Sandbox Code Playgroud)

但是,它听起来像是在开发一个与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()
Run Code Online (Sandbox Code Playgroud)

您可以在文档或http://www.doughellmann.com/PyMOTW/cmd/index.html上阅读有关该模块的更多信息.


Joh*_*kin 7

getattr和eval有同样的问题吗?

否 - 使用代码eval()非常烦人,并且可能存在严重的安全问题.呼叫getattr(x, "foo")只是另一种写作方式x.foo.

我会对我的shell的效率产生影响吗?

如果找不到命令,它将在不知不觉中变慢,但不够重要.如果做基准测试,你只会注意到它,有成千上万的条目.