I'm designing the mechanics behind a RPG. There are classes for Item, Player, NPC, etc. The Player class has attributes inventory and equipment. Equipment is a list of dictionaries, such as:
player1.equipment = [{item_slot_a:item_a}, {item_slot_b:item_b}, ..., {item_x:item_x}]
Here, item_slot_a
refers to some arbitrary 'item' slot like helmet, boots, gloves, etc., and item_a
refers to an instance of the Item class, item1 or something similar. So, notice, the entire object is getting stored as the value of a key:value dictionary pair.
Is this OK?
Is it safe, efficient, and reliable to pass an entire object as a value? I didn't notice this was going to happen until I was testing the player.equip(thing)
function. I have a (hopefully) clever way of determining the appropriate equipment slot for equippable items, and then I... well... 'bind' the item to the item slot as a key:value pair. I printed out the inventory to test the equip() function, and saw this:
player1 = create_player('Bob', 'reaver', 1)
player1.show_equipment()
player1.equip(piece_of_gear)
player1.show_equipment()
Output: [{'helmet': None}, {'torso': None}, {'hand': <__main__.Gear object at 0x000001FF200BC0D0>}, {'legs': None}, {'foot': None}, {'neck': None}, {'ring': None}, {'ear': None}, {'charm': None}, {'mh_weapon': None}, {'oh_weapon': None}, {'twohand_weapon': None}]
If I'm correct, this is the print function returning an address in memory denoting the object. Does this represent any issues? I wouldn't normally see this if I were just using the object as a storage mechanism to retrieve relevant values (its intended use), and it's probably just a symptom of me not appropriately designing the show_equipment()
function.
Please advise on the structure and reliability of my code, as possible. Any input would be greatly appreciated.
For reference, my player.show_equipment
function looks like this:
print('Equipment:')
print(self.equipment)
return\`\`\`
Obviously, if I want to print what's accurately in the equipment list, I could retrieve the object in memory (which will be an instance of the Item class), and print item.name (which is just a string, I wrote it that way) instead of printing the entire item. I'm more curious about the safety and efficacy of creating a list of dictionaries containing objects.
CodePudding user response:
Is it safe, efficient, and reliable to pass an entire object as a value?
Yes! Everything in Python is an object.
If I'm correct, this is the print function returning an address in memory denoting the object. Does this represent any issues? ... is the print function returning an address in memory denoting the object. Does this represent any issues?
No issues here. It depends entirely on the __repr__
overrides of the class. If it doesn't have one, then the default implementation is to print out the id()
of the object and its class type. E.g.
>>> class Test: pass
>>> print(Test())
<__main__.Test object at 0x00000185FF1C5D30>
>>> class Test:
... def __repr__(self): return "Tada!"
>>> print(Test())
Tada!
Please advise on the structure and reliability of my code, as possible. Any input would be greatly appreciated.
Rather than using an untyped list of dicts as the way to store items, I would instead use a dataclass to represent items. These types classes are the ideal way to store pure data, and implement things like __repr__
, __init__
and other useful methods for you! For example:
from dataclasses import dataclass
from typing import Optional
@dataclass
class Gear:
name: str
attack_rating: int = 0
magic_rating: int = 0
defense_rating: int = 0
@dataclass
class Equipment:
helmet: Optional[Gear] = None
torso: Optional[Gear] = None
hand: Optional[Gear] = None
Using this class you can easily construct your players configuration!
>>> player_equipment = Equipment()
>>> player_equipment.helmet = Gear("Tiara", magic_rating=15)
>>> print(player_equipment)
Equipment(helmet=Gear(name='Tiara', attack_rating=0, magic_rating=15, defense_rating=0), torso=None, hand=None)