Python @property против производительности метода - какой из них использовать?

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

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

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

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

Ответ 1

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

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

Ответ 2

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

$ 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 делает такие измерения такими легкими! -)

Ответ 3

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

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

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

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

Ответ 4

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

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

Ответ 5

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

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

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

Ответ 6

То, что предназначено для @property.