Python creando múltiples instancias para un solo objeto / clase

Estoy usando Python. He leído un poco sobre esto y parece que no puedo envolver mi mente alrededor de esto. Lo que quiero hacer es tener una clase llamada Pociones con varios objetos de poción en ella. Por ahora hay una poción, un simple HealthPotion. Quiero que las pociones sean astackbles en los inventarios y las existencias de la tienda. Así que necesito una instancia de la cantidad de poción para un inventario y una instancia para cada inventario de la tienda que contiene pociones. La cantidad de pociones sería dinámica, para la compra / venta y el saqueo de pociones. Si alguien pudiera proporcionar una explicación básica o ejemplos que serían geniales.

Aquí hay un fragmento de lo que tengo:

class Potion(Item): def __init__(self, name, desc, val, amt, type, effect, bound): Item.__init__(self, name, desc, val, amt, type, effect, bound) self.name = name self.desc = desc self.val = val self.amt = amt self.type = 0 #Restorative self.effect = effect def use(self, you): #Use health potion you.hp_current += self.effect you.displayStats() #Format: Name, Description, Value, Amount, Type, Effect, Bound HealthPotion = Potion('Health Potion', 'Restores 10 hit points when consumed', 10, 0, 0, 10, 0) 

Idealmente, la cantidad predeterminada se establecería en 0 y podría declarar cuánto comenzaría una determinada tienda en sus existencias. El inventario y el stock de la tienda se configuran como una matriz a la que se agregan y eliminan los elementos. Creo que tengo la lógica de cómo funcionaría esto, simplemente estoy teniendo problemas para establecer las cantidades.

EDITAR: Esto es parte de lo que tengo en un método de compra para ver qué pasaría sin usar instancias. Es bastante feo y discerní que you.inventory.y.amt no funcionará. y siendo el elemento seleccionado de la lista de elementos que se muestra en una “tienda”.

  x = selection - 1 #Item menu starts at 1. But arrays start at 0. So it takes user input and subtracts 1 to match the array. y = self.stock[x] if y.val  1: self.stock.y.amt -= 1 else: self.stock.y.amt -= 1 self.stock.pop(x) 

He visto ejemplos como este:

 class foo: a = 1 i = foo() foo.a => 1 ia => 1 ia = "inst" foo.a => 1 ia => "inst" 

Me pregunto si no solo creo un segundo objeto HealthPotion, pero eso no me suena bien. Este ejemplo me lleva a pensar lo contrario. Tal vez simplemente no entiendo la creación de instancias.

“Esto crearía el primer objeto de la clase Employee”

 emp1 = Employee("Zara", 2000) 

“Esto crearía un segundo objeto de la clase Empleado”

 emp2 = Employee("Manni", 5000) 

¡Gracias!

Creo que puedes tener un concepto ligeramente equivocado de cómo funcionan las clases y las instancias. Podría tener más sentido si piensas en las personas.

Supongamos que queremos modelar personas en nuestra jerarquía de clases. Por ahora, una persona tiene que tener un nombre, y si le pide que hable, dicen su nombre:

 class Person(object): def __init__(self, name): self.name = name def speak(self): print "Hi! My name is {self.name}.".format(self=self) 

¡Entonces una instancia de Person es, bueno, una persona! Por ejemplo:

 >>> basil = Person("Basil") >>> polly = Person("Polly") >>> >>> basil.speak() Hi! My name is Basil. >>> polly.speak() Hi! My name is Polly. >>> basil == polly False 

Entonces, una instancia no es un tipo de persona, realmente es solo una persona.

¿No puedes tener una clase cuyas instancias son en sí mismas clases, te oigo preguntar? ¡Sí por supuesto que puedes! Se llama metaclase y es una herramienta muy poderosa en ciertas circunstancias. No, sin embargo, estos.


Ahora, si miras tu situación, ¿ves la diferencia? Un HealthPotion no es una poción en particular (por ejemplo, esta en mi bolsillo), es un tipo de poción. Y la forma en que expresamos esa relación es por herencia de clase: define una nueva clase HealthPotion que hereda de Potion . Entonces puedes tener instancias de estos (en mi bolsillo, en una tienda, donde sea). Si desea usar una poción, use una específica, es decir, una instancia de la clase.

El código que tiene allí utiliza convenciones de denominación muy confusas, que creo que le están causando confusión — HealthPotion no es una clase, es una instancia, pero el nombre de CamelCase sugiere que es una clase en python.

Para tener múltiples pociones de salud usando tu clase de pociones, simplemente haz

 health_potion_1 = Potion("Health Potion", ...) health_potion_2 = Potion("Health Potion", ...) foobar_potion_1 = Potion("Foobar Potion", ...) #... 

Aunque este es un estilo bastante pobre, lo que probablemente quieras es tener una forma de crear fácilmente pociones saludables y similares, con las mismas propiedades y pociones con diferentes efectos.

Para ello debes tener

 class HealthPotion(Potion): def __init__(self, name="Health Potion", effect=10): super(HealthPotion, self).__init__(name, "Restores %d points of health" % (effect, ), effect, 0, 0) def use(self, you): you.hp_current+=self.effect 

Si desea tener varios elementos en un inventario, sería más simple tener simplemente una lista (o conjunto o alguna colección) para su inventario y tener varias instancias en la lista, por ejemplo

 inventory = [HealthPotion(), HealthPotion()] 

Si desea hacer el astackmiento, todavía creo que es una función del inventario, no del artículo (más allá de un elemento item.stackable ), así que tendría una clase de Inventory que maneja colecciones de objetos, ya sea el contenido de una persona, Un cofre o una tienda. una implementación simple sería una envoltura alrededor

 inventory = [(HealthPotion(), 2)] 

donde cualquier artículo idéntico se represente como un par del artículo y la cantidad

Alternativamente, es bastante fácil transformar el primero en el segundo si tiene un método stacks_with :

 def stack_size(item, inv): "The number of items that will stack with item in inv" return len([i for i in inv if item.stacks_with(i)]) def stacked_inventory(inv): # if there is no stackable pair in the first i items # (ie the stack size for that item is 0 in inv[0:i]), # then the 'i'th item is a new stack, # with stack_size(inv[i], inv) items in it stacks = [ (inv[i], stack_size(inv[i])) for i in range(0,len(inv)) if not stack_size(inv[i], inv[0:i])] return stacks