В этой заметке я хотел бы привести краткое описание методов регулирования доступа к атрибутам класса в питоне с помощью декораторов и с помощью присвоения специальным образом имен атрибутам в соответсвии с хорошим стилем программирования, описанным в PEP 8 . Статья написана на основе обсуждений данной темы на StackOverflow.com, нескольких мануалов и личного опыта автора.
Занимаясь написанием программ, выполняющие научные расчеты, я перешел с c++
на питон, чтобы использовать всю мощь библиотек, к которым относятся numpy, scipy, matplotlib, pyquante и прочие, распространяющиеся под свободной лицензией и находящихся в избытке на github. Однако, на начальном этапе такого перехода у меня возник дискомфорт, связанный с отсутствием таких привычных в с++ модификаторов доступа, как privat
, public
и protected
, а также методов get()
и set()
, что и побудило меня написать эту заметку. На StackOverflow первое, что бросается в глаза при обсуждении отсутствия модификаторов доступа в питоне, — это всеобщее согласие с большой долей ответственности разработчика при написании кода, которая побуждает его соблюдать хороший стиль программирования, описанный в PEP 8 . Проблема заключается в том, что в питоне всегда можно получить доступ к любому атрибуту любого класса, однако, согласно хорошему стилю, такой доступ пользователями библиотеки классов должен быть осуществлен не прямо, а с помощью некоторого интерфейса и только там, где это нужно и предусмотрено разработчиком.
Рассмотрим класс, содержащий атрибут attr
:
class MyClass:
def __init__(self):
self.attr = 0
Существует очевидная возможность доступа к атрибуту напрямую после создания объекта класса:
a=Class()
a.attr
Этим способом обращения лучше не злоупотреблять. Для того, чтобы имитировать наличие модификатора доступа privat, можно использовать подчеркивание в начале всех имен атрибутов:
class MyClass:
def __init__(self):
self._attr = 0
Конечно, в этом случае к атрибуту можно обратиться извне класса как:
a._attr
Но каждый раз видя этот код вы будете знать, что: а) осуществляется обращения к атрибуту объекта а
и б) ваш код не соответствует хорошему стилю программирования, поскольку атрибут этого класса с таким именем не предусматривает, что к нему будут обращаться вне определения класса.
Если все же есть необходимость предоставить пользователю доступ к атрибуту данного класса, лучше использовать декоратор @property
. Например:
class MyClass:
def __init__(self):
self.attr = 0
@property
def attr(self):
return self._attr
Читать полностью »