Python @property против производительности метода - какой использовать? - PullRequest
12 голосов
/ 17 июля 2009

Я написал некоторый код, который использует атрибуты объекта:

class Foo:
    def __init__(self):
        self.bar = "baz"
myFoo = Foo()
print (myFoo.bar)

Теперь я хочу сделать какой-нибудь причудливый расчет, чтобы вернуть bar. Я мог бы использовать @property, чтобы методы действовали как атрибут bar, или я мог бы изменить свой код для использования myFoo.bar().

Должен ли я вернуться и добавить паренсы ко всем моим bar доступам или использовать @property? Предположим, что моя база кода теперь мала, но из-за энтропии она увеличится.

Ответы [ 6 ]

21 голосов
/ 17 июля 2009

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

В большинстве случаев производительность вряд ли будет проблемой.

19 голосов
/ 17 июля 2009

Интересно знать о производительности, когда ее так легко измерить:

$ python -mtimeit -s'class X(object):
>   @property
>   def y(self): return 23
> x=X()' 'x.y'
1000000 loops, best of 3: 0.685 usec per loop
$ python -mtimeit -s'class X(object):

  def y(self): return 23
x=X()' 'x.y()'
1000000 loops, best of 3: 0.447 usec per loop
$ 

(на моем медленном ноутбуке - если вы удивляетесь, почему во втором случае нет подсказок вторичной оболочки, это потому, что я построил его с первого раза со стрелкой вверх в bash, и это повторяет структуру переноса строк, но не подсказки -!)

.

Таким образом, если вы не знаете, что значение 200+ наносекунд или около того будет иметь значение (узкий внутренний цикл, который вы пытаетесь максимально оптимизировать), вы можете позволить себе использовать подход со свойством; если вы сделаете некоторые вычисления, чтобы получить значение, 200+ наносекунд, конечно, станут меньшей долей общего времени.

Я согласен с другими ответами, что если вычисления становятся слишком тяжелыми, или вам могут понадобиться параметры и т. Д., Метод предпочтительнее - аналогично, я добавлю, если вам когда-нибудь понадобится спрятать вызываемый объект, но только назовите это позже, и другие причудливые уловки функционального программирования; но я хотел сделать количественную оценку производительности, поскольку timeit делает такие измерения такими простыми! -)

7 голосов
/ 17 июля 2009

В таких случаях я считаю, что гораздо лучше выбрать вариант, который имеет больше смысла. Вы не получите заметного снижения производительности при таких небольших различиях. Гораздо важнее, что ваш код прост в использовании и обслуживании.

Что касается выбора между использованием метода и @property, то это вопрос вкуса, но поскольку свойства маскируются под простые атрибуты, ничего сложного не должно происходить. Метод указывает, что это может быть дорогостоящей операцией, и разработчики, использующие ваш код, будут рассматривать кэширование значения, а не извлекать его снова и снова.

Опять же, не снижайте производительность, всегда обращайте внимание на удобство обслуживания и производительность. Компьютеры становятся все быстрее и быстрее с течением времени. То же самое не означает читабельность кода.

Короче говоря, если вы хотите получить простое вычисленное значение, @property - отличный выбор; если вы хотите рассчитать сложное значение, метод указывает, что лучше.

3 голосов
/ 17 июля 2009

Я бы пошел на рефакторинг, но только из соображений стиля - мне кажется более понятным, что «причудливые вычисления» могут продолжаться при вызове метода, в то время как я ожидаю, что свойство будет почти неактивным, но это дело вкуса.

Не беспокойтесь о производительности декоратора ... если вы считаете, что это может быть проблемой, измерьте производительность в обоих случаях и посмотрите, сколько она добавляет (я полагаю, что она будет совершенно незначительной по сравнению с ваши модные расчеты).

2 голосов
/ 17 июля 2009

Я согласен с тем, что большинство людей здесь сказали, я провел много измерений при построении гидрологических моделей в Python пару лет назад и обнаружил, что скорость, достигнутая при использовании @property, была полностью затенена расчетами.

В качестве примера, создание локальных переменных метода (удаление «точечного фактора» в моих вычислениях увеличило производительность почти на порядок больше, чем удаление @property (эти результаты усредняются по среднему приложению).

Я бы искал оптимизацию в других местах, когда это необходимо, и вначале сосредоточился бы на написании хорошего, поддерживаемого кода. На этом этапе, если @property интуитивно понятен в вашем случае, используйте его. Если нет, сделайте метод.

1 голос
/ 17 июля 2009

Это именно то, для чего предназначен @property.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...