473,414 Members | 1,766 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,414 software developers and data experts.

assigning values in __init__

Let's say I'm making a game and I have this base class:

class Character(object):

def __init__(self, name, stats):
self.name = name
self.strength = stats[0]
self.dexterity = stats[1]
self.intelligence = stats[2]
self.luck = stats[3]

Is this a good way to assign the values to the different attributes?
Should 'stats' be a list/tuple (like this), or should I do *stats instead?

I'm trying to think ahead to when I might want to add new attributes,
and I want to make sure this doesn't get crazy with individual
parameters instead of just the one list.

Or maybe there's some way to loop through two lists (the stats and the
attributes) and assign them that way? I was thinking of a nested for
statement but that didn't seem to work.
Nov 6 '06 #1
16 1917
John Salerno wrote:
Let's say I'm making a game and I have this base class:

class Character(object):

def __init__(self, name, stats):
self.name = name
self.strength = stats[0]
self.dexterity = stats[1]
self.intelligence = stats[2]
self.luck = stats[3]

Is this a good way to assign the values to the different attributes?
Should 'stats' be a list/tuple (like this), or should I do *stats instead?

I'm trying to think ahead to when I might want to add new attributes,
and I want to make sure this doesn't get crazy with individual
parameters instead of just the one list.

Or maybe there's some way to loop through two lists (the stats and the
attributes) and assign them that way? I was thinking of a nested for
statement but that didn't seem to work.
Sounds like what you should be doing is something like keyword arguments
instead.

class Character(object):
def __init__(self, name, **kwargs):
self.name=name
for key, value in kwargs.items():
setattr(self, key, value)
z=Character('name', strength=10, dexterity=5, intelligence=3, luck=0)

Now you can easily introduce new keyword arguments.

-Larry
Nov 6 '06 #2

John Salerno wrote:
Let's say I'm making a game and I have this base class:

class Character(object):

def __init__(self, name, stats):
self.name = name
self.strength = stats[0]
self.dexterity = stats[1]
self.intelligence = stats[2]
self.luck = stats[3]

Is this a good way to assign the values to the different attributes?
Should 'stats' be a list/tuple (like this), or should I do *stats instead?
How about:

class Character(object):

def __init__(self, name, **kwargs):
self.name = name
self.__dict__.update(kwargs)

c = Character( "Plato", strength=10, luck=12)

print getattr(c, "strength")
print getattr(c, "luck")

10
12

Nov 6 '06 #3
John Salerno wrote:
Let's say I'm making a game and I have this base class:

class Character(object):

def __init__(self, name, stats):
self.name = name
self.strength = stats[0]
self.dexterity = stats[1]
self.intelligence = stats[2]
self.luck = stats[3]

Is this a good way to assign the values to the different attributes?
Should 'stats' be a list/tuple (like this), or should I do *stats instead?

I'm trying to think ahead to when I might want to add new attributes,
and I want to make sure this doesn't get crazy with individual
parameters instead of just the one list.

Or maybe there's some way to loop through two lists (the stats and the
attributes) and assign them that way? I was thinking of a nested for
statement but that didn't seem to work.
If your program deals with 4-element tuples then although you *could*
use *stats in your calls to pass each element of the tuple as a single
argument, that's not really necessary. A way to write the
initializations you want without using indexing is:

class Character(object):

def __init__(self, name, stats):
self.name = name
self.strength, self.dexterity, \
self.intelligence, self.luck = stats

regards
Steve
--
Steve Holden +44 150 684 7255 +1 800 494 3119
Holden Web LLC/Ltd http://www.holdenweb.com
Skype: holdenweb http://holdenweb.blogspot.com
Recent Ramblings http://del.icio.us/steve.holden

Nov 7 '06 #4
On Mon, 06 Nov 2006 16:57:58 -0500, John Salerno wrote:
Let's say I'm making a game and I have this base class:

class Character(object):

def __init__(self, name, stats):
self.name = name
self.strength = stats[0]
self.dexterity = stats[1]
self.intelligence = stats[2]
self.luck = stats[3]

Is this a good way to assign the values to the different attributes?
Should 'stats' be a list/tuple (like this), or should I do *stats instead?

Whenever possible, think about writing self-documenting code:

def __init__(self, name, strength, dexterity, intelligence, luck):
self.name = name
self.strength = strength
# etc.

seems perfectly acceptable to me (if a tad verbose, but that isn't a big
deal -- write once, never touch again).

The problem with function signatures like these:

def __init__(self, name, stats):
def __init__(self, name, *stats):

is that the format of stats is left unstated. Is it (luck, strength,
intelligence) or (strength, intelligence, luck) or (wisdom, charisma,
power, health) or something else? You shouldn't need to read the code
line by line to find out, and relying on documentation risks having the
code and docs get out of sync.

If you expect the stats to be passed as a single tuple, you can still make
it explicit: just wrap the field names within brackets.

def __init__(self, name, (strength, dexterity, intelligence, luck) ):
I'm trying to think ahead to when I might want to add new attributes,
If this is likely, you could do something like this:

def __init__(self, name, **stats):
self.name = name
self.__dict__.update(stats)

Adding extra attributes is fine, since they will just be ignored, but what
if the caller adds an attribute "itnelligence" (instead of intelligence)?
You're now writing lots of code like this:

def save_intelligence(self, threshold):
"""Roll a saving throw against intelligence"""
try:
return roll(self.intelligence) threshold
except AttributeError:
# character has no intelligence, so always fails
return False

Yes, you can make that easier with currying, decorators etc. but why not
make sure your characters have the required attributes in the first place?

One way of doing that would be to add default values for the required
attributes in the class, and let instances inherit those defaults from the
class.

and I want to make sure this doesn't get crazy with individual
parameters instead of just the one list.
If you've got that many character attributes, I'm guessing that your game
will be a tad hard to play :-)

If you have more than a half-dozen or ten character attributes, you could
consider encapsulating them in some way. E.g. group-related attributes and
pass them as tuples:

power =(constitution, health, anaerobic_strength, aerobic_strength)
intelligence =(IQ, wisdom, dexterity, book_learning, street_wisdom)
charisma =(beauty, chutzpah, attractiveness, persuasiveness)
senses =(vision, hearing, smell, telepathy, empathy, feeling, spacial)
others =(luck, determination, laziness, attention_to_detail)

You could then roll against power, say, by giving a set of weights:

character.roll('power', (0.0, 0.0, 0.9, 0.1))

gives anaerobic strength a weighting of 90% and aerobic 10%.

But again, I think that if your roll-playing game needs to have such
fine-grained attributes, I think it will be too complex to be fun.
Or maybe there's some way to loop through two lists (the stats and the
attributes) and assign them that way? I was thinking of a nested for
statement but that didn't seem to work.
def __init__(self, stats):
names = ['strength', 'dexterity', 'intelligence', 'luck']
for name, stat in zip(names, stats):
setattr(self, name, stat)

--
Steven.

Nov 7 '06 #5
John Salerno <jo******@NOSPAMgmail.comwrites:
Let's say I'm making a game and I have this base class:

class Character(object):

def __init__(self, name, stats):
self.name = name
self.strength = stats[0]
self.dexterity = stats[1]
self.intelligence = stats[2]
self.luck = stats[3]

Is this a good way to assign the values to the different attributes?
Should 'stats' be a list/tuple (like this), or should I do *stats
instead?
A tuple is fine, but assumes that there is a logical *sequence* to
these values. If that's true, it should be no problem to assign them as:

class Character(object):
def __init__(self, name, stats):
self.name = name
(self.strength, self.dexterity,
self.intelligence, self.luck) = stats
>>foo = Character("Foo", (10, 11, 9, 10))
print foo.name, foo.strength, foo.intelligence
Foo 10 9

In this case, though, I don't see any value in a specific sequence, so
a mapping looks better to me and gives the caller more flexibility in
how to set it up.

class Character(object):
stat_keys = ['strength', 'dexterity', 'intelligence', 'luck']
def __init__(self, name, stats):
self.name = name
self.stats = {}
for (stat_key, stat_value) in [(k, stats[k])
for k in self.stat_keys]:
setattr(self, stat_key, stat_value)
>>foo = Character("Foo", dict(
... dexterity = 11, luck = 10,
... strength = 10, intelligence = 9,
... ))
>>print foo.name, foo.strength, foo.intelligence
Foo 10 9
I'm trying to think ahead to when I might want to add new
attributes
In which case you almost certainly want a mapping, not a sequence.
and I want to make sure this doesn't get crazy with individual
parameters instead of just the one list.
This is one of the many reasons why Python's built-in composite types
are so useful. A group of semantically-related values can be passed as
a single composite value.

--
\ "I hope that after I die, people will say of me: 'That guy sure |
`\ owed me a lot of money.'" -- Jack Handey |
_o__) |
Ben Finney

Nov 7 '06 #6
Larry Bates <la*********@websafe.comwrote:
John Salerno wrote:
Let's say I'm making a game and I have this base class:

class Character(object):

def __init__(self, name, stats):
self.name = name
self.strength = stats[0]
self.dexterity = stats[1]
self.intelligence = stats[2]
self.luck = stats[3]

Is this a good way to assign the values to the different attributes?
Should 'stats' be a list/tuple (like this), or should I do *stats instead?

I'm trying to think ahead to when I might want to add new attributes,
and I want to make sure this doesn't get crazy with individual
parameters instead of just the one list.

Or maybe there's some way to loop through two lists (the stats and the
attributes) and assign them that way? I was thinking of a nested for
statement but that didn't seem to work.

Sounds like what you should be doing is something like keyword arguments
instead.

class Character(object):
def __init__(self, name, **kwargs):
self.name=name
for key, value in kwargs.items():
setattr(self, key, value)
z=Character('name', strength=10, dexterity=5, intelligence=3,
luck=0)
I would say this is a bad idea because you'll get no error messages if
you mis-spell 'dexterity' for instance.

I'd prefer to see a bit more error checking, something like

class Character(object):
attributes = set(['strength', 'dexterity', 'intelligence', 'luck'])
def __init__(self, name, **kwargs):
self.name=name
for key, value in kwargs.items():
if key not in self.attributes:
raise AttributeError("Bad attribute %s for %s" % (key, self.__class__.__name__))
setattr(self, key, value)
z = Character('name', strength=10, dexterity=5, intelligence=3, luck=0)
>>Character('name', strength=10, dexterity=5, intelligence=3, luck=0)
<Character object at 0xb7dac72c>
>>Character('name', strength=10, dextrity=5, intelligence=3, luck=0)
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "z.py", line 7, in __init__
raise AttributeError("Bad attribute %s for %s" % (key, self.__class__.__name__))
AttributeError: Bad attribute dextrity for Character
>>>
You can then add to attributes in the subclasses

class MagicCharacter(Character):
attributes = Character.attributes | set(['spells', 'wand'])
>>MagicCharacter('name', strength=10, dexterity=5, intelligence=3, luck=0, spells=1)
<MagicCharacter object at 0xb7ce86ac>
>>>
If I was writing this, I'd probably just stick to named parameters
unless I had more than 10 parameters. Named parameters are easy to
manage, and you never get confused by their position.

Also pychecker understands named parameters where as if you use a
scheme like the above you'll cause pychecker problems!

--
Nick Craig-Wood <ni**@craig-wood.com-- http://www.craig-wood.com/nick
Nov 7 '06 #7
John Salerno wrote:
Is this a good way to assign the values to the different attributes?
Should 'stats' be a list/tuple (like this), or should I do *stats instead?
Thanks guys! The main suggestion seems to be to use setattr(), so I
might give that a try. But I do like Steve's suggestion that it's better
to be explicit about each attribute, instead of just accepting a list of
numbers (but I can't help but feel that for some reason this is better,
because it's more general). We shall see! :)
Nov 7 '06 #8
John Salerno <jo******@NOSPAMgmail.comwrites:
But I do like Steve's suggestion that it's better to be explicit
about each attribute, instead of just accepting a list of numbers
(but I can't help but feel that for some reason this is better,
because it's more general).
If you pass a *mapping* of the "I-might-want-to-add-more-in-the-future"
values, then you get both explicit *and* expandable, without an
arbitrary unneeded sequence.

--
\ "He may look like an idiot and talk like an idiot but don't let |
`\ that fool you. He really is an idiot." -- Groucho Marx |
_o__) |
Ben Finney

Nov 7 '06 #9
Ben Finney wrote:
John Salerno <jo******@NOSPAMgmail.comwrites:
>But I do like Steve's suggestion that it's better to be explicit
about each attribute, instead of just accepting a list of numbers
(but I can't help but feel that for some reason this is better,
because it's more general).

If you pass a *mapping* of the "I-might-want-to-add-more-in-the-future"
values, then you get both explicit *and* expandable, without an
arbitrary unneeded sequence.
Do you mean by using the **kwargs parameter? If I do this, doesn't it
mean that *anything* could be added though? Misspelled words and
completely unrelated attributes as well?

Or does this matter as long as you are handling the processing yourself
internally and not allowing users access to the Character class?
Nov 8 '06 #10
On Wed, 08 Nov 2006 10:55:57 -0500, John Salerno wrote:
Ben Finney wrote:
>John Salerno <jo******@NOSPAMgmail.comwrites:
>>But I do like Steve's suggestion that it's better to be explicit
about each attribute, instead of just accepting a list of numbers
(but I can't help but feel that for some reason this is better,
because it's more general).

If you pass a *mapping* of the "I-might-want-to-add-more-in-the-future"
values, then you get both explicit *and* expandable, without an
arbitrary unneeded sequence.

Do you mean by using the **kwargs parameter?
Yes, that's what Ben is talking about.
If I do this, doesn't it
mean that *anything* could be added though? Misspelled words and
completely unrelated attributes as well?
**kwargs flexibility carries a risk. You may consider it worthwhile or not.

Or does this matter as long as you are handling the processing yourself
internally and not allowing users access to the Character class?
Only you can decide whether **kwargs' convenience and flexibility
outweighs its risk.
--
Steven.

Nov 8 '06 #11
John Salerno <jo******@NOSPAMgmail.comwrites:
Ben Finney wrote:
If you pass a *mapping* of the
"I-might-want-to-add-more-in-the-future" values, then you get both
explicit *and* expandable, without an arbitrary unneeded sequence.

Do you mean by using the **kwargs parameter?
No. I mean what I said in this earlier post on this thread:

<URL:http://groups.google.com/group/comp.lang.python/msg/b413bb1f311e7ee1>

If you have a group of named, semantically-related, unsequenced
values, pass them into the function as a mapping object (a dict
object).

--
\ "I have yet to see any problem, however complicated, which, |
`\ when you looked at it in the right way, did not become still |
_o__) more complicated." -- Paul Anderson |
Ben Finney

Nov 9 '06 #12
On Thu, 09 Nov 2006 12:27:12 +1100, Ben Finney wrote:
John Salerno <jo******@NOSPAMgmail.comwrites:
>Ben Finney wrote:
If you pass a *mapping* of the
"I-might-want-to-add-more-in-the-future" values, then you get both
explicit *and* expandable, without an arbitrary unneeded sequence.

Do you mean by using the **kwargs parameter?

No.
Well, that'll teach me to put words in your mouth.

[snip]
If you have a group of named, semantically-related, unsequenced values,
pass them into the function as a mapping object (a dict object).
Still, if you are doing this:

mapping_object = {"strength": roll_dice(10),
"intelligence":roll_dice(10),
"dexterity":roll_dice(10)}
my_character = Character(mapping_object)

then there is little benefit to building the dict just for the purposes of
passing it to Character(), never to use it again, not when you can do this:

my_character = Character(strength: roll_dice(10),
intelligence:roll_dice(10), dexterity:roll_dice(10))

If you happen to already have collected your character attributes in a
mapping object for some other reason, then well and good, pass it into the
function. Otherwise, well, I believe the correct container for
character attributes is a Character, not a dict.

--
Steven.

Nov 9 '06 #13
On 2006-11-09, Steven D'Aprano <st***@REMOVE.THIS.cybersource.com.auwrote:
On Thu, 09 Nov 2006 12:27:12 +1100, Ben Finney wrote:
>John Salerno <jo******@NOSPAMgmail.comwrites:
>>Ben Finney wrote:
If you pass a *mapping* of the
"I-might-want-to-add-more-in-the-future" values, then you get both
explicit *and* expandable, without an arbitrary unneeded sequence.

Do you mean by using the **kwargs parameter?

No.

Well, that'll teach me to put words in your mouth.

[snip]
>If you have a group of named, semantically-related, unsequenced values,
pass them into the function as a mapping object (a dict object).

Still, if you are doing this:

mapping_object = {"strength": roll_dice(10),
"intelligence":roll_dice(10),
"dexterity":roll_dice(10)}
my_character = Character(mapping_object)

then there is little benefit to building the dict just for the purposes of
passing it to Character(), never to use it again, not when you can do this:

my_character = Character(strength: roll_dice(10),
intelligence:roll_dice(10), dexterity:roll_dice(10))
But you will have to adapt this if you want extra or different
characteristics.

Personnally I would prefer something like:

chardict = {}
for char in characteristics:
chardict[char] = roll_dice(10)

my_character = Character(chardict)

This way you only have to keep your characteristics in one place.
If you happen to already have collected your character attributes in a
mapping object for some other reason, then well and good, pass it into the
function. Otherwise, well, I believe the correct container for
character attributes is a Character, not a dict.
What is wrong with keeping the character attributes in a dict in the
Character?

--
Antoon Pardon
Nov 9 '06 #14
On Thu, 09 Nov 2006 10:36:07 +0000, Antoon Pardon wrote:
On 2006-11-09, Steven D'Aprano <st***@REMOVE.THIS.cybersource.com.auwrote:
>On Thu, 09 Nov 2006 12:27:12 +1100, Ben Finney wrote:
>>John Salerno <jo******@NOSPAMgmail.comwrites:

Ben Finney wrote:
If you pass a *mapping* of the
"I-might-want-to-add-more-in-the-future" values, then you get both
explicit *and* expandable, without an arbitrary unneeded sequence.

Do you mean by using the **kwargs parameter?

No.

Well, that'll teach me to put words in your mouth.

[snip]
>>If you have a group of named, semantically-related, unsequenced values,
pass them into the function as a mapping object (a dict object).

Still, if you are doing this:

mapping_object = {"strength": roll_dice(10),
"intelligence":roll_dice(10),
"dexterity":roll_dice(10)}
my_character = Character(mapping_object)

then there is little benefit to building the dict just for the purposes of
passing it to Character(), never to use it again, not when you can do this:

my_character = Character(strength: roll_dice(10),
intelligence:roll_dice(10), dexterity:roll_dice(10))

But you will have to adapt this if you want extra or different
characteristics.
Sure, but only in one place:

# now have charisma
my_character = Character(strength=roll_dice(8),
intelligence=roll_dice(12), dexterity=roll_dice(20),
charisma=roll_dice(6))

If all the char attributes are initialised with the same function, it
may make sense to set them in a loop, as you do below. But if they are all
calculated differently, as above, then you lose the benefit of a loop.
Personnally I would prefer something like:

chardict = {}
for char in characteristics:
chardict[char] = roll_dice(10)

my_character = Character(chardict)

This way you only have to keep your characteristics in one place.
As I do.

Remember, the prerequisite for my suggestion to make sense is that, once
you've created your initial character attributes and stuck them in a dict,
you never use the dict again. Also, I'm assuming the constraint that there
is a manageably small number of character attributes.

>If you happen to already have collected your character attributes in a
mapping object for some other reason, then well and good, pass it into the
function. Otherwise, well, I believe the correct container for
character attributes is a Character, not a dict.

What is wrong with keeping the character attributes in a dict in the
Character?
For the same reason we typically say object.attribute rather than
object.__dict__[attribute]

Perhaps you missed the original post, where one of the constraints was
that character attributes in the game were also object attributes. E.g.

class Character(object):
def __init__(self, strength):
self.strength = strength

The question posed was, what is the best way of calling __init__ with
values for those character attributes?

If the character attributes vary at runtime, or there are many of them, or
if they are needed together (rather than individually) in multiple places
apart from Character.__init__, then it makes sense to bundle them up in a
dict and pass the dict around, like Ben and now you are suggesting.

But if the character attributes are not varying, and there are only a few,
and they only get used collectively for Character.__init__, then I don't
believe there is any advantage to putting them in a dict to be used once
and then tossed away.

To give an analogy, if you are writing a coordinate class, you would
likely do something like this:

class Coord(object):
def __init__(self, x, y):
self.x = x
self.y = y

If you had a lot of dimensions, you'd change your entire model:

class Coord(object):
def __init__(self, alist):
self.coordinates = alist

But it is unlikely that a tactic like this would be worth the extra work:
class Coord(object):
def __init__(self, mapping_object):
# check that mapping_object has the right keys
expected = ['x', 'y']
for key in expected:
if key not in mapping_object.keys(): raise KeyError
# do something with mapping_object
self.__dict__.update(mapping_object)

mapping = {'x': some_value, 'y': some_value}
point = Coord(mapping)
del mapping # never use it again after construction
--
Steven.

Nov 9 '06 #15
Steven D'Aprano wrote:
On Thu, 09 Nov 2006 12:27:12 +1100, Ben Finney wrote:
>John Salerno <jo******@NOSPAMgmail.comwrites:
>>Ben Finney wrote:
If you pass a *mapping* of the
"I-might-want-to-add-more-in-the-future" values, then you get both
explicit *and* expandable, without an arbitrary unneeded sequence.
Do you mean by using the **kwargs parameter?
No.

Well, that'll teach me to put words in your mouth.

[snip]
>If you have a group of named, semantically-related, unsequenced values,
pass them into the function as a mapping object (a dict object).

Still, if you are doing this:

mapping_object = {"strength": roll_dice(10),
"intelligence":roll_dice(10),
"dexterity":roll_dice(10)}
my_character = Character(mapping_object)

then there is little benefit to building the dict just for the purposes of
passing it to Character(), never to use it again, not when you can do this:

my_character = Character(strength: roll_dice(10),
intelligence:roll_dice(10), dexterity:roll_dice(10))
Except, of course, that you *can't* do that: I think you meant to use
equals signs instead of colons?
If you happen to already have collected your character attributes in a
mapping object for some other reason, then well and good, pass it into the
function. Otherwise, well, I believe the correct container for
character attributes is a Character, not a dict.
regards
Steve
--
Steve Holden +44 150 684 7255 +1 800 494 3119
Holden Web LLC/Ltd http://www.holdenweb.com
Skype: holdenweb http://holdenweb.blogspot.com
Recent Ramblings http://del.icio.us/steve.holden

Nov 9 '06 #16
On 2006-11-09, Steven D'Aprano <st***@REMOVE.THIS.cybersource.com.auwrote:
On Thu, 09 Nov 2006 10:36:07 +0000, Antoon Pardon wrote:
>On 2006-11-09, Steven D'Aprano <st***@REMOVE.THIS.cybersource.com.auwrote:
>>On Thu, 09 Nov 2006 12:27:12 +1100, Ben Finney wrote:

John Salerno <jo******@NOSPAMgmail.comwrites:

Ben Finney wrote:
If you pass a *mapping* of the
"I-might-want-to-add-more-in-the-future" values, then you get both
explicit *and* expandable, without an arbitrary unneeded sequence.
>
Do you mean by using the **kwargs parameter?

No.

Well, that'll teach me to put words in your mouth.

[snip]
If you have a group of named, semantically-related, unsequenced values,
pass them into the function as a mapping object (a dict object).

Still, if you are doing this:

mapping_object = {"strength": roll_dice(10),
"intelligence":roll_dice(10),
"dexterity":roll_dice(10)}
my_character = Character(mapping_object)

then there is little benefit to building the dict just for the purposes of
passing it to Character(), never to use it again, not when you can do this:

my_character = Character(strength: roll_dice(10),
intelligence:roll_dice(10), dexterity:roll_dice(10))

But you will have to adapt this if you want extra or different
characteristics.

Sure, but only in one place:
Are your sure? The OP had subclasses like Fighter, Mage etc.
So it seems that you have to do something like this for
every such subclass. Or am I missing something.
# now have charisma
my_character = Character(strength=roll_dice(8),
intelligence=roll_dice(12), dexterity=roll_dice(20),
charisma=roll_dice(6))

If all the char attributes are initialised with the same function, it
may make sense to set them in a loop, as you do below. But if they are all
calculated differently, as above, then you lose the benefit of a loop.
Not necesarily. You could have a table as follows:

characteristics = [("strength", partial(roll_dice, 8)),
("inteligence" , partial(roll_dice, 12),
...

chardict={}
for char, roller in characteristics:
chardict[char] = roller()

>Personnally I would prefer something like:

chardict = {}
for char in characteristics:
chardict[char] = roll_dice(10)

my_character = Character(chardict)

This way you only have to keep your characteristics in one place.

As I do.

Remember, the prerequisite for my suggestion to make sense is that, once
you've created your initial character attributes and stuck them in a dict,
you never use the dict again. Also, I'm assuming the constraint that there
is a manageably small number of character attributes.
That depends on how the rest of the game is set up. Suppose the
character is wandering through a maze. Now in the maze are "tests"
which require the character to roll under a certain characteristic
with a certain bonus/malus. So such a test object value may be
equivallent to ("strength" , -2) I think such a setup will be
easier to implement if you keep the characteristics as a dictionary
within a character instance.

Now whether such a scheme would suit the OP is up to him to decide.
>>If you happen to already have collected your character attributes in a
mapping object for some other reason, then well and good, pass it into the
function. Otherwise, well, I believe the correct container for
character attributes is a Character, not a dict.

What is wrong with keeping the character attributes in a dict in the
Character?

For the same reason we typically say object.attribute rather than
object.__dict__[attribute]
But we also typically use:

object.some_dict[some_characteristic]

rather than

object.__dict__[some_characterictic]

where some_charaterictic contains the name of a characteristic.
Perhaps you missed the original post, where one of the constraints was
that character attributes in the game were also object attributes. E.g.

class Character(object):
def __init__(self, strength):
self.strength = strength

The question posed was, what is the best way of calling __init__ with
values for those character attributes?
Well if that is what he wants.
If the character attributes vary at runtime, or there are many of them, or
if they are needed together (rather than individually) in multiple places
apart from Character.__init__, then it makes sense to bundle them up in a
dict and pass the dict around, like Ben and now you are suggesting.
It is not only that they can vary ay runtime. There is also the
possibility that you don't know in advance which one you will need
because that is decided by the environment. I think that would be
an argument in favor of a dict too.
But if the character attributes are not varying, and there are only a few,
and they only get used collectively for Character.__init__, then I don't
believe there is any advantage to putting them in a dict to be used once
and then tossed away.
I guess it depends on how he will need those characteristics later on.
To give an analogy, if you are writing a coordinate class, you would
likely do something like this:

class Coord(object):
def __init__(self, x, y):
self.x = x
self.y = y
But what if the application often needed one value from such an
object. So lots of time you would be given a coord plus an
indication of what value was wanted by giving a name, so that
you ended up doing a lot of getattr(coord, name) calls.
Because whether you needed the x or y coordinate is decided
by the data and not by the program structure.
May be the O.P. should decide first on how he is going to use
these characteristics in the rest of his game before deciding
what is the best approach.

--
Antoon Pardon
Nov 9 '06 #17

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: Josh | last post by:
Caution, newbie approaching... I'm trying to come up with a very simple Tkinter test application that consists of a window with a drop-down menu bar at the top and a grid of colored rectangles...
10
by: Matthew Sims | last post by:
Python Newbie here. This is my first time learning object-oriented programming and trying to break out of the usual Korn/Perl/PHP style of programming. Having some difficulty understand some items....
13
by: Frans Englich | last post by:
Hello, I am having trouble with throwing class instances around. Perhaps I'm approaching my goals with the wrong solution, but here's nevertheless a stripped down example which demonstrates my...
14
by: Eric Bantock | last post by:
Very basic question I'm afraid. Once an array has been declared, is there a less tedious way of assigning values to its members than the following: myarray=8; myarray=3; myarray=4; myarray=0;...
23
by: Antoon Pardon | last post by:
I know this PEP is rejected. However I have a problem that would benefit from having extreme values and the sample implementation that is given in the PEP is unsatifactory for my purpose. I had...
10
by: Alan G Isaac | last post by:
My class MyClass reuses many default parameters with a small number of changes in each instance. For various reasons I decided to put all the parameters in a separate Params class, instances of...
5
by: Manuel Graune | last post by:
Hello, while trying to learn how to program using objects in python (up to now simple scripts were sufficient for my needs) I stumbled over the a problem while assigning values to an object. ...
7
by: George Sakkis | last post by:
A situation that often comes up is having to initialize several instance attributes that accept a default value. For a single class, passing the default values in __init__ is fine: class...
1
by: The Pythonista | last post by:
I've been wondering for a while about whether assigning to __class__ is bad form or not. Specifically, I mean doing so when some other method of implementing the functionality you're after is...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.