Tengo una lista de objetos a nivel de clase y un método de clase fight que opera con los objetos de esa lista:

from Heroes import Hero
from Creatures import Creature
from random import randint

class Battle():
    """template to simulate the battle"""


    obj_list = []

    def __init__(self,obj1_name,obj2_name):

        #create  hero
        self.obj1 = Hero(obj1_name, health = randint(70,100), strength = randint(70,80), defence = randint(45,55), speed = randint(40,50), luck = randint(10,30))
        Battle.obj_list.append(self.obj1)



        #create  creature
        self.obj2 = Creature(obj2_name, health = randint(70,100), strength = randint(70,80), defence = randint(45,55), speed = randint(40,50), luck = randint(10,30))
        Battle.obj_list.append(self.obj2)

    @classmethod
    def fight(cls):
        """simulate fight"""

        # first attack is landed by the obj with highest speed
        if cls.obj_list[0].speed > cls.obj_list[1].speed:

           cls.obj_list[1].health =  cls.obj_list[0].attack() - cls.obj_list[1].defence

        # same speed first attack landed by the obj with highest luck
        elif cls.obj_list[0].speed == cls.obj_list[1].speed:

            if cls.obj_list[0].luck >= cls.obj_list[1].luck:
                cls.obj_list[1].health =  cls.obj_list[0].attack() - cls.obj_list[1].defence
            else:
                cls.obj_list[0].health =  cls.obj_list[1].attack() - cls.obj_list[0].defence

        #self.obj1.speed < self.obj2.speed
        else:
                cls.obj_list[0].health =  cls.obj_list[1].attack() - cls.obj_list[0].defence

        return cls.obj_list

if __name__ == "__main__":

    first_round =  Battle("Icarus","Beast")


    for i in Battle.obj_list:
            print(i.name,i.health)

    Battle.fight()


    for i in Battle.obj_list:
            print(i.name,i.health)

    Battle.fight()

    for i in Battle.obj_list:
            print(i.name,i.health)

Salida:

Icarus 90
Beast 74
Icarus 30
Beast 74
Icarus 30
Beast 74

La primera llamada del método fight actualiza correctamente el atributo health de los objetos de obj_list pero luego, no importa cuántas veces llame al método, el atributo health no está actualizado nunca más. ¿Qué me estoy perdiendo? ¿Debería usar otro enfoque para compartir el estado de los objetos?

2
dejdej 20 oct. 2019 a las 16:39

1 respuesta

La mejor respuesta

Usar un atributo de clase como almacenamiento para héroe y criatura es innecesario y hace que el código sea ilegible.

Con tu enfoque, después de tres peleas, Battle.obj_list se verá así:

[Héroe (primera pelea), Criatura (primera pelea), Héroe (segunda pelea), Criatura (segunda pelea), Héroe (tercera pelea), Criatura (tercera pelea)].

En su código siempre accede a [0] y [1].

Lo siguiente es que creas héroe y criatura en una batalla. Puedes imaginarte como en la 'realidad': el héroe y la criatura existen antes de la batalla y cuando comienza la batalla (se crea la instancia de batalla), entra en la batalla.

class Battle():
    """template to simulate the battle"""
    def __init__(self, hero, creature):

        #create  hero
        self.hero = hero

        #create  creature
        self.creature = creature

    def fight(self):
        """simulate fight"""

        # first attack is landed by the obj with highest speed
        if self.hero.speed > self.creature.speed:
           self.creature.health =  self.hero.attack() - self.creature.defence

        # same speed first attack landed by the obj with highest luck
        elif self.hero.speed == self.creature.speed:
            if self.hero.luck >= self.creature.luck:
                self.creature.health =  self.hero.attack() - self.creature.defence
            else:
                self.hero.health =  self.creature.attack() - self.hero.defence

        #self.obj1.speed < self.obj2.speed
        else:
            self.hero.health =  self.creature.attack() - self.hero.defence
        return [self.hero, self.creature]


if __name__ == "__main__":
    hero = Hero(
        obj1_name, health = randint(70,100),
        strength = randint(70,80),
        defence = randint(45,55),
        speed = randint(40,50),
        luck = randint(10,30)
        )

    creature = Creature(
        obj2_name,
        health = randint(70,100),
        strength = randint(70,80),
        defence = randint(45,55),
        speed = randint(40,50),
        luck = randint(10,30)
        )

    first_round =  Battle(hero, creature)

Sería bueno si publicaras la clase Criatura y Héroe

0
Frank 20 oct. 2019 a las 16:38