assigning values in __init__

Antoon Pardon apardon at forel.vub.ac.be
Thu Nov 9 11:31:21 EST 2006


On 2006-11-09, Steven D'Aprano <steve at REMOVE.THIS.cybersource.com.au> wrote:
> On Thu, 09 Nov 2006 10:36:07 +0000, Antoon Pardon wrote:
>
>> On 2006-11-09, Steven D'Aprano <steve at REMOVE.THIS.cybersource.com.au> wrote:
>>> On Thu, 09 Nov 2006 12:27:12 +1100, Ben Finney wrote:
>>>
>>>> John Salerno <johnjsal at NOSPAMgmail.com> writes:
>>>> 
>>>>> 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



More information about the Python-list mailing list