- Часть I. Вводное руководство
- Глава 2. Использование интерпретатора
- 2.2. Интерпретатор и его среда
- 9.4. Выборочные замечания
9.4. Выборочные замечания
Атрибуты экземпляров (обычно атрибуты данных) записываются поверх атрибутов классов (обычно методов) с тем же именем. Чтобы избежать конфликтов имен, которые могут привести к тяжело обнаружимым ошибкам, полезно использовать своего рода соглашение, позволяющее минимизировать вероятность конфликтов. Например: называть методы именами, начинающимися с заглавной буквы, добавлять небольшую приставку в начало имен атрибутов данных (возможно просто символ подчеркивания) или использовать глаголы для методов и существительные для атрибутов данных.
В некоторых случаях изменение атрибутов данных напрямую, а не с помощью специально предназначенных для этого методов, может привести к порче инварианта объекта и непригодности его для дальнейшего использования. Вы можете "спрятать" данные и, тем самым, защитить их от случайного изменения. Для этого в языке существует соглашение: все атрибуты, имена которых содержат не менее двух символов подчеркивания в начале и не более одного символа подчеркивания в конце, считаются частными и доступны только из методов объекта. (На самом деле, Вы можете получить доступ к частным атрибутам извне, используя специальное имя, однако такой доступ никак не назовешь случайным. Более подробно работа с частными атрибутами описана в разделе 9.6.) С другой стороны, модули расширения, написанные на C, могут полностью спрятать детали реализации и при необходимости полностью контролировать доступ.
Обычно первый аргумент в определении метода называют self. Это не более чем соглашение: имя self не имеет абсолютно никакого специального значения. Однако, следуя этому соглашению, Вы делаете код более понятным для других программистов. (Некоторые программы, например программы просмотра классов, рассчитаны на то, что пользователь всегда следует этому соглашению.)
Любой объект-функция, являющийся атрибутом класса, определяет метод экземпляров этого класса. Совсем не обязательно, чтобы определение функции находилось в определении класса: присваивание объекта-функции локальной переменной также будет работать. Например:
# Определение функции за пределами определения класса
def f1(self, x, y):
return min(x, x+y)
class C:
f = f1
def g(self):
return 'Привет всему миру'
h = g
Теперь f, g и h являются атрибутами класса C и ссылаются на объекты функции и, следовательно, все они будут методами экземпляров класса C. Вы можете также использовать функцию, определенную с помощью оператора lambda. Заметим, что такая практика обычно только сбивает с толку.
Методы могут вызывать другие методы, как атрибуты аргумента self, например:
class Bag:
def __init__(self):
self.data = []
def add(self, x):
self.data.append(x)
def addtwice(self, x):
self.add(x)
self.add(x)
Методы могут ссылаться на глобальные имена точно таким же способом, как и обычные функции. Глобальная область видимости, ассоциированная с методом — это глобальное пространство имён модуля, содержащего определение функции (так как определение функции обычно находится в определении класса, то — в глобальном пространстве имён модуля, содержащего определение класса). В то время как редко существует веская причина использовать глобальные данные в методе, глобальная область видимости всё же находит множество разумных применений: использование импортированных в глобальную область видимости модулей, а также определённых в ней функций и классов.
Атрибуты классов ведут себя как статические атрибуты их экземпляров (то есть общие для всех экземпляров данного класса). Однако присвоить такому атрибуту новое значение Вы можете, только обратившись к нему как атрибуту того класса, в котором он определён (в противном случае Вы лишь создадите новый атрибут экземпляра с таким же именем).