Это плохая практика, чтобы широко использовать python getattr? - PullRequest
9 голосов
/ 26 мая 2010

Я создаю похожую на оболочку среду. Мой оригинальный метод обработки пользовательского ввода состоял в том, чтобы использовать команды отображения словаря (строки) для методов различных классов, используя тот факт, что функции являются объектами первого класса в python.

Ради гибкости (в основном для разбора команд) я подумываю изменить свою настройку так, чтобы я использовал getattr (команду), чтобы получить нужный мне метод, а затем передать ему аргументы в конце моего парсера , Еще одним преимуществом этого подхода является отсутствие необходимости обновлять мой (в настоящее время статически реализованный) словарь команд каждый раз, когда я добавляю новый метод / команду.

У меня вопрос в два раза. Во-первых, есть ли у getattr те же проблемы, что и у eval? Во-вторых, получу ли я удар по эффективности моей оболочки? Имеет ли значение, сколько у меня методов / команд? В настоящее время я смотрю на 30 некоторых команд, которые в итоге могут удвоиться.

Ответы [ 2 ]

23 голосов
/ 26 мая 2010

Разница между прямым доступом к атрибуту и ​​использованием 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  

Однако, похоже, что вы разрабатываете оболочку, очень похожую на то, как cmd библиотека Python делает оболочки командной строки. cmd позволяет создавать оболочки, которые выполняют команды, сопоставляя имя команды с функцией, определенной для объекта cmd.Cmd, например:

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

7 голосов
/ 26 мая 2010

У getattr те же проблемы, что и у eval?

Нет - код, использующий eval(), ужасно раздражает в обслуживании и может иметь серьезные проблемы с безопасностью. Вызов getattr(x, "foo") - это просто еще один способ написать x.foo.

получу ли я удар по эффективности моей оболочки

Это будет незаметно медленнее, если команда не найдена, но не настолько важна. Вы заметите это только в тестах с десятками тысяч записей.

...