Когда и как использовать встроенное функциональное свойство () в Python

Протестируйте контракт интерфейса модуля, который Вы тестируете:

  • , Если клиент ожидал бы определенное поведение при использовании класса, протестируйте его.
  • , Если Ваш класс должен предотвратить некоторое поведение от клиента, как определено в его контракте, протестируйте его.

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

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

68
задан olamundo 12 October 2009 в 13:22
поделиться

6 ответов

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

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

и присваивания, такие как xb = 2 , на языках, которые имеют свойства (набор языков, который включает, но не ограничивается Python), точно такие же, как для методов получения и установки в, например, Java: те же ожидания, то же отсутствие гарантий, обеспечиваемых языком.

Первая победа для свойств - это синтаксис и удобочитаемость. Необходимость писать, например,

x.setB(x.getB() + 1)

вместо очевидного

x.b += 1

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

В частности, в Python есть еще один большой плюс для использование свойств (или других дескрипторов) вместо геттеров и сеттеров: помимо влияния на читаемость кода ваших пользователей, вы также беспричинно тратите машинные циклы (и энергию, которая идет на их компьютер во время этих циклов ;-), снова без уважительной причины

Ваш единственный аргумент против свойств - это, например, то, что «внешний пользователь обычно не ожидает никаких побочных эффектов в результате присваивания»; но вы упускаете тот факт, что один и тот же пользователь (на таком языке, как Java, где геттеры и сеттеры широко распространены) не ожидал бы (наблюдаемых) «побочных эффектов» в результате вызова сеттера (и тем более для геттера ;-). Это разумные ожидания, и вы, как автор класса, должны попытаться учесть их - независимо от того, используются ли ваши сеттер и получатель напрямую или через свойство, не имеет значения. Если у вас есть методы с важными наблюдаемыми побочными эффектами, не не назовите их getThis , setThat и не используйте их через свойства.

Жалоба на то, что свойства "скрыть реализацию" совершенно неоправданно: большая часть всего ООП связана с реализацией сокрытия информации - возложением на класс ответственности за представление логического интерфейса внешнему миру и его внутренней реализации, насколько это возможно. Геттеры и сеттеры, как и свойства, являются инструментами для достижения этой цели. Свойства просто справляются с этим лучше (на языках, которые их поддерживают; -).

Жалоба на то, что свойства «скрывают реализацию», совершенно неоправданна: большая часть всего ООП связана с реализацией сокрытия информации - возлагая на класс ответственность за представление логического интерфейса внешнему миру и его внутреннюю реализацию. как можно лучше. Геттеры и сеттеры, как и свойства, являются инструментами для достижения этой цели. Свойства просто справляются с этим лучше (на языках, которые их поддерживают; -).

Жалоба на то, что свойства «скрывают реализацию», совершенно неоправданна: большая часть всего ООП связана с реализацией сокрытия информации - возлагая на класс ответственность за представление логического интерфейса внешнему миру и его внутреннюю реализацию. как можно лучше. Геттеры и сеттеры, как и свойства, являются инструментами для достижения этой цели. Свойства просто справляются с этим лучше (на языках, которые их поддерживают; -).

129
ответ дан 24 November 2019 в 14:06
поделиться

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

Итак, для начала вы напишите:

class MyClass(object):
    def __init__(self):
        self.myval = 4

Очевидно, теперь вы можете написать myobj.myval = 5 .

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

31
ответ дан 24 November 2019 в 14:06
поделиться

, но скрывая тот факт, что ab = 2 не является простое задание похоже на рецепт для неприятностей

Но вы этого не скрываете; этого факта никогда не было. Это питон - язык высокого уровня; не сборка. Некоторые из «простых» утверждений в нем сводятся к инструкциям для одного процессора. Вносить простоту в задание - значит читать вещи, которых там нет.

Когда вы говорите xb = c, вы, вероятно, должны думать только о том, что «что бы ни случилось, теперь xb должно быть c».

14
ответ дан 24 November 2019 в 14:06
поделиться

Основная причина в том, что он действительно выглядит лучше. Он более питонический. Специально для библиотек. something.getValue () выглядит менее привлекательно, чем something.value

В plone (довольно большая CMS) у вас был document.setTitle (), который выполняет много вещей, таких как сохранение значения, его повторная индексация и т.д. Просто сделать document.title = 'something' лучше. Вы знаете, что в любом случае многое происходит за кулисами.

5
ответ дан 24 November 2019 в 14:06
поделиться

Вот мой старый пример. Я обернул библиотеку C, в которой были такие функции, как «void dt_setcharge (int atom_handle, int new_charge)» и «int dt_getcharge (int atom_handle)». Я хотел на уровне Python сделать "atom.charge = atom.charge + 1".

Декоратор "property" упрощает это. Что-то вроде:

class Atom(object):
    def __init__(self, handle):
        self.handle = handle
    def _get_charge(self):
        return dt_getcharge(self.handle)
    def _set_charge(self, charge):
        dt_setcharge(self.handle, charge)
    charge = property(_get_charge, _set_charge)

10 лет назад, когда я писал этот пакет, мне пришлось использовать __getattr__ и __setattr__, которые сделали это возможным, но реализация была намного более подвержена ошибкам.

class Atom:
    def __init__(self, handle):
        self.handle = handle
    def __getattr__(self, name):
        if name == "charge":
            return dt_getcharge(self.handle)
        raise AttributeError(name)
    def __setattr__(self, name, value):
        if name == "charge":
            dt_setcharge(self.handle, value)
        else:
            self.__dict__[name] = value
2
ответ дан 24 November 2019 в 14:06
поделиться

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

Учтите, что у вас есть класс Foo, который широко используется в вашем приложении. Теперь это приложение стало довольно большим, и далее можно сказать, что это веб-приложение, которое стало очень популярным.

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

Да, конечно, это проблемный код, но вы просто сэкономили много $$, быстро исправив его.

Что делать, если Foo находится в библиотеке, которой у вас сотни или тысячи пользователей? Что ж, вы избавили себя от необходимости посоветовать им провести дорогостоящий рефакторинг при обновлении до последней версии Foo.

В примечаниях к выпуску есть строка о Foo вместо абзаца руководства по переносу.

Опытные программисты Python этого не делают. ожидают многого от ab = 2 , кроме ab == 2 , но они знают, что даже это может быть неправдой. То, что происходит внутри класса, - это его личное дело.

Не ожидают многого от ab = 2 , кроме ab == 2 , но они знают, что даже это может быть неправдой. То, что происходит внутри класса, - это его личное дело.

Не ожидают многого от ab = 2 , кроме ab == 2 , но они знают, что даже это может быть неправдой. То, что происходит внутри класса, - это его личное дело.

3
ответ дан 24 November 2019 в 14:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: