Что такое питонический способ использования геттеров и сеттеров?
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_...
- вот для чего нужны свойства.
Это - ошибка периода выполнения, которая вызывается Dynamic Linker
dyld: Library not loaded: @rpath/...
...
Reason: image not found
, ошибка Library not loaded
с @rpath
<глоток> [О] глоток> указывает, что Dynamic Linker
не может найти платформу.
Проверка, если платформа была добавлена к General -> Embedded Binaries
Проверка, если @rpath
- Build Settings -> Runpath Search Paths
содержит путь с тем же местом назначения/подпутем, как была установка в Build Phases -> Embed Frameworks -> Destination, Subpath
Read больше здесь
Если Вы используете Xcode 11 или более новые :
Прокручивают вниз к [1 116] Платформы, Библиотеки и Встроенное Содержание .
Удостоверяются эти , Встраивают & Знак или Встройте, Не Подписываясь , значение выбрано для опция Embed при необходимости.
Xcode 11
В [1 121] Xcode 11
я сталкивался с тем же выпуском
, Изменяющимся , "Не Встраивают" в [1 123] вкладка "Общие" > "Платформы, Библиотеки, и Встроенное Содержание" все еще заканчивалось та же ошибка.
то, Что сделало решенный для меня, добавляло Платформа в [1 126] Вкладка Фаз разработки> раздел Embed Frameworks
- Обновленный---
, я заметил, что в проектах, разработанных в предыдущих версиях Xcode , Встраивают Раздел Платформ , не доступно при выполнении в Xcode 11 Найдите ниже шагов достигать решения:
1: Первая потребность добавить Новая Фаза Файлов Копии под [1 130] вкладка Build Phases .
2: Второе изменение название добавленной фазы к [1 131] Встраивает Платформы
3: Измените место назначения на [1 132] Платформы .
4: Добавьте платформу, для которой произошла ошибка.