diff --git a/translations/README-ru.md b/translations/README-ru.md index a0ee30f..9eb5ed4 100644 --- a/translations/README-ru.md +++ b/translations/README-ru.md @@ -3222,3 +3222,80 @@ Ellipsis - Интересно, что хэш `float('-inf')` - "-10⁵ x π" в Python 3, тогда как в Python 2 - "-10⁵ x e". --- + + +### ▶ Давайте искажать + +1\. +```py +class Yo(object): + def __init__(self): + self.__honey = True + self.bro = True +``` + +**Результат:** +```py +>>> Yo().bro +True +>>> Yo().__honey +AttributeError: 'Yo' object has no attribute '__honey' +>>> Yo()._Yo__honey +True +``` + +2\. +```py +class Yo(object): + def __init__(self): + # Попробуем симметричные двойные подчеркивания в названии атрибута + self.__honey__ = True + self.bro = True +``` + +**Результат:** +```py +>>> Yo().bro +True + +>>> Yo()._Yo__honey__ +Traceback (most recent call last): + File "", line 1, in +AttributeError: 'Yo' object has no attribute '_Yo__honey__' +``` + +Почему обращение к `Yo()._Yo__honey` сработало? + +3\. + +```py +_A__variable = "Some value" + +class A(object): + def some_func(self): + return __variable # переменная еще не инициализирована +``` + +**Результат:** +```py +>>> A().__variable +Traceback (most recent call last): + File "", line 1, in +AttributeError: 'A' object has no attribute '__variable' + +>>> A().some_func() +'Some value' +``` + + +#### 💡 Объяснение: + +* [Искажение имени](https://en.wikipedia.org/wiki/Name_mangling) используется для предотвращения коллизий имен между различными пространствами имен. +* В Python интерпретатор изменяет (mangles) имена членов класса, начинающиеся с `__` (двойное подчеркивание, оно же "дундер") и не заканчивающиеся более чем одним подчеркиванием в конце, добавляя перед ними `_NameOfTheClass`. +* Таким образом, чтобы получить доступ к атрибуту `__honey` в первом фрагменте, мы должны были добавить `_Yo` спереди, что предотвратило бы конфликты с тем же атрибутом `name`, определенным в любом другом классе. +* Но почему тогда это не сработало во втором фрагменте? Потому что при манипулировании именами исключаются имена, заканчивающиеся двойным подчеркиванием. +* Третий фрагмент также является следствием манипулирования именами. Имя `__variable` в операторе `return __variable` было искажено до `_A__variable`, что также является именем переменной, которую мы объявили во внешней области видимости. +* Кроме того, если длина искаженного имени превышает 255 символов, произойдет усечение (truncation). + +--- +---