Насколько я понимаю, в Python нет действительно закрытых методов / атрибутов, а это означает, что, пока вы знаете имя метода или атрибута, вы всегда сможете получить к нему доступ и / или изменить его (возможно, я неправильно понимаю понятие приватности).
Принимая во внимание структуру, описанную выше, я столкнулся с ситуацией, которую я не могу полностью обернуть вокруг себя. При создании matplotlib.pyplot
сюжета:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
fig, ax = plt.subplots()
x = np.arange(100)
ax.plot(x, np.sin(x), label='sinus')
ax.legend()
Я получаю объект matplotlib.legend.Legend
, содержащий список всех matplotlib.text.Text
объектов, которые напоминают текстовые записи, отображаемые в легенде:
>>> fig.axes[0].legend()
<matplotlib.legend.Legend at 0x28f6aa4d898>
>>> fig.axes[0].legend().get_texts()
<a list of 1 Text objects>
>>> fig.axes[0].legend().get_texts()[0]
<matplotlib.text.Text at 0x28f6aa17198>
>>> print(fig.axes[0].legend().get_texts()[0])
Text(0,0,'sinus')
Согласно исходному коду, мне кажется, что список, возвращаемый методом matplotlib.legend.Legend.get_texts()
, заполнен содержимым matplotlib.legend.Legend
переменной экземпляра self.texts
, которая сама является списком. Доступ и изменение этой переменной экземпляра не работает:
>>> fig.axes[0].legend().texts
[<matplotlib.text.Text at 0x28f6420db38>]
>>> print(fig.axes[0].legend().texts[0])
Text(0,0,'sinus')
>>> fig.axes[0].legend().texts = [matplotlib.text.Text(0,0,'foo')]
>>> print(fig.axes[0].legend().texts[0])
Text(0,0,'sinus')
Я не эксперт в Python, но я не ожидал такого поведения, и я не понимаю, как это происходит на уровне объекта / свойства, и я не следил глубже, если есть какие-то особые ограничения в конструкции переменной экземпляра matplotlib.legend.Legend.texts
.
Единственная общая причина, по которой я мог это сделать, заключалась в том, что на некотором уровне глубины существует некая «призрачная» установка, которая просто не изменяет свойство класса:
class Foo:
def __init__(self, value):
self._x = value
@property
def x(self):
return self._x
@x.setter
def x(self, value):
# This setter blocks outside access
pass
Этот сеттер блокирует управление извне для изменения значения переменной:
>>> f = Foo(3)
>>> f.x
3
f.x = 5
>>> f.x
3
Тем не менее, matplotlib.legend.Legend
переменная экземпляра self.texts
, похоже, определена как обычная переменная экземпляра, и я не смог найти ее, определенную как свойство или любые методы получения или установки, связанные с ним.
Итак, учитывая эту ситуацию, у меня есть три вопроса:
1) Является ли этот маленький пример класса приемлемым / законным способом получения «своего рода» конфиденциальности в том смысле, что атрибут не может быть изменен?
2) Существуют ли другие / эквивалентные способы блокировки доступа / контроля над атрибутами или методами в Python?
3) Как это работает или организовано в конкретном случае matplotlib.legend.Legend
объектов (фокус на переменной экземпляра self.texts
)?
Вопросы:
1) Я пытался найти ответы на эти вопросы и не смог. В частности, вопрос о том, как это поведение реализовано в matplotlib.legend.Legend
объектах, остается пока без ответа.
2) Я посмотрел на исходный код matplotlib.legend.Legend
и вижу, что функция matplotlib.legend.Legend.get_texts()
возвращает объект silent_list
, который, по-видимому, является просто объектом списка с переопределенным методом __repr__
. Все еще не помогает мне понять, что я скучаю.
3) Мне известно о наборе высокоуровневых методов в matplotlib.legend.Legend
объектах, которые позволяют мне изменять легенду многими / всеми возможными способами. Я просто хочу понять, как работает механизм под капотом.
Большое спасибо заранее за ваше время и помощь.