trictionary?

Bengt Richter bokr at oz.net
Mon Aug 29 18:53:24 EDT 2005


On 28 Aug 2005 18:54:40 -0700, "mensanator at aol.com" <mensanator at aol.com> wrote:

>Steven Bethard wrote:
>> Adam Tomjack wrote:
>> > Steven Bethard wrote:
>> > ...
>> >> Using a two element list to store a pair of counts has a bad code
>> >> smell to me.
>> > ...
>> >
>> > Why is that?
>>
>> Note that "code smell"[1] doesn't mean that something is actually wrong,
>> just that it might be.  In Python, pairs are usually handled with
>> tuples[2], but tuples would be inconvenient in this case, since the
>> first value must be modified.  Declaring a class with two attributes as
>> you suggested is often a good substitute, but if the OP's code is really
>> what it looks like, I get another code smell because declaring a class
>> to be used by only 10 lines of code seems like overkill.
>>
>> I also get a code smell from a dict holding two-element lists because
>> I've been writing in Python and answering questions on the Python-list
>> for a couple of years now, and I've never needed one yet. ;-)
>>
>> STeVe
>>
>> [1]http://en.wikipedia.org/wiki/Code_smell
>> [2]http://www.python.org/doc/faq/general.html#why-are-there-separate-tuple-and-list-data-types
>
>Could you do me a favor and see what this smells like?
>
>I put some data in a csv file (with headers) and this will
>bring it in quite simply as a dictionary with [names] as
>keys and an attribute dictionary as the value.
>
>py_monsters.csv:
>
>name,hardiness,agility,friend,courage,room,weight,special_def_odds,armor,weapon,odds,dice,side,hits,reaction,desc
>PIRATE,5,20,0,10,26,300,0,0,11,60,1,10,0,"not met",You see a man with a
>beard and a brass ring in his ear.  He is wearing clothes  made of silk
>and is wielding a very fancily engraved sword.
>
>
>import csv
>temp1 = []
>temp2 = []
>reader = csv.reader(file(r"py_monsters.csv"))
>for rec in reader:
>	temp1.append(rec)
>for i in temp1[1:]:
>	temp2.append((i[0],dict(zip(temp1[0][1:],i[1:]))))
>monsters = dict(temp2)
>
>This gives me what I want
>
>[('PIRATE', {'reaction': 'not met',
>'agility': '20',
>'room': '26',
>'weight': '300',
>'armor': '0',
>'weapon': '11',
>'hits': '0',
>'side': '10',
>'special_def_odds': '0',
>'courage': '10',
>'hardiness': '5',
>'desc': 'You see a man with a beard and a brass ring in his ear.
>He is wearing clothes  made of silk and is wielding a very fancily
>engraved sword.',
>'odds': '60',
>'friend': '0',
>'dice': '1'})]
>
>so that I can now write code like
>
>if monsters['PIRATE']['reaction']=='not met':
>        print monsters['PIRATE']['desc']

I think if the field names are legal python names, I would rather write that 'if ...'
without all that line noise ;-) E.g., using simple classes (and effectively using
their attribute instance dicts essentially the way you used raw dicts), you could write

    if monsters.PIRATE.reaction == 'not met':
        print monsters.PIRATE.desc

Also, if the reaction, agility, etc list is fixed, you could use __slots__ for
better efficiency. Also, your __init__ method for the latter could convert
strings to ints for handier use later (unless csv already does that in the mode
you are using).

>From the above code I infer that you can do define the requisite classes, so
I'll leave it to you ;-) Note that attribute access opens the door to having
default values as class variables, and using properties to retrieve dynamically
calculated values by name. If you are not familiar with those aspects of classes,
your progammer.agility value can increase markedly with a little study ;-)

E.g., a name like monsters.random_elf could live right
alongside PIRATE and return one a randomly selected elf from a an internal list
of elves or via random selection from a list of elf names defined at the same
level as PIRATE, etc. etc. You could also dynamically configure these guys
according to distance to food and time since last meal, and if you are
carrying food, etc.

With suitable classes you could put instances in various "spaces" defined
by other classes, that define geometric or social or other interactions.

>
>instead of using stupid index numbers.
>
>But the loader seems to have a kind of perl-like odor to it,
>i.e., next week I won't understand what it does.
>
If you have to do something tricky, choose names wisely and
comment the non-obvious ;-)

Regards,
Bengt Richter



More information about the Python-list mailing list