Python creates multiple instances for a single object / class

I am using Python. I read a little about it and it seems like I can’t think it over. What I want to do is a class called Potions with various potion items. At the moment, there is one potion, a simple HealthPotion. I want potions to be stacked in stores and stores. Therefore, I need a copy of the amount of the potion for inventory and a copy for each store that has potions. The amount of potion would be dynamic for buying / selling and looting potions. If someone can give a basic explanation or examples that would be great.

Here is a snippet of what I have:

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) 

Ideally, the default value will be set to 0, and I can declare how much a particular store will start with their stock. Stocks and inventory are set up as an array, which is added and removed to / from. I think I have the logic for how this will work, I just have problems creating amounts.

EDIT: This is part of what I have in the buy method to see what happens without using instances. This is pretty ugly and I noticed that you.inventory.y.amt will not work. y - the selected item from the list of items displayed in the "store".

  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 <= you.coin: if y.amt == 0: you.inventory.append(y) you.inventory.y.amt += 1 else: you.inventory.y.amt += 1; you.coin -= y.val self.funds += y.val if self.stock.y.amt > 1: self.stock.y.amt -= 1 else: self.stock.y.amt -= 1 self.stock.pop(x) 

I looked at such examples:

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

I am wondering if I am only creating a second HealthPotion object, but that doesn’t sound like that. This example makes me think differently. Maybe I just don’t understand what is happening.

"This will create the first object of the Employee class"

 emp1 = Employee("Zara", 2000) 

"This will create a second object of the Employee class"

 emp2 = Employee("Manni", 5000) 

Thanks!

+4
source share
2 answers

I think you might have a somewhat misconception about how classes and instances work. It might make sense if you think about people.

Suppose we want to model people in our class hierarchy. At the moment, the person should have a name, and if you ask them to speak, they will pronounce their name:

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

Then the Person instance is, well, the person! For instance:

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

Thus, an instance is not a person who is truly a person.

Don't you have a class whose instances themselves are classes, I hear what you are asking? Yes, of course you can! He called the metaclass and is a very powerful tool in certain circumstances. However, not these.


Now, if you look at your situation, do you see the difference? A HealthPotion is not a special potion (let's say it's in my pocket) - it's a kind of potion. And the way we express this relationship is to inherit a class: define a new HealthPotion class that inherits from Potion . Then you can have copies of these (in my pocket, in the store, anywhere). If you want to use a potion, you are using a specific instance of the class.

+10
source

The code you have has very confusing naming conventions that seem confusing to me --- HealthPotion is not a class, it is an instance, but the name CamelCase assumes that it is a class in python.

To have multiple health potions using your potion class, simply do

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

Although this is a pretty bad style, you probably want to be able to easily create health and similar potions with the same properties and potions with different effects.

For this you must have

 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 

If you want to have multiple items in your inventory, it would be easier to just have a list (or set or some collection) for your inventory and have multiple instances in the list, for example.

 inventory = [HealthPotion(), HealthPotion()] 

If you want to perform stacking, I still think that this is an inventory function and not an element (outside the item.stackable member), so I will have an Inventory class that handles collections of an object, the contents of a face, chest or store. a simple implementation would be a wrapper around

 inventory = [(HealthPotion(), 2)] 

where any identical elements are represented as a pair of elements and a sum

It is also quite easy to convert the first to the last if you have a stacks_with method:

 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 
+2
source

Source: https://habr.com/ru/post/1398626/


All Articles