Доступ к переменным класса через экземпляр
В Python переменные класса могут быть доступны через этот экземпляр класса:
>>> class A(object):
... x = 4
...
>>> a = A()
>>> a.x
4
Легко показать, что a.x
действительно разрешено a.x
, а не копируется в экземпляр во время построения:
>>> A.x = 5
>>> a.x
5
Несмотря на то, что это поведение хорошо известно и широко используется, я не смог найти окончательную документацию, охватывающую его. Наиболее близким, которое я мог найти в документах Python, был раздел в классах:
class MyClass:
"""A simple example class"""
i = 12345
def f(self):
return 'hello world'
[надрез]
... По определению все атрибуты класса, которые являются объектами-объектами, определяют соответствующие методы его экземпляров. Поэтому в нашем примере x.f
является допустимым методом, так как MyClass.f
является функцией, но x.i
не является, так как MyClass.i
не является....
Однако в этой части речь идет конкретно о методах, поэтому она, вероятно, не относится к общему случаю.
Мой вопрос в том, что это документировано? Могу ли я полагаться на это поведение?
Ответы
Ответ 1
Обозначает части Classes
и Class instances
в http://docs.python.org/reference/datamodel.html
Класс имеет пространство имен, реализуемое объектом словаря. Класс ссылки на атрибуты переводится в поисковые запросы в этом словаре, например, C.x переводится в C.__ dict __ [ "x" ] (хотя для классов нового стиля, в частности, имеется несколько крючков, которые допускают другие способы определения атрибутов)
Экземпляр класса создается путем вызова объекта класса (см. выше). экземпляр класса имеет пространство имен, реализованное как словарь, который первое место, в котором выполняется поиск ссылок атрибутов. Когда атрибут там не найден, а класс экземпляров имеет атрибут по этому имени, поиск продолжается с классом атрибуты.
Как правило, это использование прекрасное, за исключением особых случаев, упомянутых как "классы нового стиля, в частности, есть несколько крючков, которые позволяют использовать другие способы определения атрибутов".
Ответ 2
Вы можете не только полагаться на это поведение, но и постоянно.
Подумайте о методах. Метод - это просто функция, которая была сделана атрибутом класса. Затем вы посмотрите на экземпляр.
>>> def foo(self, x):
... print "foo:", self, x
...
>>> class C(object):
... method = foo # What a weird way to write this! But perhaps illustrative?
...
>>> C().method("hello")
foo: <__main__.C object at 0xadad50> hello
В случае объектов, подобных функциям, это не простой поиск, но возникает какая-то магия, чтобы передать self
автоматически. Возможно, вы использовали другие объекты, предназначенные для хранения в качестве атрибутов класса, и просмотрели экземпляр; свойства являются примером (ознакомьтесь с property
встроенным, если вы не знакомы с ним.)
Как примечания okm, способ, которым это работает, описан в ссылке на модель данных (включая информацию о ссылках на дополнительную информацию о магии, которая делает методы и свойства работы). Страница модели данных является, безусловно, наиболее полезной частью справочника языка; он также включает, помимо прочего, документацию почти о всех методах и именах __foo__
.