By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,285 Members | 2,124 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,285 IT Pros & Developers. It's quick & easy.

refactoring so that multiple changes can be made with one variable?

P: n/a
My code is below. For now I'm focusing on the lines where health (and
armor) are increased in each character class. Let's say I decided to
change the amount of increase in the future. As it is now, I'd have to
go to each character class and change the number so that each is still
in a good relation to the other (right now: 3, 2, 1; later: perhaps 4,
3, 2, 1, if I added a new class -- i.e., change Fighter from 3 to 4,
Thief from 2 to 3, in other words increase them all by 1). So instead of
changing each one, is there a simple, clean way of just changing a
single number so that this change is reflected in all classes? Hope that
makes sense.

class Character(object):
def __init__(self, name, strength, dexterity, intelligence):
self.name = name
self.health = 10
self.armor = self.attack = self.defense = self.magic_attack = \
self.magic_defense = 0
self.strength = strength
self.dexterity = dexterity
self.intelligence = intelligence
self.adjust_attributes()

def adjust_attributes(self):
pass
class Fighter(Character):
def adjust_attributes(self):
self.health += 3
self.armor += 3
self.attack += 2
self.defense += 2
self.strength += 1
class Thief(Character):
def adjust_attributes(self):
self.health += 2
self.armor += 2
self.attack += 1
self.defense += 1
self.magic_defense += 1
self.dexterity += 1
class Mage(Character):
def adjust_attributes(self):
self.health += 1
self.armor += 1
self.magic_attack += 2
self.magic_defense += 2
self.intelligence += 1
Nov 14 '06 #1
Share this Question
Share on Google+
6 Replies


P: n/a

John Salerno wrote:
My code is below. For now I'm focusing on the lines where health (and
armor) are increased in each character class. Let's say I decided to
change the amount of increase in the future. As it is now, I'd have to
go to each character class and change the number so that each is still
in a good relation to the other (right now: 3, 2, 1; later: perhaps 4,
3, 2, 1, if I added a new class -- i.e., change Fighter from 3 to 4,
Thief from 2 to 3, in other words increase them all by 1). So instead of
changing each one, is there a simple, clean way of just changing a
single number so that this change is reflected in all classes? Hope that
makes sense.

You could keep a handle on all object instances created then go through
the objects making appropriate changes, e.g:
class Character(object):
instances = []
def __init__(self, name, strength, dexterity, intelligence):
instances.append(self)
# as before ...
def mod_instances(self):
for inst in instances:
inst.some_property += 1 # or whatever
# (Untested)

- Paddy.

Nov 14 '06 #2

P: n/a
Paddy wrote:
You could keep a handle on all object instances created then go through
the objects making appropriate changes, e.g:
class Character(object):
instances = []
def __init__(self, name, strength, dexterity, intelligence):
instances.append(self)
# as before ...
def mod_instances(self):
for inst in instances:
inst.some_property += 1 # or whatever
# (Untested)
But doesn't this require that the change be predetermined so you can
code it into the method?

I don't necessarily need a programmatic way to do this, just a simple
way to go back to the code and edit a single thing, instead of having to
update all the numbers.
Nov 14 '06 #3

P: n/a
John Salerno wrote:
My code is below. For now I'm focusing on the lines where health (and
armor) are increased in each character class. Let's say I decided to
change the amount of increase in the future. As it is now, I'd have to
go to each character class and change the number so that each is still
in a good relation to the other (right now: 3, 2, 1; later: perhaps 4,
3, 2, 1, if I added a new class -- i.e., change Fighter from 3 to 4,
Thief from 2 to 3, in other words increase them all by 1). So instead of
changing each one, is there a simple, clean way of just changing a
single number so that this change is reflected in all classes? Hope that
makes sense.

class Character(object):
def __init__(self, name, strength, dexterity, intelligence):
self.name = name
self.health = 10
self.armor = self.attack = self.defense = self.magic_attack = \
self.magic_defense = 0
self.strength = strength
self.dexterity = dexterity
self.intelligence = intelligence
self.adjust_attributes()

def adjust_attributes(self):
pass
class Fighter(Character):
def adjust_attributes(self):
self.health += 3
self.armor += 3
self.attack += 2
self.defense += 2
self.strength += 1
class Thief(Character):
def adjust_attributes(self):
self.health += 2
self.armor += 2
self.attack += 1
self.defense += 1
self.magic_defense += 1
self.dexterity += 1
class Mage(Character):
def adjust_attributes(self):
self.health += 1
self.armor += 1
self.magic_attack += 2
self.magic_defense += 2
self.intelligence += 1
The place to do this seems to be in the Character class.

class Character(object):
_health_base_inc = 1
_armor_base_inc = 1
# etc
def __init__(self, name, strength, dexterity, intelligence):
self.name = name
self.health = 10
self.armor = self.attack = self.defense = self.magic_attack = \
self.magic_defense = 0
self.strength = strength
self.dexterity = dexterity
self.intelligence = intelligence
self.adjust_attributes()

def adjust_attributes(self):
pass

class Mage(Character):
# for symmetry with Character
_health_char_inc = 1
_armor_char_inc = 1
# etc
def adjust_attributes(self):
self.health += self._health_char_inc + self_health_base_inc
self.armor += self._armor_char_inc + self._armor_base_inc
# etc

James

--
James Stroud
UCLA-DOE Institute for Genomics and Proteomics
Box 951570
Los Angeles, CA 90095

http://www.jamesstroud.com/
Nov 14 '06 #4

P: n/a

John Salerno wrote:
Paddy wrote:
You could keep a handle on all object instances created then go through
the objects making appropriate changes, e.g:
class Character(object):
instances = []
def __init__(self, name, strength, dexterity, intelligence):
instances.append(self)
# as before ...
def mod_instances(self):
for inst in instances:
inst.some_property += 1 # or whatever
# (Untested)

But doesn't this require that the change be predetermined so you can
code it into the method?

I don't necessarily need a programmatic way to do this, just a simple
way to go back to the code and edit a single thing, instead of having to
update all the numbers.
I just put in a simple version of mod_instances. mod_instances could
take a function as an argument the napply the function to all
instances, e.g:

def mod_func1(inst):
inst.abc += inst.xyz # or whatever

class Character(object):
instances = []
def __init__(self, name, strength, dexterity, intelligence):
instances.append(self)
# as before ...
def mod_instances(self, mod_func):
for inst in instances:
mod_func(inst)

You can define different mod_func, like mod_func1 to make whatever
changes to the instances.

Nov 15 '06 #5

P: n/a
On Tue, 14 Nov 2006 10:41:53 -0500, John Salerno wrote:
My code is below. For now I'm focusing on the lines where health (and
armor) are increased in each character class. Let's say I decided to
change the amount of increase in the future. As it is now, I'd have to
go to each character class and change the number so that each is still
in a good relation to the other (right now: 3, 2, 1; later: perhaps 4,
3, 2, 1, if I added a new class -- i.e., change Fighter from 3 to 4,
Thief from 2 to 3, in other words increase them all by 1). So instead of
changing each one, is there a simple, clean way of just changing a
single number so that this change is reflected in all classes? Hope that
makes sense.
Cutting your code down to the minimum that exhibits the behaviour you want:

class Character(object):
def __init__(self, name, strength, dexterity, intelligence):
self.name = name
self.health = 10
# and so on...
self.adjust_attributes()
def adjust_attributes(self):
pass
class Fighter(Character):
def adjust_attributes(self):
self.health += 3

class Thief(Character):
def adjust_attributes(self):
self.health += 2

etc.

Sounds like you want some sort of factory function that returns a class:

# WARNING: untested
def make_character_class(name, adjustments):
class klass(Character):
_adjustments = {}
def adjust_attributes(self):
for key, value in self._adjustments.items():
x = getattr(self, key)
setattr(self, key, x + item)

setattr(klass, klass.__name__, name)
setattr(klass, klass._adjustments, adjustments)
return klass
And now you use it like this:

Fighter = make_character_class('Fighter', {'health': 3})
Thief = make_character_class('Thief', {'health': 2})

Now you can easily change the adjustments, all in just a few lines.

Here's another idea:

character_adjustments = { 'Fighter': {'health': 3},
'Thief': {'health': 2},
'Mage': {'intelligence': 3, 'strength': -1}
}

and change the make_character_class factory function above to only take a
single argument, name. Now if you decide you want to *programmatically*
adjust the adjustments, you can do this:

# still untested...
for key in character_adjustments:
for attribute, value in key.items():
# adjust the values to make up for my poor choices
character_adjustments[key][attribute] = value + 1

(but of course you must do this BEFORE creating your character classes!)
And last but most certainly not least, you can separate the adjustment
values into (say) an INI file, read them in at run-time and pass those
values to the factory function above. Then write another function which
walks through the INI file, adjusting the values in place as needed. This
is obviously going to take the most work, so I strongly suggest you don't
go down this path unless you really have to.
--
Steven D'Aprano

Nov 15 '06 #6

P: n/a
On 2006-11-15, Dennis Lee Bieber <wl*****@ix.netcom.comwrote:
On Wed, 15 Nov 2006 18:57:39 +1100, Steven D'Aprano
<st***@REMOVEME.cybersource.com.audeclaimed the following in
comp.lang.python:
>And last but most certainly not least, you can separate the
adjustment values into (say) an INI file, read them in at
run-time and pass those values to the factory function above.
Then write another function which walks through the INI file,
adjusting the values in place as needed. This is obviously
going to take the most work, so I strongly suggest you don't
go down this path unless you really have to.

Nice to see I wasn't the only one to consider extending to an
INI file for this <G>
Coincidentally, I'm just reading "The Pragmattic Programmer" for
the first time. One of guidelines is to pry the details ut of the
code if they might change. The above advice seems like a perfect
example.

--
Neil Cerutti
For those of you who have children and don't know it, we have a
nursery downstairs. --Church Bulletin Blooper
Nov 15 '06 #7

This discussion thread is closed

Replies have been disabled for this discussion.