#python #static-variables
Вопрос:
Я пытаюсь использовать одну статическую переменную в качестве идентификатора для всех дочерних экземпляров этого родительского класса. Проблема, с которой я сталкиваюсь, заключается в двойном подсчете этого идентификатора, вероятно, потому, что родителю __init__
звонят дважды. Но если я удалю явный Parent().__init__()
вызов, то счетчик вообще не увеличится. Как я могу заставить идентификатор увеличивать только единицы? Вот мой фрагмент кода:
#!/usr/bin/python3
class Parent:
cls_id = 0
def __init__ (cls):
cls.cls_inc_id()
@classmethod
def cls_inc_id (cls):
cls.cls_id = 1
@classmethod
def child_inc_id (self):
self.id = 1
class Child1 (Parent):
def __init__ (self):
Parent().__init__()
self.id = super().cls_id
print ("Child1 id: ", self.id)
class Child2 (Parent):
def __init__ (self):
Parent().__init__()
self.id = super().cls_id
print ("Child2 id: ", self.id)
child1 = Child1()
child2 = Child1()
child3 = Child2()
child4 = Child2()
Мой вывод таков:
%> ./static_vars.py
Child1 id: 2
Child1 id: 4
Child2 id: 6
Child2 id: 8
Заранее спасибо
Комментарии:
1. Извините, чего именно вы пытаетесь достичь? Какой результат вы ожидаете ?
2. В качестве отступления, не используйте
cls
в качестве имени первого аргумента to__init__
. Условно, так и должно быть__init__ (self)
, поскольку это метод экземпляра
Ответ №1:
Он увеличивается в два раза из-за Parent().__init()
. Это создает совершенно новый объект, инициализирует его, а затем отбрасывает. Вы должны использовать super().__init__()
, и в вашем __init__ method refer to
родительском файле.cls_inc_id`. Тогда это сработает.
И, кстати, в Parent.__init__
вы называете параметр «cls», но на самом деле это «я» — это метод объекта, а не метод класса.
Новый код:
#!/usr/bin/python3
class Parent:
cls_id = 0
def __init__ (self):
print("Parent.__init__")
Parent.cls_inc_id()
@classmethod
def cls_inc_id (cls):
print("Parent.cls_inc_id")
cls.cls_id = 1
@classmethod
def child_inc_id (cls):
print("child_inc_id")
cls.id = 1
class Child1 (Parent):
def __init__ (self):
print("Child1.__init__")
super().__init__()
self.id = super().cls_id
print ("Child1 id: ", self.id)
class Child2 (Parent):
def __init__ (self):
print("Child2.__init__")
super().__init__()
self.id = super().cls_id
print ("Child2 id: ", self.id)
child1 = Child1()
child2 = Child1()
child3 = Child2()
child4 = Child2()
Выход:
Child1.__init__
Parent.__init__
Parent.cls_inc_id
1
Child1 id: 1
Child1.__init__
Parent.__init__
Parent.cls_inc_id
1
Child1 id: 2
Child2.__init__
Parent.__init__
Parent.cls_inc_id
1
Child2 id: 3
Child2.__init__
Parent.__init__
Parent.cls_inc_id
1
Child2 id: 4
Комментарии:
1. Также
cls.cls_inc_id()
должно бытьParent.cls_inc_id()
. В противном случае он создает атрибут экземпляра вместо обновления атрибута класса.2. Ха! Очень зоркий глаз!
3. @Barbar нет, это не так, потому
cls_inc_id
чтоclassmethod
4. Да, это так, потому что он ВЫЗЫВАЕТ его как объектный метод. Попробовать это.
5. Я не совсем понимаю, что ты имеешь в виду. Он всегда будет получать объект класса в качестве первого параметра. Неважно, как вы его назовете, он не создаст атрибут экземпляра. Однако он создаст отдельные переменные класса в зависимости от того, как вы его называете. т. Е. Если вы используете
self.cls_inc_id()
,Parent.cls_inc_id
метод передаетсяChild1
либоChild2
в зависимости от типаself
Ответ №2:
Как уже упоминали другие, вы неправильно используете super
конструктор, но я бы также ссылался на фактический класс в родительском классе, а не на экземпляр self
, который вы неправильно назвали cls
:
class Parent:
cls_id = 0
def __init__(self):
self.id = Parent.cls_id
Parent.cls_id = 1
class Child1(Parent):
def __init__(self):
super().__init__()
print ("Child1 id: ", self.id)
class Child2(Parent):
def __init__(self):
super().__init__()
print ("Child2 id: ", self.id)
child1 = Child1()
child2 = Child1()
child3 = Child2()
child4 = Child2()
Child1 id: 0
Child1 id: 1
Child2 id: 2
Child2 id: 3
Если вам нужен отдельный идентификатор для каждого типа класса, вы можете использовать класс сопоставления словаря с идентификатором:
from collections import defaultdict
class Parent:
cls_ids = defaultdict(int)
def __init__(self):
self.id = Parent.cls_ids[type(self)]
Parent.cls_ids[type(self)] = 1
Child1 id: 0
Child1 id: 1
Child2 id: 0
Child2 id: 1
Комментарии:
1. Спасибо за совет по использованию пакета коллекций. Я попробую это сделать.