Как получить доступ к внешнему члену класса из внутреннего класса в Python? - PullRequest
0 голосов
/ 09 декабря 2018

Как получить доступ к внешнему члену класса из внутреннего класса в Python 3?

Ниже приведен мой фрагмент кода.

class Outer:    
    def __init__(self):
        self.__x = 20
        self.__str = "Outer Class"

    def show(self):
        self.i1 = self.Inner(Outer())
        self.i1.display()

    def fn(self):
        print("Hello from fn() of Outer Class")
        print("str : ", self.__str)

    class Inner:
        def __init__(self, outer):
            self.__str_in = "Inner Class"
            self.outer = outer

        def display(self):
            print("str_in : ", self.__str_in)
            print("Inside display() of Inner Class")
            # print("x : ", self.outer.__x)
            # print("str : ", self.outer.__str)
            # self.outer.fn()


obj = Outer()
obj.show()

Если я выполняю закомментированные строки, выдается ошибкаговоря -

line 23, in display
    print("x : ", self.outer.__x)
AttributeError: type object 'Outer' has no attribute '_Inner__x'

Кто-нибудь может помочь?Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 09 декабря 2018

Проблема с вашим кодом заключается в том, что вы неправильно поняли значение name mangling, это именно то, что вы делаете, добавляя двойной начальный балл в имя переменной.

При настройкепеременная как self.__x, то, что вы на самом деле делаете, говорит миру за пределами вашего класса, что доступ к нему возможен только при работе внутри класса Outer.Если вы попытаетесь получить доступ извне, скажем, добавьте после определения obj следующего print(obj.__x), вы увидите ту же проблему.

Манглинг имен означает, что при доступе к переменной вне области вашего класса вы должны вызывать переменную _ClassName__variableName, поэтому в нашем примере вы должны использовать print(obj._Outer__x), чтобы иметь возможность print переменная.

Поскольку ваш класс Inner работает так же, как и внешняя область, простейшим решением было бы переписать ваш метод display следующим образом:

def display(self):
    print("str_in : ", self.__str_in)
    print("Inside display() of Inner Class")
    print("x : ", self.outer._Outer__x)
    print("str : ", self.outer._Outer__str)
    self.outer.fn()

Теперь другая вещьЯ заметил, и может вызвать проблемы, если вы не сделали этого сознательно, это вызов self.i1 = self.Inner(Outer()).Здесь вы не используете те же данные объекта, которые вы создали, как obj, но создаете новый экземпляр Outer и отправляете его на Inner.
И в чем проблема с этим? Допустим, вы добавили следующие строки:

obj = Outer()
obj._Outer__x = 10
obj.show()

Тогда результат вашего show() всегда будет x: 20, потому что это изменение вы сделали в переменной,был создан для экземпляра, который не был передан Inner.

Если это не то поведение, к которому вы стремились, просто измените эту строку на:

self.i1 = self.Inner(self)

Так что теперь выэффективно передать экземпляр объекта Inner

0 голосов
/ 09 декабря 2018

Проблема в том, что вы передаете класс вместо экземпляр в self.i1 = self.Inner(Outer), а self.__str является атрибутом instance .

Есть и другая проблема.Вы используете префикс __, который подвергается искажению имени , поэтому постарайтесь избежать этого.

У вас есть два способа исправить это:

  • Passнапример, self.i1 = self.Inner(self)

или

  • Сделать _str атрибутом класса:

    class Outer:
        _str = "Outer Class"  # NOTE THE SINGLE _
    
        def __init__(self):
            self._x = 20 # NOTE THE SINGLE _
    
        ...           
    
...