Когда я пытаюсь append()
сам объект в список внутри объекта, это не работает, я не понимаю, почему.
class PLayer:
CLASS_NAME = "player"
TOTAL_PLAYER_NUMBER = 0
TOTAL_PLAYER_LIST = []
PLAYER_ID_INCREMENT = 0
def __init__(self, name,
first_name,
birthday,
note,
player_id=None,
total_score=None,
tournament_score=None):
self.PLAYER_ID_INCREMENT += 1
self.TOTAL_PLAYER_NUMBER += 1
self.name = name
self.first_name = first_name
self.birthday = birthday
self.player_id = self.PLAYER_ID_INCREMENT
self.total_score = 0
self.tournament_score = 0
self.note = note
self.TOTAL_PLAYER_LIST.append(self.Player)
Итак, у класса Player есть список TOTAL_PLAYER_LIST = []
, затем внутри __init__
я хочу добавить только что созданного игрока в список с последней строкой self.TOTAL_PLAYER_LIST.append(self.Player)
, но получаю эту ошибку
line 25, in __init__
self.TOTAL_PLAYER_LIST.append(self.Player)
AttributeError: 'PLayer' object has no attribute 'Player'
Я не понимаю, почему. Я пробовал ставить и удалять self.
, скобки также () для Player() .
Что ж, класс PLayer
действительно не имеет атрибута player...
.Player
Если вы это сделаете, это работает нормально. В вашем классе нет атрибута Player
. Игрок, которого вы хотите добавить, указан в переменной self
, экземпляре.
self.TOTAL_PLAYER_LIST.append(self)
Давайте рассмотрим более простой пример с отладкой:
class Player:
TOTAL_PLAYER_NUMBER = 0
TOTAL_PLAYER_LIST = []
PLAYER_ID_INCREMENT = 0
def __init__(self, name):
self.PLAYER_ID_INCREMENT += 1
self.TOTAL_PLAYER_NUMBER += 1
self.name = name
self.player_id = self.PLAYER_ID_INCREMENT
self.TOTAL_PLAYER_LIST.append(self)
def __repr__(self):
return f"{self.name}:<{self.player_id}>"
print(Player("Doe")) # Doe:<1>
print(Player.TOTAL_PLAYER_LIST) # [Doe:<1>]
Назовите свой класс Player
, а не PLayer
Атрибут класса против атрибута экземпляра
self.PLAYER_ID_INCREMENT += 1
Это не изменит атрибут класса PLAYER_ID_INCREMENT
, просто создайте атрибут экземпляра 1
:
doe = Player("Doe")
joe = Player("joe")
print(Player.TOTAL_PLAYER_NUMBER) # 0
print(doe.TOTAL_PLAYER_NUMBER) # 1
print(joe.TOTAL_PLAYER_NUMBER) # 1
Исправьте это с помощью:
def __init__(self, name):
Player.PLAYER_ID_INCREMENT += 1
Player.TOTAL_PLAYER_NUMBER += 1
...
doe = Player("Doe")
joe = Player("joe")
print(Player.TOTAL_PLAYER_NUMBER) # 2
print(doe.TOTAL_PLAYER_NUMBER) # 2
print(joe.TOTAL_PLAYER_NUMBER) # 2
Это происходит потому, что целые числа являются неизменяемыми, а += «перепривязывает» увеличенное значение к новой ссылке, расположенной... в self
, пространстве имен экземпляра, а не пространстве имен класса.
Более питонический способ сделать это с помощью метаклассов:
import typing
class CountInstances(type):
def __init__(cls, name, bases, dict_):
super().__init__(name, bases, dict_)
cls.count = 0
def __call__(cls, *args, **kwargs):
cls.count += 1
return super().__call__(*args, **kwargs)
class Player(metaclass=CountInstances):
total_player_list: typing.Final = []
def __init__(self, name):
self.name = name
self.player_id = self.count
self.total_player_list.append(self)
def __repr__(self):
return f"{self.name}:<{self.player_id}>"
doe = Player("Doe")
joe = Player("Joe")
print(Player.count) # 2
print(doe.count) # 2
print(joe.count) # 2
print(Player.total_player_list) # [Doe:<1>, Joe:<2>]
Подробнее о метаклассах: Что такое метаклассы в Python?
Player.TOTAL_PLAYER_LIST.append(себя)