SyntaxError: "invalid syntax"
>>> def make_object(name, class_):
... pass
В общих чертах, замыкающий одинарный символ подчеркивания (пост-
фикс) используется по договоренности, чтобы избежать конфликтов из-
за совпадения имен с ключевыми словами Python. Эта договоренность
определена и объяснена в PEP 8.
3 . Двойной начальный символ подчеркивания: __var
Шаблоны именования, которые мы рассмотрели к этому моменту, по-
лучают свой смысл только из согласованной договоренности. В случае
атрибутов (переменных и методов) класса Python, которые начинаются
с двойных символов подчеркивания, все немного по-другому.
Префикс, состоящий из двойного символа подчеркивания, заставляет
интерпретатор Python переписывать имя атрибута для того, чтобы в под-
классах избежать конфликтов из-за совпадения имен.
Такое переписывание также называется искажением имени (name
mangling) — интерпретатор преобразует имя переменной таким образом,
что становится сложнее создать конфликты, когда позже класс будет
расширен.
Я знаю, звучит довольно абстрактно. Вот почему я подобрал этот неболь-
шой пример кода, который мы сможем использовать для эксперименти-
рования:
class Test:
def __init__(self):
self.foo = 11
self._bar = 23
self.__baz = 23
Давайте взглянем на атрибуты объекта, использовав встроенную функ-
цию
dir()
:
2 .4 . Подчеркивания, дандеры и другое 49
>>> t = Test()
>>> dir(t)
['_Test__baz', '__class__', '__delattr__', '__dict__',
'__dir__', '__doc__', '__eq__', '__format__', '__ge__',
'__getattribute__', '__gt__', '__hash__', '__init__',
'__le__', '__lt__', '__module__', '__ne__', '__new__',
'__reduce__', '__reduce_ex__', '__repr__',
'__setattr__', '__sizeof__', '__str__',
'__subclasshook__', '__weakref__', '_bar', 'foo']
Результат показывает список с атрибутами объекта. Давайте возьмем
этот список и отыщем наши первоначальные имена переменных
foo
,
_bar
,
и
__baz
. Обещаю, вы обнаружите несколько интересных изменений.
Прежде всего, в списке атрибутов переменная
self.foo
появляется неиз-
мененной как
foo
.
Далее,
self._bar
ведет себя таким же образом — она обнаруживается
в классе как
_bar
. Как уже было отмечено, в данном случае начальный
символ подчеркивания — это просто договоренность, подсказка про-
граммисту.
Однако с атрибутом
self.__baz
все выглядит немного по-другому. Когда
вы попытаетесь отыскать в списке атрибут
__baz
, вы увидите, что пере-
менной с таким именем там нет.
Так что же произошло с
__baz
?
Если вы приглядитесь, то увидите, что в этом объекте имеется атрибут
с именем
_Test__baz
. Это и есть искажение имени, которое применяет
интерпретатор Python. Это делается, чтобы защитить переменную от
переопределения в подклассах.
Давайте создадим еще один класс, который расширяет класс
Test
и пы-
тается переопределить его существующие атрибуты, добавленные в кон-
структоре:
class ExtendedTest(Test):
def __init__(self):
super().__init__()
self.foo = 'переопределено'
self._bar = 'переопределено'
self.__baz = 'переопределено'
50 Глава 2 • Шаблоны для чистого Python
Итак, какими, по вашему мнению, будут значения
foo
,
_bar
и
__baz
в эк-
земплярах класса
ExtendedTest
? Давайте посмотрим:
>>> t2 = ExtendedTest()
>>> t2.foo
Do'stlaringiz bilan baham: |