Добавление экземпляров класса к списку отменяет атрибуты предыдущего экземпляра - PullRequest
0 голосов
/ 09 мая 2020

Итак, я пытаюсь создать список объектов класса, используя вложенные циклы while. У меня есть два типа классов: normal_class и special_class.

Для special_class я даю ему координаты x, y, выполняя special_class.set (x, y). Для обычного класса я просто оставляю его как есть.

Если я добавлю еще один special_class, выполнив special_class.set (x, y), а затем ls.append (special_class), он переопределит координаты первого , поэтому я получаю два special_class с одинаковыми координатами вместо двух special_class с отдельными координатами.

Я только недавно начал программировать на Python, поэтому любая помощь будет полезна :)

Это некий псевдокод:

  1. Ввод - строка символов ie. «XXY»
  2. Я сравниваю каждый из этих символов со словарем, который я создал ie. dict = {"X": special_class (), "Y": normal_class}
  3. Я хочу установить координаты special_class, normal_class не имеет атрибутов координат
  4. Если character_from_string == key из словаря проверьте, является ли это специальным или обычным классом. Затем используйте пару значений
  5. Если это специальный класс, set_pos (x, y) для некоторых чисел x, y. Если это нормально, передайте
  6. Добавить экземпляр класса в список
  7. Так что я надеюсь получить такой результат, как [объект special_class, объект special_class, объект normal_class]
  8. Если я сделаю ls [0] .get_pos и ls [1] .get_pos, он вернет то же значение, даже если я установил для него разные x, y. Зачем? И как я могу это исправить?

Код!


class special_class:
    def __init__(self):
        self.char = "X"
    def set_pos(self, x, y):
        self.x = x
        self.y = y
    def get_pos(self):
        return (self.x, self.y)


class normal_class:
    def __init__(self):
        self.char = "Y"

class also_special_class:
    def __init__(self):
        self.char = "Z"
    def set_pos(self, x, y):
        self.x = x
        self.y = y
    def get_pos(self):
        return (self.x, self.y)



string = "XYXZ"
dict = {"X": special_class(), "Y": normal_class(), "Z": also_special_class()}
ls = []

i = 0
while i < len(string):
    k = 0
    keys = list(dict.keys())
    while k < len(keys):
        if string[i] == keys[k]:
            instance = dict[keys[k]]
            if keys[k] == "X" or keys[k] =="Z": # i and k numbers that change
                special_class = instance.set_pos(i, k) # why is special_class None?
                ### this code is ugly but it's the only way I know of doing it without errors
                ### however, the position of the two elements is not what I put into it initially

                special_instance = dict[keys[k]]
                special_instance.set_pos(i,k)
                print(special_instance.get_pos())
                instance = special_instance
            ls.append(instance)
        k += 1

    i += 1

print()
print(ls)
print("\nPosition after finished loop")
print(ls[0].get_pos())
print(ls[2].get_pos())


Если бы вы могли дать мне указатели на а) почему этот прокомментированный фрагмент special_class возвращает None b) Указатели что касается улучшения моего кода, особенно этой части

special_instance = dict[keys[k]]
                special_instance.set_pos(i,k)
                print(special_instance.get_pos())
                instance = special_instance

c) Объяснение, почему я получаю те же значения для get_pos и как я могу исправить свой код, чтобы он работал так, как задумано, будь потрясающим !!

1 Ответ

0 голосов
/ 09 мая 2020

Вам нужно использовать copy.deepcopy(), чтобы сделать неполную копию объекта класса. Это добавит объект класса (kls), а не ссылку на него.

В частности, в вашем случае это должно решить проблему.

from copy import deepcopy
ls.append(deepcopy(special_class))

Пример

from copy import deepcopy

klasses = []

for _ in range(5):
    #initialize the class object
    kls = YourClass() 
    klasses.append(deepcopy(kls))

Некоторые предложения для определений ваших классов:

  1. Имена классов должны быть CamelCased. См. python соглашение об именах классов / переменных / функций / методов PEP-8 для более подробной информации.

    # example
    class SpecialClass(object):
        def __init__(self):
            ...
    
        def some_method(self):
            ...
    
  2. Создайте экземпляр класса как минимум с круглыми скобками; и, если необходимо, с аргументами, как того требует метод __init__(). Например, kls = SpecialClass создает только псевдоним класса SpecialClass по имени kls и не создает экземпляр SpecialClass. Чтобы создать экземпляр, используйте вместо этого: SpecialClass().

    # example
    kls = SpecialClass()    
    
...