Python Count function not work on instances of a class?
Question:
So Ive been trying to make a method which checks if an entered Item is present in the players inventory. For that I used the count to check if the item exists atleast once. However it seems like that it does not instances of the class. (All the items in the inventory of the player are instance of a classs)
inventory = []
def equipItem(self):
equipinput = input("Chosse Item to equip: ")
#Get Input which item to equip
itemcount = self.inventory.count(equipinput)
#Count how many times the item was found
if itemcount >= 1:
itemindex = self.inventory.index(equipinput)
if self.inventory[itemindex].typeitem == "weapontype":
#Check the item type(is an attribute of the item/Class)
self.inventory[0], self.inventory[itemindex] = self.inventory[itemindex], self.inventory[0]
#Switch position of the item to equip and that of the current item (It is always on the first position)
print("Changed Weapon to " + str(equipinput))
game()
#Go back to the game
else:
self.inventory[1], self.inventory[itemindex] = self.inventory[itemindex], self.inventory[1]
print("Changed Armor to " + str(equipinput))
game()
else:
print(f"{Fore.RED}You do not have this item!{Style.RESET_ALL}")
#Output an error Message in red
game()
Example inventory:
self.inventory = [Wooden Dagger, Steel Sword]
Example input would be then: Steel Sword
Expected Output/inventory:
self.inventory = [Steel Sword, Wooden Dagger]
Answers:
You cannot count instances of a class this way. If you look at the representation of it by printing it, you will see something like <__main__.SteelSword object at 0x7f15e6f97430>
. They are obviously different, but are instances of the same class. So you can do:
[isinstance(ins, SteelSword) for ins in self.inventory].count(True)
Now, if you use input()
, you will always get a string back, which is different from a class reference: 'SteelSword' != <class '__main__.SteelSword'>
So you need a way to address this issue. What you could do, for example, is to create a dict
that takes your class names as a string ('SteelSword'
) key and the class references as the corresponding values.
You are comparing apples to oranges. The returned value of input is type string and the inventory array contains instances of some class (which you have omitted but i will call the "equipment" class).
You could create a __str__(self):
method for the omitted "equipment" class like so.
class Equipment:
def __init__(self, name: str):
self.name = name
def __str__(self):
return self.name
You could then use list comprehension to create an array of string representations of the inventory and compare the input to that.
inventory = [Equipment('steel sword'), Equipment('basic axe')]
def equip_item(self):
string_inventory = [str(item) for item in self.inventory] # creates array ['steel sword', 'basic axe']
print(string_inventory.count('basic axe')) # now we can compare strings to strings with the count method
I would also recommend looking into the __repr__(self):
magic method.
lastly, if comparing string, I also recommend using the .upper() method so capitalization does not cause problems.
So Ive been trying to make a method which checks if an entered Item is present in the players inventory. For that I used the count to check if the item exists atleast once. However it seems like that it does not instances of the class. (All the items in the inventory of the player are instance of a classs)
inventory = []
def equipItem(self):
equipinput = input("Chosse Item to equip: ")
#Get Input which item to equip
itemcount = self.inventory.count(equipinput)
#Count how many times the item was found
if itemcount >= 1:
itemindex = self.inventory.index(equipinput)
if self.inventory[itemindex].typeitem == "weapontype":
#Check the item type(is an attribute of the item/Class)
self.inventory[0], self.inventory[itemindex] = self.inventory[itemindex], self.inventory[0]
#Switch position of the item to equip and that of the current item (It is always on the first position)
print("Changed Weapon to " + str(equipinput))
game()
#Go back to the game
else:
self.inventory[1], self.inventory[itemindex] = self.inventory[itemindex], self.inventory[1]
print("Changed Armor to " + str(equipinput))
game()
else:
print(f"{Fore.RED}You do not have this item!{Style.RESET_ALL}")
#Output an error Message in red
game()
Example inventory:
self.inventory = [Wooden Dagger, Steel Sword]
Example input would be then: Steel Sword
Expected Output/inventory:
self.inventory = [Steel Sword, Wooden Dagger]
You cannot count instances of a class this way. If you look at the representation of it by printing it, you will see something like <__main__.SteelSword object at 0x7f15e6f97430>
. They are obviously different, but are instances of the same class. So you can do:
[isinstance(ins, SteelSword) for ins in self.inventory].count(True)
Now, if you use input()
, you will always get a string back, which is different from a class reference: 'SteelSword' != <class '__main__.SteelSword'>
So you need a way to address this issue. What you could do, for example, is to create a dict
that takes your class names as a string ('SteelSword'
) key and the class references as the corresponding values.
You are comparing apples to oranges. The returned value of input is type string and the inventory array contains instances of some class (which you have omitted but i will call the "equipment" class).
You could create a __str__(self):
method for the omitted "equipment" class like so.
class Equipment:
def __init__(self, name: str):
self.name = name
def __str__(self):
return self.name
You could then use list comprehension to create an array of string representations of the inventory and compare the input to that.
inventory = [Equipment('steel sword'), Equipment('basic axe')]
def equip_item(self):
string_inventory = [str(item) for item in self.inventory] # creates array ['steel sword', 'basic axe']
print(string_inventory.count('basic axe')) # now we can compare strings to strings with the count method
I would also recommend looking into the __repr__(self):
magic method.
lastly, if comparing string, I also recommend using the .upper() method so capitalization does not cause problems.