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

发布于 2024-09-02 18:48:58 字数 323 浏览 8 评论 0原文

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

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

我的问题有两个方面。首先,getattr 是否也存在与 eval 相同的问题?其次,我的 shell 的效率会受到影响吗?我有多少方法/命令重要吗?我目前正在研究 30 个命令,最终可能会增加一倍。

I'm creating a shell-like environment. My original method of handleing user input was to use a dictionary mapping commands (strings) to methods of various classes, making use of the fact that functions are first class objects in python.

For flexibility's sake (mostly for parsing commands), I'm thinking of changing my setup such that I'm using getattr(command), to grab the method I need and then passing arguments to it at the end of my parser. Another advantage of this approach is not having to update my (currently statically implemented) command dictionary every time I add a new method/command.

My question is two fold. First, does getattr have the same problems as eval? Second, will I be taking a hit to the efficiency of my shell? Does it matter how many methods/commands I have? I'm currently looking at 30 some commands, which could eventually double.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

很酷又爱笑 2024-09-09 18:48:58

直接属性访问和使用 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 库非常相似的 shell cmd 执行命令行 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()

您可以在以下任一位置阅读有关该模块的更多信息:文档,或位于 http://www.doughellmann.com/PyMOTW/cmd/index.html

The difference between direct attribute access and using getattr() should be fairly negligible. You can tell the difference between the two versions' bytecodes by using Python's dis module to compare the two approaches:

>>> 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  

It does, however, sound like you are developing a shell that is very similar to how the Python library cmd does command line shells. cmd lets you create shells that executes commands by matching the command name to a function defined on a cmd.Cmd object like so:

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()

You can read more about the module at either the documentation, or at http://www.doughellmann.com/PyMOTW/cmd/index.html

披肩女神 2024-09-09 18:48:58

getattr 和 eval 有同样的问题吗?

不——使用eval()的代码维护起来非常烦人,并且可能会产生严重的安全问题。调用 getattr(x, "foo") 只是编写 x.foo 的另一种方式。

我的 shell 的效率是否会受到影响

会不知不觉地变慢,但还不够重要。只有在进行具有数万个条目的基准测试时您才会注意到它。

does getattr have the same problems as eval?

No -- code using eval() is terribly annoying to maintain, and can have serious security problems. Calling getattr(x, "foo") is just another way to write x.foo.

will I be taking a hit to the efficiency of my shell

It will be imperceptibly slower if the command isn't found, but not enough to matter. You'd only notice it if doing benchmarks, with tens of thousands of entries.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文