Я делаю это так:
def set_property(property,value):
def get_property(property):
или
object.property = value
value = object.property
Я новичок в Python, так что я все еще изучаю синтаксис, и я хотел бы несколько советов по этому вопросу.
python
getter-setter
Хорхе Губерте
источник
источник
._x
(который не является свойством, просто атрибут) обходятproperty
перенос. Только ссылки, чтобы.x
пройтиproperty
.«Pythonic» - это не использование «получателей» и «сеттеров», а использование простых атрибутов, как показано в вопросе, и
del
для удаления (но имена изменяются для защиты невинных ... встроенных):Если позже вы захотите изменить настройки и получить, вы можете сделать это без необходимости изменять код пользователя, используя
property
декоратор:(Каждое использование декоратора копирует и обновляет предыдущий объект свойства, поэтому обратите внимание, что вы должны использовать одно и то же имя для каждого набора, получения и удаления функции / метода.
После определения вышеизложенного исходная настройка, получение и удаление кода остаются прежними:
Вам следует избегать этого:
Во-первых, вышеприведенное не работает, потому что вы не предоставляете аргумент для экземпляра, для которого свойство будет установлено (обычно
self
), а именно:Во-вторых, это дублирует назначение двух специальных методов
__setattr__
и__getattr__
.В- третьих, мы также имеем
setattr
иgetattr
встроенные функции.@property
Декоратор для создания методов получения и установки.Например, мы могли бы изменить поведение настройки, чтобы наложить ограничения на устанавливаемое значение:
В общем, мы хотим избежать использования
property
и просто использовать прямые атрибуты.Это то, что ожидается от пользователей Python. Следуя правилу наименьшего удивления, вы должны стараться дать своим пользователям то, что они ожидают, если у вас нет веских причин для обратного.
демонстрация
Например, скажем, нам нужно, чтобы атрибут защищенного объекта был целым числом от 0 до 100 включительно, и предотвращали его удаление с соответствующими сообщениями, информирующими пользователя о его правильном использовании:
(Обратите внимание, что это
__init__
относится кself.protected_value
методам свойств, к которым они относятсяself._protected_value
. Это делается для того, чтобы__init__
использовать свойство через открытый API, гарантируя, что оно «защищено».)И использование:
Имена имеют значение?
Да, они делают .
.setter
и.deleter
сделайте копии оригинальной собственности. Это позволяет подклассам корректно изменять поведение, не изменяя поведения в родительском.Теперь, чтобы это работало, вы должны использовать соответствующие имена:
Я не уверен, где это было бы полезно, но вариант использования - если вы хотите получить, установить и / или удалить только свойство. Вероятно, лучше придерживаться семантически одного и того же свойства, имеющего то же имя.
Вывод
Начните с простых атрибутов.
Если вам позже понадобится функциональность, связанная с настройкой, получением и удалением, вы можете добавить ее с помощью декоратора свойств.
Избегайте именованных функций
set_...
иget_...
- вот для чего нужны свойства.источник
__init__
метод относится к методу , а к методуself.protected_value
getter и settersself._protected_value
. Не могли бы вы объяснить, как это работает? Я проверил ваш код, и он работает как есть - так что это не опечатка.__init__
не так ли?self.protected_value = start_protected_value
что на самом деле вызывает функцию-установщик; Я думал, что это было задание.источник
Использование
@property
и@attribute.setter
помогает вам не только использовать «питонический» способ, но и проверять действительность атрибутов как при создании объекта, так и при его изменении.Таким образом, вы фактически «скрываете»
_name
атрибут от разработчиков клиента, а также выполняете проверки типа свойства name. Обратите внимание, что следуя этому подходу, даже во время инициации вызывается установщик. Так:Приведет к:
Но:
источник
Проверьте
@property
декоратор .источник
Вы можете использовать аксессоры / мутаторы (то есть
@attr.setter
и@property
) или нет, но самое главное, чтобы быть последовательным!Если вы используете
@property
для доступа к атрибуту, например,используйте его для доступа к каждому * атрибуту! Было бы плохой практикой обращаться к некоторым атрибутам, используя
@property
и оставлять некоторые другие свойства общедоступными (например, имя без подчеркивания) без доступа, например , не делатьОбратите внимание, что
self.b
здесь нет явного средства доступа, даже если оно общедоступно.Точно так же с сеттерами (или мутаторами ), не стесняйтесь использовать,
@attribute.setter
но будьте последовательны! Когда вы делаете, например,Мне трудно угадать ваше намерение. С одной стороны, вы говорите, что оба
a
иb
являются общедоступными (без подчеркивания в их именах), поэтому мне теоретически должно быть разрешено получить доступ / изменить (получить / установить) оба. Но тогда вы указываете явный мутатор только дляa
, который говорит мне, что, возможно, я не должен быть в состоянии установитьb
. Поскольку вы предоставили явный мутатор, я не уверен,@property
означает ли отсутствие явного accessor ( ), что я не смогу получить доступ ни к одной из этих переменных, или вы просто экономно использовали@property
.* Исключение составляют случаи, когда вы явно хотите сделать некоторые переменные доступными или изменяемыми, но не оба, или вы хотите выполнить некоторую дополнительную логику при доступе или изменении атрибута. Это когда я лично использую
@property
и@attribute.setter
(в противном случае нет явных acessors / mutators для открытых атрибутов).Наконец, предложения PEP8 и Google Style Guide:
PEP8, Проектирование для Наследования говорит:
С другой стороны, в соответствии с Руководством по стилю Google Python Language Rules / Properties рекомендуется:
Плюсы этого подхода:
и минусы:
источник
@property
, использование остальных также@property
кажется плохим решением.@property
(например, выполнение некоторой специальной логики перед возвратом атрибута). В противном случае, почему вы бы украшали один атрибут,@propery
а не другие?@property
для начала, верно? Если ваш геттер есть,return this._x
а ваш сеттер естьthis._x = new_x
, то использовать его@property
вообще глупо.@property
- это быть последовательным».Вы можете использовать магические методы
__getattribute__
и__setattr__
.Имейте в виду, что
__getattr__
и__getattribute__
не то же самое.__getattr__
вызывается только когда атрибут не найден.источник