Как python разрешает закрытые (двойное подчеркивание) методы внутри класса? - PullRequest
0 голосов
/ 30 января 2019

Рассмотрим следующий класс

class Foo(object):

    @staticmethod
    def __is():
        print('__is')

    def m(self):
        Foo.__is()  # executes


Foo.__is()  # fails because of mangling

print(Foo.__dict__.keys())

Foo.__is(), когда он запускается после определения класса, происходит сбой из-за искажения имени.Как интерпретатор Python может разрешать Foo.__is() внутри методов, но не вне класса?

Ответы [ 2 ]

0 голосов
/ 30 января 2019

Перенос имен для имен, начинающихся с __ внутри класса, реализуется путем переписывания этих имен в искаженную форму, ТОЛЬКО внутри класса.Таким образом, ваш Foo.__is внутри класса заменяется на _Foo__is, который теперь присутствует в классе __dict__.Этот атрибут доступен как внутри, так и за пределами класса, поэтому нет частной защиты.Но после замены имя __is нигде не существует (я думаю), поэтому оно не работает извне.

Из справки Python:

"__ *"Классно-частные имена.Имена в этой категории, когда они используются в контексте определения класса, переписываются для использования искаженной формы, чтобы помочь избежать столкновения имен между «частными» атрибутами базового и производного классов.Смотрите раздел Идентификаторы (Имена).

Также смотрите мой комментарий к ошибкам в вашем фрагменте кода.

0 голосов
/ 30 января 2019

Вы можете думать о классах как о пространствах имен с некоторыми свистками.

Одним из свистков является способность разрешать __methods внутри себя без _class__method.Это ничем не отличается от «магии» автоматической передачи экземпляров в качестве первого аргумента в методы (ваш обычный self)

Чтобы проиллюстрировать идею «пространства имен», вы можете сделать некоторые странные вещи, такие как

class A:
    def insane():
        return 42

    for _ in range(5):
        print(insane()
...