Автор оригинала: Ogunbiyi Ibrahim.
Привет, ребята , в этом посте в блоге мы собираемся углубиться в некоторые приемы программирования на python, или я скажу, что функции , которые мы можем использовать как разработчики python , мы все знаем, что каждая вещь в python-это объект, класс-это объект, экземпляр-это объект, функция-это объект и т. Д.
Мы все знаем это в любое время, когда мы это делаем:
object.attribute or object.attribute = value`
Мы пытаемся получить атрибут или установить атрибут объекта, который очень распространен во всех программах python, особенно при работе с классами .
Ну и что ? почему тебя это должно волновать?
Так почему же вы должны беспокоиться об управлении атрибутами , теперь позвольте мне разбить его , вот несколько возможных сценариев:
ПРИМЕР ИСПОЛЬЗОВАНИЯ № 1
Мы знаем , что в python мы можем получить доступ к любому атрибуту класса , обратившись к нему с помощью obj.attribute.call , что означает, что наши атрибуты открыты для различных операций, таких как чтение, запись, удаление. Вот пример в приведенном ниже фрагменте кода:
Когда этот код выполняется , ниже приведен результат:
>>> John Doe you a confirmed user >>> John Doe you're not yet confirmed
Вы можете видеть, что мы изменили состояние нашего объекта вне контекста класса , когда ссылаемся на атрибут confirmed и устанавливаем для него значение false.
В большинстве случаев мы не хотим , чтобы мы устанавливали разрешение на наш атрибут , например, доступ только для чтения или доступ к атрибутам чтения и записи, т. е. В других случаях, чтобы предотвратить изменение состояния нашего класса внешним миром.
ПРИМЕР ИСПОЛЬЗОВАНИЯ № 2
Иногда мы хотим подключиться к атрибуту и внести в него некоторые изменения в тот момент, когда к нему обращаются такие вызовы, как этот:
>>> obj.attribute >>> obj.attribute = value
управление атрибутами играет здесь большую роль, как мы увидим в этом посте, есть больше вариантов использования, но мы покинем этот город, чтобы не делать этот пост громоздким.
Особенности:
Вот функции python, которые помогают нам управлять доступом к атрибутам в нашем коде
- Методы __getattr__ и __setattr__ для маршрутизации неопределенных выборок атрибутов и всех назначений атрибутов общим методам обработчика.
- Метод __getattribute__ для маршрутизации всех извлечений атрибутов в общий метод обработчика.
- Встроенное свойство | для маршрутизации доступа к определенным атрибутам для получения и установки функций обработчика. Протокол
- дескриптор , для маршрутизации определенных атрибутов доступа к экземплярам классов с произвольными методами обработчика get и set, а также основой для других инструментов, таких как свойства и слоты.
В этом посте я рассмотрю последние две функции в приведенном выше списке,
я обещаю создать еще один пост, который объяснит два других.
Предпосылки
Чтобы использовать этот пост , необходимы базовые знания ” ООП “ python, также, если вы пробуете примеры с python 2.x, обратите внимание, что вы должны использовать классы new-style.
Протокол свойств
Протокол свойств позволяет нам направлять определенные операции get , set и delete в функции или методы , которые мы предоставляем, что позволяет нам вставлять код, который будет автоматически выполняться при доступе к атрибутам, перехватывать удаление атрибутов и при желании предоставлять документацию по атрибутам.
Свойство создается путем присвоения результата встроенной функции атрибуту класса:
>>> attribute = property(fget, fset, fdel, doc)
Атрибут свойства принимает четыре необязательных позиционных аргумента, где первым аргументом является обратный вызов для запуска, когда при ссылке на атрибут этот обратный вызов возвращает значение.
Второй аргумент-это обратный вызов, который выполняется, когда объекту присваивается значение, этот обратный вызов возвращает None.
>>> obj.attribute = value
Третий аргумент – ‘ fdel’ является обратным вызовом, когда операция ‘ del ‘ выполняется над атрибутом, этот обратный вызов возвращает None.
В то время как последний аргумент doc-это doc-строка.
Все эти аргументы являются необязательными, если один из них не передан, и мы пытаемся выполнить операцию, которая вызывает исключение ‘ AttributeError’ , указывающее, что операция не разрешена .
достаточно истории, позвольте мне показать вам, как это работает в коде
Этот фрагмент кода слева от вас не делает ничего значимого , но он показывает, как встроенное свойство может использоваться , когда на атрибут ссылаются или присваивают значение, вот результат при выполнении кода.
>>> getting attribute >>> John Doe >>> setting value >>> This is person name
С тем фактом, что мы можем подключаться, когда на атрибут ссылаются, это платформа для нас, чтобы создать некоторую модификацию доступа к атрибутам здесь, где мы можем предоставить доступ только для чтения к name атрибуту, используемому в этом контексте.
Давайте удалим ‘setName’ и ‘delName’ метод, который мы передали в наше встроенное в него свойство, и предоставим ему доступ только для чтения.
Вот что мы получаем, когда запускаем этот код:
>>> getting attribute John Doe Traceback (most recent call last): File "/home/user/path/python\_files/read\_only\_property.py", line 14, in \person1.name = 'smith' AttributeError: can't set attribute
С помощью приведенного выше кода мы установили атрибут name как атрибут только для чтения, в результате чего, если мы попытаемся установить для него новое значение , мы получим ошибку.
Что делать, если мы не хотим, чтобы атрибут был доступен для чтения и записи? это просто, мы устанавливаем атрибут на встроенное свойство, не передавая ему никаких аргументов, подобных этому:
И если атрибут name извлекается или устанавливается, возникает исключение.
>>> Traceback (most recent call last): File "/home/user/path/python\_files/pratice.py", line 13, in \print(person1.name) AttributeError: unreadable attribute
Давайте перейдем к более значимому варианту использования протокола свойств, скажем, у нас есть класс Employee , который собирает имя сотрудника и зарплату в момент создания экземпляра, и мы хотим , чтобы он вычитал налог из зарплаты всякий раз, когда на атрибут зарплаты ссылаются, приведенный ниже код показывает, как:
Вот результат.
Вы можете видеть, что в момент получения атрибута мы подключились к процессу и выполнили некоторый код, возвращая значение.
Свойство кодирования с помощью декоратора
Свойство кодирования с этим синтаксисом выше прекрасно, но есть более питонический способ сделать это с помощью декораторов python, это возможно, потому что декораторы-это просто повторная привязка имени функции.
class Person: @property def name(self): ... same as : name = property(name)
Пример:
Используя приведенный выше пример класса employee,
теперь я переработал наш код, чтобы использовать синтаксис декоратора свойств для выполнения того же эффекта, что и другой. У декоратора свойств есть атрибут для получения , установки и удаления атрибута
@property.getter for specifying the get function @attribute_name.setter for specifying the set function @attribute_name.deleter for specifying the del function the getter attribute on the property decorator function is optional because a call to @property() take getter has it default
Вывод
Вот она, одна из функций для управления доступом к атрибутам в python , есть больше вариантов использования этой функции , все еще выясняя их по мере того, как я узнаю больше .
Примечание: Я должен был также объяснить протокол дескриптора в этом посте, но я пропустил это , чтобы не делать этот пост громоздким, в ближайшее время будет размещен специальный пост на протоколе дескриптора .
Если у вас есть предложение , вопрос или вы заметили ошибку в этом посте , пожалуйста, прокомментируйте ниже или свяжитесь со мной в twitter
Спасибо , Счастливого Пифонинга!