Reputation: 137
I want to be able to do something like:
def func(var_name):
x = 2
y = 3
return getattr(self, var_name)
And have
func("x")
return 2. Obviously the problem here is that the function call doesn't get passed itself, so I don't have access to a self
that I can pass into getattr
.
I thought this answer was a solution to this problem, but it returns f itself, rather than a specific call of it, so can't access variables computed while func runs.
Obviously in this toy example using getattr or something similar isn't necessary, but I have a more complicated situation where I think it might be.
This question has been poorly received, apparently because it's something people think I shouldn't want to do in the first place, so I want to explain why I want to do this: I am coding a pokemon battle game, and am trying to solve the problem of how to encode attacks that (may) have an effect back on the user, such as an attack that has the potential to give a moxie boost (you don't need to know what that means).
The way I addressed this problem is by giving the attack object an attribute which is a list of BackEffect
objects. These objects would consist of a function do()
which executes the effect, and information on when do should be executed, and what arguments do()
needs, because different effects need access to different information. E.g. a moxie boost effect would need to be executed if the attack faints the opposing pokemon. The execute_attack()
function would then be able to go through the list and call all the do functions that need to be called.
The original way I did this gets quite cluttered as you add more effects:
def execute_attack(attack, pokemon):
DO VARIOUS OTHER THINGS WHICH PRODUCES VARIABLES USED BELOW
attacker = attack.attacking_pokemon
for b in attack.back_effects:
if b.effect_type == "needs to know if hit":
b.do(attacker, did_it_hit)
elif b.effect_type == "needs to know if fainted":
b.do(attacker, did_it_faint)
elif b.effect_type == "needs to know how much damage":
b.do(attacker, how_much_damage)
With more elifs needing to be added sometimes when new effects are implemented. This is clearly quite repetitive, so I wanted to find a way of doing this which avoids repetition, and which allows new BackEffect
s to be added without editing execute_attack()
, as long as the relevant variables are already accessible to execute_attack()
.
For an object, this would be possible using getattr()
, so I thought something like that was what I was looking for. The proposal to put everything in a dictionary is undesirable because I would either have to put everything in execute_attack()
into a dictionary, or edit execute_attack()
to move more variables into the dictionary whenever I add a new effect_type
, making execute_attack()
get larger and larger. It would make the rest of the code that isn't dealing with back effects look a lot messier if a lot of otherwise unrelated key variables that get used over and over again have to be retrieved from the same dictionary.
Using locals()
doesn't have this problem, so it seems like a much nicer solution, for my specific purposes. I'm aware it can cause problems if unexpected things end up being asked for from execute_attack()
, but the list of things that can be asked for is built in, so that shouldn't be an issue for me. I just don't want it to be built in in a very repetitive way to execute_attack()
, which is already a long function. This also makes it easier to implement new effects.
Is using locals()
still bad practice in my case? If so, why?
I didn't include this information initially because my last question was poorly received for going into unnecessary detail.
Upvotes: -2
Views: 68
Reputation: 49805
Replace the last line of func
with:
return locals()[var_name]
Upvotes: -1