#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>