Найти - Пользователи
Полная версия: Как python хранит экземпляры класса
Начало » Python для новичков » Как python хранит экземпляры класса
1
Alexey_mne31
Доброго времени суток.
Очередной глупый вопрос.
Как Python хранит объекты класса в списке?

Допустим есть список с кучей объектов разных классов:
 [<__main__.Healer object at 0x0000029CBBAFF7F0>, 
<__main__.Healer object at 0x0000029CBBAFF100>, 
<__main__.Healer object at 0x0000029CBBAFFC70>, 
<__main__.Lancer object at 0x0000029CBBB0B1F0>, 
<__main__.Lancer object at 0x0000029CBBB0B220>, 
<__main__.Lancer object at 0x0000029CBBB0B2B0>, 
<__main__.Warlord object at 0x0000029CBBAFFD90>]

Мне нужно:
 first_unit = row.pop(row.index(Healer)-1)

Вот тут проблема:
 row.index(Healer)

Мне нужен не строго определенный Healer object, хранящийся в ячейке памяти, а первый объект контейнера, относящийся к классу Healer

Подскажите, как бы вы это сделали?
PEHDOM
Alexey_mne31 а у вас не особо много то варантов, перебираете все элементы пока не натолкнетесь на первый “Healer”.
Дальше уже идут варианты реализации, можо просто фором пройтись по списку, можно через генератор списков, можно через filter..
Alexey_mne31
PEHDOM
е идут варианты реализации, можо просто фором пройтись по списку, можно чер
блин, я похоже как-то неправильно выражаюсь постоянно…
вот лично сам реализовал вчера через атрибут, общий для всего класса:
 def move_units(self):
        if not self.has(Warlord):
            return
        else:
            Healer.order = 1
            Lancer.order = 2
            Warrior.order = 3
            Warlord.order = 4
            if self.has(Healer):
                row = self.units
                row.sort(key = lambda x: x.order)
                row.reversе
                row2 = [k.name for k in row]
                row2.reverse
                first_unit = row.pop(row2.index('healer')-1)
                row.reverse
                row.insert(0, first_unit)
        return
То есть, индекс нужного мне объекта я ищу не в моем списке, а в сгенерированном списке:
 row2 = [k.name for k in row]
Но этот индекс использую в первом списке:
 first_unit = row.pop(row2.index('healer')-1)

Это работает, но это коряво.
Когда пытаюсь найти в контейнере индекс объекта Healer напрямую, интерпретатор начинает ругаться, насколько я понял, потому что 2 объекта Healer для него - разные объекты (они хранятся в разных ячейках памяти), а я задаю поиск по более общей характеристике - класс. Метод ‘index’ этого не понимает.


doza_and
Alexey_mne31
блин, я похоже как-то неправильно выражаюсь постоянно…
Тут проблема скорее в том что вы код пишете “не так”. Это называется рвать гланды через жопу.
Alexey_mne31
Подскажите, как бы вы это сделали?

РГЧЖ делали бы также.
Попробуйте сначала описать что вы делаете а потом уже описывать проблему.

В контейнерах питона хранятся ссылки на реальные объекты.

Поэтому обычные люди сделали бы исходно два списка если требуется специальная обработка

  
all_units=[]
moving_units=[]
...
my = SomeMoving()
all_units.append(my)
moving_units.append(my)
....
for u in moving_units:
     u.step()

А в играх обычно полагаются на полиморфизм, поскольку со всеми юнитами надо чтото делать.
 class UnitBase:
    ....
    def step(self):
        pass
class MovingUnit(UnitBase):
      .....
      def step(self):
          move()
          fight()
all_units=[]
....
for u in all_units:
     u.step()

Как вы можете легко заметить тут нигде нет работы с индексами pop и прочей РГЧЖ.
Это потому что проблему надо решать не в том месте где она вам мешает, а в том месте где вы ее создали неправильным выбором архитектуры приложения.

Rodegast
> Допустим есть список с кучей объектов разных классов:

Хранить разные типы в одном списке это очень хреновая идея. Разбей свой список на несколько или делай список кортежей.
AD0DE412
Rodegast
Хранить разные типы в одном списке это
потому что …
FishHook
AD0DE412
потому что …
Потомо что в питоне вы не можете статически (то есть на этапе компиляции) гарантировать что конкретный объект имеет конкретный метод. Это ведет к тому, что AtributeError вы получите только в рантайме. Если эта ошибка случается по условию, то вам следует очень ответственно подходить к покрытию вашего кода тестами. И вы скорее всего не покроете все кейсы, потому что здесь не обойтись юнит тестами.
AD0DE412
ok
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB