Атрибуты объектов Python - методология для доступа

Дополнительный пример с использованием Guava:

URL xmlData = ...
String data = Resources.toString(xmlData, Charsets.UTF_8);
23
задан user 4 June 2012 в 05:10
поделиться

7 ответов

Общепринятый способ сделать вещи просто использует простые атрибуты, как так

>>> class MyClass:
...     myAttribute = 0
... 
>>> c = MyClass()
>>> c.myAttribute 
0
>>> c.myAttribute = 1
>>> c.myAttribute
1

, Если Вы действительно должны, чтобы быть в состоянии записать методам get и методам set, тогда что Вы хотите искать, "свойства класса Python" и , статья Ryan Tomayko о Getters/Setters/Fuxors является великолепным местом для запуска (хотя немного долго)

23
ответ дан nealmcb 29 November 2019 в 00:41
поделиться

Относительно одинарного и двойного подчеркивания: оба обозначают одно и то же понятие «приватность». То есть люди будут знать, что атрибут (будь то метод, «нормальный» атрибут данных или что-то еще) не является частью общедоступного API объекта. Люди будут знать, что прикоснуться к нему напрямую - значит вызвать катастрофу.

Кроме того, атрибуты нижнего подчеркивания с двумя ведущими символами (но не атрибуты нижнего подчеркивания с одним ведущими) именуются , чтобы сделать доступ к ним случайно из подклассов или из любого места. иначе за пределами текущего класса менее вероятно. Вы все еще можете получить к ним доступ, но не так тривиально. Например:

>>> class ClassA:
...     def __init__(self):
...         self._single = "Single"
...         self.__double = "Double"
...     def getSingle(self):
...         return self._single
...     def getDouble(self):
...         return self.__double
... 
>>> class ClassB(ClassA):
...     def getSingle_B(self):
...         return self._single
...     def getDouble_B(self):
...         return self.__double
... 
>>> a = ClassA()
>>> b = ClassB()

Теперь вы можете тривиально получить доступ к a._single и b._single и получить атрибут _single, созданный ClassA:

>>> a._single, b._single
('Single', 'Single')
>>> a.getSingle(), b.getSingle(), b.getSingle_B()
('Single', 'Single', 'Single')

Но пытаясь получить доступ атрибут __double в экземпляре a или b напрямую не будет работать:

>>> a.__double
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: ClassA instance has no attribute '__double'
>>> b.__double
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: ClassB instance has no attribute '__double'

И хотя методы, определенные в ClassA, могут получить его напрямую (при вызове в любом экземпляре) :

>>> a.getDouble(), b.getDouble()
('Double', 'Double')

Методы, определенные в ClassB, не могут:

>>> b.getDouble_B()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 5, in getDouble_B
AttributeError: ClassB instance has no attribute '_ClassB__double'

И прямо в этой ошибке вы получите подсказку о том, что происходит. Имя атрибута __double, когда осуществляется доступ внутри класса, обрабатывается по имени, чтобы включать имя класса, к которому он обращается в . Когда ClassA пытается получить доступ к self.__double, он фактически превращается - во время компиляции - в доступ к self._ClassA__double, а также для ClassB. (Если бы метод из ClassB был назначен для __double, не включенный в код для краткости, он не коснулся бы __double ClassA, но создал бы новый атрибут.) Другой защиты от этот атрибут, так что вы можете получить к нему прямой доступ, если знаете правильное имя:

>>> a._ClassA__double, b._ClassA__double
('Double', 'Double')

Так почему же это проблема?

Ну, это проблема в любое время вы хотите наследовать и изменять поведение любого кода, имеющего дело с этим атрибутом. Вы должны либо переопределить все, что непосредственно касается этого атрибута с двойным подчеркиванием, либо вы должны угадать имя класса и изменить имя вручную. Проблема усугубляется, когда этот атрибут с двойным подчеркиванием на самом деле является методом: переопределение метода или вызов метода в подклассе означает ручное преобразование имени или повторную реализацию всего кода, который вызывает метод, чтобы не используйте двойное подчеркивание Не говоря уже о динамическом доступе к атрибуту с помощью getattr(): вам также придется вручную там манипулировать.

С другой стороны, поскольку атрибут только тривиально переписан, он предлагает только поверхностную «защиту». Любой фрагмент кода все еще может получить атрибут, вручную искажая, хотя это сделает их код зависимым от имени вашего класса , и усилия на вашей стороне по рефакторингу вашего кода или переименование вашего класса (при сохранении того же имени, видимого пользователю, что является обычной практикой в ​​Python) без необходимости нарушит их код. Они также могут «обмануть» Python, выполнив для них распределение имен, назвав их класс таким же, как ваш: обратите внимание, что в названии искаженного атрибута нет имени модуля. И наконец, атрибут с двойным подчеркиванием по-прежнему виден во всех списках атрибутов и во всех формах самоанализа, в которых не пропускаются атрибуты, начиная с подчеркивания ( single ).

Итак, , если вы используете имена с двойным подчеркиванием, используйте их крайне редко, так как они могут оказаться довольно неудобными, и никогда не используйте их для методов или чего-либо еще, что подкласс может захотеть переопределение, переопределение или прямой доступ . И поймите, что двойное подчеркивание - искажение имен не предлагает никакой реальной защиты . В конце концов, использование единственного подчеркивания выигрывает у вас столько же и дает вам меньше (потенциальное, будущее) боль. Используйте одно начальное подчеркивание.

57
ответ дан Thomas Wouters 29 November 2019 в 00:41
поделиться

Я думаю, что большинство просто обращаются к ним напрямую, нет необходимости в методах get / set.

>>> class myclass:
...     x = 'hello'
...
>>>
>>> class_inst = myclass()
>>> class_inst.x
'hello'
>>> class_inst.x = 'world'
>>> class_inst.x
'world'

Кстати, вы можете использовать функцию dir (), чтобы увидеть, какие атрибуты / методы прикреплены к вашему экземпляру:

>>> dir(class_inst)
['__doc__', '__module__', 'x']

Два ведущих подчеркивания, «__», используются для создания атрибута или функция частная. Другие соглашения см. В PEP 08: http://www.python.org/dev/peps/pep-0008/

.
3
ответ дан monkut 29 November 2019 в 00:41
поделиться

Редактирование: можно ли уточнить лучшие практики именования атрибутов с единственным или двойным начальным символом подчеркивания? Я вижу в большинстве модулей, что одинарное подчеркивание используется.

Одинарное подчеркивание не означает ничего специального для Python, это - просто лучшая практика, для сообщения "эй, что Вы, вероятно, не хотите получать доступ к этому, если Вы не знаете то, что Вы делаете". Двойное подчеркивание однако заставляет Python исказить имя, внутренне делающее его доступный только от класса, где это определяется.

Двойное продвижение И запаздывающее подчеркивание обозначают специальную функцию, такой как __add__, который называют при использовании + оператор.

Read больше в PEP 8, особенно раздел "Naming Conventions".

8
ответ дан Thomas Wouters 29 November 2019 в 00:41
поделиться

Python не должен определять средства доступа с самого начала, начиная с преобразования атрибутов в свойства является быстрым и безболезненным. Посмотрите следующее для яркой демонстрации:

Восстановление после Склонности

1
ответ дан Ignacio Vazquez-Abrams 29 November 2019 в 00:41
поделиться

Некоторые люди используют методов get и методы set. В зависимости от которого стиля кодирования Вы используете Вас, может назвать их getSpam и seteggs. Но можно также сделать Вас, приписывает только для чтения, или присвойтесь только. Это немного неудобно сделать. Один путь переопределяет

> __getattr__

и

> __setattr__

методы.

Редактирование:

, В то время как мой ответ все еще верен, это не правильно, когда я сообразил. Существуют лучшие способы сделать средства доступа в Python и не являются очень неловкими.

-2
ответ дан Vasil 29 November 2019 в 00:41
поделиться

В Python нет смысла делать getter / setters, вы все равно не можете защитить вещи, и если вам нужно выполнить какой-то дополнительный код при получении / установке свойства, взгляните на встроенную функцию () (python -c ' помощь (недвижимость) ")

0
ответ дан Anders Waldenborg 29 November 2019 в 00:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: