0
class hero():

    def __init__(self, name="Jimmy", prof="Warrior", weapon="Sword"):
        """Constructor for hero"""
        self.name = name
        self.prof = prof
        self.weapon = weapon
        self.herodict = {
            "Name": self.name,
            "Class": self.prof,
            "Weapon": self.weapon
        }
        self.herotext = {
            "Welcome": "Greetings, hero. What is thine name? ",
            "AskClass": "A fine name %s. What is thine class? " % self.herodict['Name'],
            "AskWeapon": "A %s ? What shalt thy weapon be? " % self.herodict['Class'],
        }

    def setHeroDict(self, textkey, herokey):
        n = raw_input(self.herotext[textkey])
        self.herodict[herokey] = n
        print self.herodict[herokey]



h = hero("Tommy", "Mage", "Staff")
h.setHeroDict("Welcome", "Name")
h.setHeroDict("AskClass", "Class")

Alright so, I asked this once before here and a smart fellow told me to try using lambdas. I tried it and it worked. Great! However my question here is a bit different. As I stated there, Im pretty new at this, and have a good deal of holes in my knowledge that im trying to fill. Basically.. how do I do this better without having to use lambdas (or do people usually use lambdas for this?)

What im trying to do:

  1. Have a hero class with some variables that have some defaults attached to them.
  2. I then want to use a definition that can go and use my herotext to use one of the values to ask a question.
  3. The user then answers the question, and that defenition goes and changes the appropriate value in herodict

Problem im trying to get passed: In my herotext I have a value that itself points to a key in herodict. As explained in the link, this I have learned is due to the herodict being initialized to the default values along with herotext before a user can provide input. So it prints out the default (Tommy in this case) name instead of the new user input name in the "AskClass" self.herodict['Name'] value.

How do I fix this? I dont mind if I have to make another file or whatever, I just want to know what is a more logical way of doing this sort of thing? Ive been stuck on this all day and my mind is friend. I know it may be simple to a lot of you and Im hoping you will share your knowledge.

Thanks

Community
  • 1
  • 1
Paul Duncan
  • 302
  • 1
  • 5
  • 19

2 Answers2

1

Here you go. This is a pretty clean method to do it. Shortly, I'll post my version of your class. :-) (well, I was going to, but this is already pretty prolix..)

class hero():
    def __init__(self, name="Jimmy", prof="Warrior", weapon="Sword"):
        """Constructor for hero"""
        self.name = name
        self.prof = prof
        self.weapon = weapon
        self.herodict = {
            "Name": self.name,
            "Class": self.prof,
            "Weapon": self.weapon
        }
        self.herotext = {
            "Welcome": "Greetings, hero. What is thine name? ",
            "AskClass": "A fine name {Name}. What is thine class? ",
            "AskWeapon": "A {Class}? What shalt thy weapon be? ",
        }

    def setHeroDict(self, textkey, herokey):
        n = raw_input(self.herotext[textkey].format(**self.herodict))
        self.herodict[herokey] = n
        print self.herodict[herokey]


h = hero("Tommy", "Mage", "Staff")
h.setHeroDict("Welcome", "Name")
h.setHeroDict("AskClass", "Class")

Explanation:

'format' is just a newer thing that does about what % does. The line above could have used the % method too. These two are equivalent:

"Hello, {foo}".format(**{'foo': 'bar'})
"Hello, %(foo)s!" % {'foo': 'bar'}

Either way, the idea is to avoid overwriting your template string. At the time you were creating your string templates, you were using them, then assigning the value to a variable.

Just as 5 * 10 always gets replaced with 50, 'meow%s' % 'meow!' is always replaced with "meow meow!". The five, ten, and both meows are automatically garbage collected, unless there's a reference to them elsewhere.

>>> print 5 * 10
50
>>> # the five, ten, and the 50 are now gone.
>>> template = "meow {}"
>>> template.format('splat!')
'meow splat!'
>>> # 'splat!' and 'meow splat!' are both gone, but your template still exists.
>>> template
'meow {}'
>>> template = template % 'hiss!'  # this evaluates to "template = 'meow hiss!'"
>>> template  # our template is now gone, replaced with 'meow hiss!' 
'meow hiss!'

..so, store your template in a variable, and and don't 'save over' them with the strings you create using them, unless you're done with the template and it makes sense to do so.

Mr. B
  • 2,536
  • 1
  • 26
  • 26
  • So this basically, in essence, reinitialized the dict entry and retrieves the most uptodate version? This looks very nice. Is this usually how people go about dict changes/retrial? By the way thank you for the effort in this answer. If I could upvote you more I would. ps, {foo} method instead of % is blow'n my mind. So much easier. – Paul Duncan Jun 02 '13 at 03:44
  • ..reinitialize probably isn't the right term, but yes. It's not the only way to go about retrieval of items from dicts, but some of that is different use cases, some of it is personal preference. I'll edit this to add my version of your class. – Mr. B Jun 03 '13 at 00:40
  • ..well, I got interrupted, so, nix that. Anyways, format takes keyword arguments, so the most basic version of that is `"{a}, {b}".format(a='1', bar='2')`. I can also make a dict, and use the `**some_dict` expansion magic to use that dict as the keyword arguments: `"{a}, {b}".format(**{'a': 1, 'b': 2, 'c': 3})`. Format ignores extra keyword arguments, so it's ok to include 'c' in there. Not all functions/methods ignore extras. Also, using a really big dict expands *all* of the options, so bear in mind a dict with 1000 keys expands to 1000 keyword arguments, which is pretty inefficient. – Mr. B Jun 03 '13 at 01:32
1

Do you need to use dictionaries? I think it could be more straightforward if you use simple class variables.

class Hero:
def __init__(self, name = "Jimmy", prof = "Warrior", weapon="Sword"):
    self.name = name
    self.prof = prof
    self.weapon = weapon

and then use a separate function to ask the user for info.

def create_hero():
    name = input("Greetings, hero. What is thine name? ")
    prof = input("A fine name %s. What is thine class?" % name)
    weapon = input("A %s ? What shalt thy weapon be?" % prof)
    return hero(name, prof, weapon)

run it with h = create_hero()

Dictionaries are typically used for data in the same style as associative lists (ie a set of pairs).

user2097752
  • 211
  • 2
  • 2
  • I think it makes sense to use a dictionary for user data. It's easily serializable, and that's nice when saving a game or some such. – Mr. B Jun 01 '13 at 03:20