Когда использовать встроенные «свойства»: вспомогательные функции и генераторы - PullRequest
9 голосов
/ 04 мая 2010

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

Использование ключевого слова property, безусловно, правильно, если класс A имеет свойство _x, допустимые значения которого вы хотите ограничить; то есть он заменил бы конструкцию getX() и setX(), которую можно написать на C ++.

Но где еще уместно сделать функцию свойством? Например, если у вас есть

class Vertex(object):
    def __init__(self):
        self.x = 0.0
        self.y = 1.0

class Polygon(object):
    def __init__(self, list_of_vertices):
        self.vertices = list_of_vertices
    def get_vertex_positions(self):
        return zip( *( (v.x,v.y) for v in self.vertices ) )

уместно добавить

    vertex_positions = property( get_vertex_positions )

Можно ли когда-нибудь сделать генератор похожим на собственность? Представьте себе, если изменение в нашем коде означает, что мы больше не храним Polygon.vertices таким же образом. Тогда можно было бы добавить это к Polygon?

    @property
    def vertices(self):
        for v in self._new_v_thing:
            yield v.calculate_equivalent_vertex()

Ответы [ 2 ]

14 голосов
/ 04 мая 2010
  • Если у вас есть нормальный атрибут и вы получаете и / или настраиваете его, имеет смысл для пользователя класса выставлять атрибут напрямую. Одна из главных причин, по которой публичные члены являются анафемой в некоторых языках, заключается в том, что если вам нужно сделать что-то более сложное позже, вам потребуется изменение API; в Python вы можете просто определить свойство.

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

  • Если что-то не является атрибутом-y, не делайте это свойством. Создание метода не вредно, и это может быть выгодно: то, что он делает, более очевидно, вы можете обойти некоторый связанный метод, если вам нужно, вы можете добавить аргументы ключевых слов без изменения API.

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

  • Вы указываете, что можете использовать property для ограничения доступа к некоторому внутреннему атрибуту _x. Это может быть правдой, но имейте в виду

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

    • Иногда люди используют property для реализации атрибутов только для чтения. Обычно лучше просто иметь нормальный атрибут и понимать, что вы не можете помешать пользователю делать что-то глупое и неподдерживаемое.

  • Проницательно вы можете найти интересное:

    • property не является ключевым словом; это нормальное имя, которое вы можете перепривязать. Это своего рода Интересно, что property не является синтаксисом или чем-то еще: это обычный класс, который вы можете реализовать самостоятельно на чистом Python. Он использует тот же механизм, который заставляет методы работать в Python - дескрипторы .

    • Вы описываете, что делает property как «маскирует методы получения и установки методов класса», что не совсем так. Вещи, которые принимает property, являются просто обычными функциями, и вообще не нуждаются в определении в вашем классе; property пройдет self для вас. На самом деле функции не становятся методами, пока вы их не найдете, когда Python создает объекты методов на лету. Во время определения класса они являются просто функциями. Когда у вас есть нормальный метод, он называется «метод экземпляра»; в Python «метод класса» относится к другим специальным вещам , подобным свойствам, которые изменяют то, что происходит при поиске атрибута.

2 голосов
/ 04 мая 2010

Существует очевидное ограничение в использовании свойств: он не принимает никаких аргументов , и никогда не примет.

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

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