Присвоение значения внутреннего класса Python

#python #inner-classes

#python #внутренние классы

Вопрос:

Я создал внутренний класс внутри класса и создал два экземпляра класса, но при присвоении разных значений свойствам внутреннего класса оно присваивается обоим экземплярам. Кто-нибудь может помочь? Вот код

 class cl1:
    def __init__(self,tagName):
        self.name = tagName
    name1 = 'tagName'
    class cl2:
        name2 = 'name2'

test1 = cl1('test1')
test2 = cl1('test2')
test1.cl2.name2 = "cl1"
test2.cl2.name2 = 'cl2'
print (test1.cl2.name2)
 

При его запуске результат

 cl2
 

Почему это не «cl1», как назначено?

Комментарии:

1. Вы не создали никаких экземпляров cl1.cl2 . Вы просто присваиваете переменным класса. Как вы думаете, внутренние классы работают так же, как в Java? Они этого не делают. Они обычно не используются в Python.

Ответ №1:

Значение:

 test1.cl2.name2
 

Является атрибутом класса для класса cl2 . Оно связано с этим классом, а не с экземплярами этого класса. Таким образом, даже если вы просматриваете ссылки на экземпляр cl1 класса, чтобы установить значение этого атрибута, поскольку существует только один из них, выигрывает последнее, что вы устанавливаете для него. Ваши print операторы печатают одно и то же единственное значение.

Google «класс python против переменных экземпляра» для получения ряда хорошо выглядящих описаний различий между переменными / атрибутами класса и экземпляра.

Вот пример, который 1) Предоставляет атрибуты экземпляра и класса именно там, где, как вам кажется, вы их хотели, и 2) переименовывает задействованные классы, чтобы иметь имена в верхнем регистре, чтобы это было очевидно, когда вы ссылаетесь на атрибут экземпляра по сравнению с атрибутом класса.

 class Cl1:
    class Cl2:
        def __init__(self, tagName):
            self.name2 = tagName

    def __init__(self, tagName1, tagName2):
        self.name1 = tagName1
        self.cl2 = Cl1.Cl2(tagName2)

test1 = Cl1('test1', 'test2')
test2 = Cl1('test2', 'test2')
test1.cl2.name2 = 'cl1'
test2.cl2.name2 = 'cl2'
print(test1.cl2.name2)
 

Результат:

 cl1
 

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

Также обратите внимание на ссылки на self . Переменные экземпляра создаются внутри конструктора класса (его __init__ function ) путем ссылки на них self , ссылки на создаваемый экземпляр.

Комментарии:

1. Не могли бы вы посоветовать, как изменить код, чтобы cl2 мог быть частью свойств cl1, чтобы результатом распечатки был cl1?

2. Конечно. Я сразу скажу, что вы всегда должны называть классы прописными первыми буквами, а экземпляры и другие переменные — строчными. Это значительно упрощает понимание того, что происходит, и тогда вы обычно будете говорить о переменной класса, когда она имеет имя в верхнем регистре, и переменной экземпляра, когда она имеет имя в нижнем регистре.

3. Я надеюсь, что то, что я добавил к ответу, даст вам совет, о котором вы просите.

4. Спасибо. Это работает довольно хорошо. Ключ «self.cl2 = Cl1.Cl2 (tagName2)» для переноса внутреннего класса на внешний класс.

5. Cl1.Cl2 это просто полное имя внутреннего класса. Cl1.Cl2(tagName2) создает экземпляр этого класса. Ему присваивается значение self.cl2 , что означает, что каждый экземпляр Cl1 класса имеет переменную экземпляра с именем cl2 , которая ссылается на экземпляр Cl2 класса. Вот почему вы можете сделать test1.cl2.name2 , что <Cl1 instance><cl1 attribute pointing to a Cl2 instance><name2 attribute of Cl2 instance>