Basi c путаница с классами и модулями (особенно с "self") - PullRequest
0 голосов
/ 27 мая 2020

Я думал, что этот код будет работать

class A:
    def __init__(self):
        self.x = 1
        B = self.create_b()
        print(B.y)

    def create_b(self):
        class B:
            def __init__(self):
                self.y = self.x
        return B
A = A()

, но получаю следующую ошибку:

AttributeError: type object 'B' has no attribute 'y'

Что я делаю не так?

Ответы [ 2 ]

1 голос
/ 27 мая 2020

Есть три проблемы с этим кодом. Во-первых, поскольку create-b возвращает объект класса, а не экземпляр класса, запрос B __init__ никогда не запускался. Вы можете решить эту проблему с помощью

class A:
    def __init__(self):
        self.x = 1
        B = self.create_b()
        b = B()
        print(b.y)

    def create_b(self):
        class B:
            def __init__(self):
                self.y = self.x
        return B
A = A()

Во-вторых, вложенные классы не имеют доступа к локальному пространству имен метода упаковки, как вложенная функция (закрытие). При попытке self.y = self.x экземпляры класса B не имеют особых отношений с экземпляром A, который их создал. Вы можете решить эту проблему с помощью

class A:
    def __init__(self):
        self.x = 1
        B = self.create_b(self)
        b = B()
        print(b.y)

    def create_b(self):
        class B:
            def __init__(self, a):
                self.y = a.x
        return B
A = A()

. В-третьих, python создает weakref классам, когда они определены, которые никогда не исчезают. Каждый раз, когда вы вызываете create_b, вы создаете небольшую утечку памяти. Вы можете решить это с помощью

class A:
    def __init__(self):
        self.x = 1
        b = B(self)
        print(b.y)

class B:
    def __init__(self, a):
        self.y = a.x
A = A()
1 голос
/ 27 мая 2020

Вы путаете классы с классами экземплярами (не Python модулями). В Python class операторы являются исполняемыми и создают вызываемый объект, который затем должен быть вызван для создания экземпляров объектов класса, который был определен.

Обычные методы класса автоматически получить первый аргумент, являющийся экземпляром, которому они принадлежат, и по соглашению этот аргумент обычно называется self.

Вот что я имею в виду:

class A:
    def __init__(self):
        self.x = 1
        B = self.create_b()  # Create B class.
        b = B(self)  # Create instance of B class passing this instance of A.
        print(b.y)

    def create_b(self):
        class B:
            def __init__(self, a_inst):
                self.y = a_inst.x
        return B

a = A()  # -> 1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...