Что такое питонический способ использования геттеров и сеттеров?
blockquote>Путь «Pythonic» не для использования «getters» и «seters» , но для использования простых атрибутов, таких как демонстрация вопроса, и
del
для разыменования (но имена изменены для защиты невинных ... встроенных):value = 'something' obj.attribute = value value = obj.attribute del obj.attribute
Если позже вы хотите измените настройку и получение, вы можете сделать это, не изменяя код пользователя, используя декоратор
property
:class Obj: """property demo""" # @property def attribute(self): # implements the get - this name is *the* name return self._attribute # @attribute.setter def attribute(self, value): # name must be the same self._attribute = value # @attribute.deleter def attribute(self): # again, name must be the same del self._attribute
(Каждый декоратор копирует и обновляет предыдущий объект свойства, поэтому обратите внимание, что вы вероятно, должно использовать одно и то же имя для каждого набора, get и delete function / method.)
После определения выше первоначальная настройка, получение и удаление одинаковы:
obj = Obj() obj.attribute = value the_value = obj.attribute del obj.attribute
Вы должны избегать этого:
blockquote>def set_property(property,value): def get_property(property):
Во-первых, это не работает, потому что вы не предоставляете аргумент для экземпляра, который будет иметь свойство (обычно
self
), который будет:class Obj: def set_property(self, property, value): # don't do this ... def get_property(self, property): # don't do this either ...
Во-вторых, этот дубликат (f15) и
__getattr__
.В-третьих, у нас также есть встроенные функции
setattr
иgetattr
.setattr(object, 'property_name', value) getattr(object, 'property_name', default_value) # default is optional
@property
decorator предназначен для создания геттеров и сеттеров.Например, мы могли бы изменить поведение установки, чтобы установить ограничения на заданное значение:
class Protective(object): @property def protected_value(self): return self._protected_value @protected_value.setter def protected_value(self, value): if acceptable(value): # e.g. type or range check self._protected_value = value
В общем, мы хотим чтобы избежать использования
property
и просто использовать прямые атрибуты.Это то, что ожидается от пользователей Python. Следуя правилу наименьшего удивления, вы должны попытаться дать своим пользователям то, что они ожидают, если у вас нет очень веских оснований для обратного.
Демонстрация
Например, скажем, нам нужно наш атрибут защиты объекта должен быть целым числом от 0 до 100 включительно и предотвратить его удаление, с соответствующими сообщениями, чтобы информировать пользователя о его правильном использовании:
class Protective(object): def __init__(self, start_protected_value=0): self.protected_value = start_protected_value @property def protected_value(self): return self._protected_value @protected_value.setter def protected_value(self, value): if value != int(value): raise TypeError("protected_value must be an integer") if 0 <= value <= 100: self._protected_value = int(value) else: raise ValueError("protected_value must be " + "between 0 and 100 inclusive") @protected_value.deleter def protected_value(self): raise AttributeError("do not delete, protected_value can be set to 0")
И использование:
>>> p1 = Protective(3) >>> p1.protected_value 3 >>> p1 = Protective(5.0) >>> p1.protected_value 5 >>> p2 = Protective(-5) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 3, in __init__ File "<stdin>", line 15, in protected_value ValueError: protectected_value must be between 0 and 100 inclusive >>> p1.protected_value = 7.3 Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 17, in protected_value TypeError: protected_value must be an integer >>> p1.protected_value = 101 Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 15, in protected_value ValueError: protectected_value must be between 0 and 100 inclusive >>> del p1.protected_value Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 18, in protected_value AttributeError: do not delete, protected_value can be set to 0
Имеются ли названия?
Да, они делают .
.setter
и.deleter
делают копии исходного свойства. Это позволяет подклассам правильно изменять поведение, не изменяя поведение родителя.class Obj: """property demo""" # @property def get_only(self): return self._attribute # @get_only.setter def get_or_set(self, value): self._attribute = value # @get_or_set.deleter def get_set_or_delete(self): del self._attribute
Теперь для этого вам нужно использовать соответствующие имена:
obj = Obj() # obj.get_only = 'value' # would error obj.get_or_set = 'value' obj.get_set_or_delete = 'new value' the_value = obj.get_only del obj.get_set_or_delete # del obj.get_or_set # would error
I «Не знаю, где это было бы полезно, но прецедент - это если вы хотите получить свойство get, set и / или delete-only. Вероятно, лучше всего придерживаться семантически одного и того же свойства с тем же именем.
Заключение
Начать с простых атрибутов.
Если позже вам понадобится функциональность вокруг настройки, , и удаляя его, вы можете добавить его с помощью декоратора свойств.
Избегайте функций с именем
set_...
иget_...
- вот для чего нужны свойства.
Полное владение Groovy - это хорошо, но не обязательно. Можно начать работу с Grails, не изучая Groovy.
"Grails In Action" содержит красивую вводную часть в Groovy.
Я думаю, что более важно иметь основу для Spring и Hibernate, чтобы вы могли знать, что происходит.
Если вы программист на Java, вам практически не придется изучать Groovy. Вы можете вернуться к Java, когда захотите. Просто начните с grails, и вы изучите Groovy на ходу. Groovy просто упрощает работу с Java с помощью API управления списками, замыканий, синтаксического анализа XML и т. Д.
У меня есть коллега, который запустил Grails без знания Groovy и освоил этот язык, но он по-прежнему писал гораздо менее эффективный и раздутый код Grails, просто «вернувшись к Java», поскольку изучение Groovy - это больше, чем изучение синтаксиса.
Изучение Groovy - это изменение ваших привычек программирования, а Grails - даже больше. Поэтому вам следует потратить неделю на чистый Groovy с «Groovy в действии», прежде чем запускать «Grails в действии», или просто посетите Руководство пользователя Groovy , чтобы узнать, чем отличаются от других языков.
Groovy очень легко подобрать, если вы знаете java. Если нет, то это немного сложно (но не сильно).
Вы также можете изучать grails вместе с Groovy одновременно, если вы знаете Java и концепции программирования в целом (такие вещи, как структуры данных (карты, связанные списки и т. Д.) ), циклы, рекурсия и т. д.)
Если вы не знаете Java или никогда раньше не программировали, то я предлагаю вам начать с основ http://groovy.codehaus.org/Beginners+Tutorial или сначала поучитесь по книге, прежде чем начинать работу с grails. В противном случае некоторые ярлыки / идиомы в groovy / grails могут вас до бесконечности запутать.