How does one return a random number from a dictionary every time a key is called?
<p>I am trying to create a weapon that provides random damage. I am doing so using an item database in the form</p>

<pre><code>itemsList = {
1: {"name": "Padded Armor",  "armor": 1,  "value": 5, "class": "Light"},
2: {"name": "Leather Armor",  "armor": 2,  "value": 10, "class": "Light"},
....
19: {"name": "Dagger", "damage" : int(random.randrange(1, 4)), "value": 2, "Type": "Dagger"},
20: {"name": "Dagger + 1", "damage" : int(random.randrange(1, 4) + 1), "value": 200, "Type": "Dagger"},
21: {"name": "Dagger + 2", "damage" : int(random.randrange(1, 4) + 2), "value": 750, "Type": "Dagger"},
22: {"name": "Dagger + 3", "damage" : int(random.randrange(1, 4) + 3), "value": 2000, "Type": "Dagger"}
}
</code></pre>

<p>Every time I attempt to call <code>"damage"</code> it just returns the same result. I understand that this is because the random number is generated one and then saved to that dictionary key. </p>

<p>How would I go about generating a random number every time damage is called?</p>

<p>I would go to the trouble of making the things in <code>itemsList</code> instances of a class. Although you might think that's overkill, doing it will give you a lot of programming flexibility later. It'll also make a lot of the code easier to write (and read) because you'll be able to refer to things using dot notation instead of via indexing which means you'll not only be able write to now use <code>itemsList[19].damage</code> instead of <code>itemsList[19]["damage"]</code>. You'll also use the same syntax for all other attributes such as <code>itemsList[1].name</code> and <code>itemsList[2].value</code>, as well as be able to write conditional code like this:</p>

<pre><code>if hasattr(itemsList[2], 'Class'):
    # do something based on itemsList[2].Class
</code></pre>

<p>Here's what I mean:</p>

<pre><code>import random

class Gear(object):
    def __init__(self, **kwargs):
        kwargs['_damage'] = kwargs.pop('damage', False)
        self.__dict__.update(kwargs)

    @property
    def damage(self):
        return int(random.randrange(*self._damage)) if self._damage else 0

itemsList = {
    1: Gear(name="Padded Armor", armor=1, value=5, Class="Light"),
    2: Gear(name="Leather Armor", armor=2, value=10, Class="Light"),
    # ...
    19: Gear(name="Dagger", damage=(1, 4), value=2, Type="Dagger"),
    20: Gear(name="Dagger + 1", damage=(1, 5), value=200, Type="Dagger"),
    21: Gear(name="Dagger + 2", damage=(1, 9), value=750, Type="Dagger"),
    22: Gear(name="Dagger + 3", damage=(2, 6), value=2000, Type="Dagger"),
}
</code></pre>

<p>To answer your follow-on questions in one comment below:</p>

<p><code>kwargs</code> is a dictionary of all the keyword arguments passed to the <code>__init__()</code> constructor method. (<code>__dict__</code> is the name of a dictionary where each instance stores its attributes.) See <a href="https://docs.python.org/2/faq/programming.html?#how-can-i-pass-optional-or-keyword-parameters-from-one-function-to-another" rel="nofollow">this section</a> in the documentation.</p>

<p><code>damage</code> is defined by the class using a <a href="https://docs.python.org/2/library/functions.html#property" rel="nofollow"><code>@property</code></a> decorator which is a simple way to actualy make it a "data descriptor". This sets things up so that whenever you reference a class instance's <code>damage</code> attribute, it will call a function to retrieve/determine its current "value". See the <a href="https://docs.python.org/2/howto/descriptor.html?highlight=property" rel="nofollow"><em>Descriptor HowTo Guide</em></a> for more information on Python descriptors.</p>

python dictionary random properties python-descriptors