1
0
mirror of https://github.com/satwikkansal/wtfpython synced 2024-12-22 12:50:23 +01:00

Translate Name mangling example

This commit is contained in:
Vadim Nifadev 2024-04-24 15:39:50 +03:00
parent 3b9d9bdcd1
commit b5c20d02ea

View File

@ -3222,3 +3222,80 @@ Ellipsis
- Интересно, что хэш `float('-inf')` - "-10⁵ x π" в Python 3, тогда как в Python 2 - "-10⁵ x e".
---
### ▶ Давайте искажать
<!-- Example ID: 37146d2d-9e67-43a9-8729-3c17934b910c --->
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 "<stdin>", line 1, in <module>
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 "<stdin>", line 1, in <module>
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).
---
---