tags:

views:

111

answers:

2

The following code:

class Log:

    BAT_STATS = ['AB', 'R', 'H', 'HR']

    def __init__(self, type):
  for cat in Log.BAT_STATS:
         self.cat = 0

I want the loop there to create a class property of each key in BAT_STATS, so I can go:

log = Log()
print log.HR;

Similar to PHP with $this->$$foo = 'bar' where $foo would be 'HR'.

+5  A: 

Maybe this?

class Log:
    BAT_STATS = ['AB', 'R', 'H', 'HR']

    def __init__(self, type):
        for cat in Log.BAT_STATS:
            setattr(self, cat, 0)

EDIT - Oops, indentation was a bit messed up.

@EOL: Are you suggesting putting it straight into the class definition? While for some applications it might be nice just to set these values once for the class rather than per-instance, I'm not sure how you'd do that. Inside the class definition you don't have a "self" or "klass" variable to call setattr on. At the end of the class definition Python parcels up the locals dictionary to use as the class's member dictionary. You can read this dictionary directly with locals(), but I don't think you have any guarantee that you can write back to it. I would guess that the easiest way to get the effect is to modify the class dictionary after it has been created, but that could be quite confusing because then the class's behaviour is no longer clear just from looking at its definition. It's not necessarily a bad idea, but I wouldn't like to recommend it without having a better understanding of the scenario it's going to be used in.

Weeble
setattr is indeed a good way to do it. However, why the __init__()? why not put the loop directly in the main code?
EOL
A: 

Explicit recommendation: DO NOT USE the following.
and please ease-up on the downvotes...

Edit: I even found a quote from Alex Martelli expressing how bad an idea my snippet is.
(Short excerpt from Python in a Nutshell, 2nd ed. O'Reilly 2006)
Use exec only when it is really indispensable. MOst often, it's best to avoid exec choose more specific, well-well controlled mechanisms instead: exec pries loose your control on your code's namespace, damages performance and exposes you to numerours, hard-to-find bugs.

Therefore here is my not so pythonic moment:

class Log:
   BAT_STATS = ['AB', 'R', 'H', 'HR']
   def __init__(self):
      for cat in Log.BAT_STATS:
           exec('self.' + cat + ' = 0')

Using setattr() is of course cleaner (I recommend it in this simple case), but it's nice to remember the power of exec... A bit like being reminded of a dangerous tool we have in the shed.

mjv
"it's nice to remember the power of exec...", - oh no, it is not :P This is one of those things, that are better off forgotten until that one chance in a lifetime when they are actually useful. (I didn't -1 you)
shylent
OK, I won't downvote, but the downvote does mean "this is not useful". And this isn't. Sorry.
Lennart Regebro
@Lennart, thks for your kind forgiveness. I think that there is some usefulness in a question such as this one to highlight possible but undesirable ways of achieving the goal; this is probably more true now that dressed this up through a few edits from my unexplicit "not so pythonic" initial statement.
mjv