Разное поведение для статических атрибутов класса
Почему по разному ведет себя статический атрибут класса в случаи с pandas? Возможно, что я заморачиваюсь конечно, но такое поведение не дает покоя.
class test:
table=[]
def __init__(self,count):
self.a=count
def changer(self):
self.a+=1
self.table=self.table.append(self.a)
class test2:
table=pd.DataFrame()
def __init__(self,count):
self.a=count
def changer(self):
self.a+=1
self.table=self.table.append({self.a:self.a},ignore_index=True)
for i in [1,2,3]:
i=test(i)
i.changer()
print(test.table)
for i in [5,6,7]:
i=test2(i)
i.changer()
print(test2.table)
в первом случаи статический атрибут список. и print(test.table)>>>[2,3,4] во втором случаи объект pandas, в который построчно добавляем строки, но результат пустой dataframe. Чем вызвано такое странное поведение и как лучше это обойти?
Ответы (1 шт):
Если вы добавите print(self.table) в оба метода changer, то вас будет ожидать некоторый сюрприз. Вдруг выяснится, что self.table после присвоения ей нового значения - это совсем отдельная сущность от class.table и у первого класса в self.table после присваивания будет вообще значение None.
Однако при этом self.table.append в случае списка пополняет class.table, что логично - ведь для списка .append работает in place и добавляет значения именно в тот список, на который указывает ссылка class.table, а вот с Pandas такой трюк не пройдёт, потому что там table.append не добавляет ничего в имеющуюся таблицу, а создаёт новую.
Но я могу вам подсказать вариант, который будет работать в случае с Pandas. Для этого надо поменять инициализацию класса test2 и метод changer:
class test2:
table=pd.DataFrame({0: [0]}) # делаем одну колонку с одним значением
def __init__(self,count):
self.a=count
def changer(self):
self.a+=1
self.table[self.a] = self.a # пишем новое значение в исходный DataFrame
Вывод:
[2, 3, 4]
0 6 7 8
0 0 6 7 8
Хотя вру, можно даже не менять инициализацию, а сделать такое присвоение в changer:
def changer(self):
self.a+=1
self.table.loc[0, self.a] = self.a
Но результат при этом будет float:
[2, 3, 4]
6 7 8
0 6.0 7.0 8.0