Reputation: 33
I want to accomplish the following:
tmp = do_stuff(tmp2)
if tmp != None:
num = tmp
However the variables to be assigned in my problem are variables (better: properties) of an object instance:
class mycls(object):
def __init__(self):
self.__a, self._b, self.c = 2, 3, 5
def set_a(self, val): self.__a = val
def set_b(self, val): self._b = val
def set_c(self, val): self.c = val
A = property(fset = set_a)
B = property(fset = set_b)
C = property(fset = set_c)
tmp2 = [7, 11, 13]
inst = mycls()
tmp = do_stuff(tmp2[0])
if tmp != None: inst.A = tmp
tmp = do_stuff(tmp2[1])
if tmp != None: inst.B = tmp
tmp = do_stuff(tmp2[2])
if tmp != None: inst.C = tmp
Obviously the last part looks highly repetitive and in my case needs to be applied to over 10 variables. My question now is: how can those last 6 lines be compressed?
Ideally I would prefer a solution like:
for i in [[inst.A, 0], [inst.B, 1], [inst.C, 2]]:
tmp = do_stuff(tmp2[i[1]])
if tmp != None: i[0] = tmp
However this doesn't work (because the inst.X
are evaluated and you can't store primitive datatypes by reference/pointer). Another approach I came up with was to use the variable names as strings and fiddle with inst.__dict__
, e.g. like this:
for i in [["A", 0], ["B", 1], ["C", 2]]:
tmp = do_stuff(tmp2[i[1]])
if tmp != None: inst.__dict__[i[0]] = tmp
However this plan was foiled by the fact that A
, B
and C
are properties.
LISP-like macros would be an enormous help here, unfortunately Python doesn't seem to support macros and I don't want to add dependencies to one of the macro libraries for Python I found on-line (which I didn't test since I won't be able to use them anyway).
I also want to avoid using anonymous functions in a list since this will likely result in the same amount of code as in the second code listing.
My last resort to solve this problem would currently be eval
s, which I wanted to avoid at all cost.
Upvotes: 3
Views: 1187
Reputation: 1121814
You are looking for setattr()
:
for i in [["A", 0], ["B", 1], ["C", 2]]:
tmp = do_stuff(tmp2[i[1]])
if tmp != None: setattr(inst, i[0], tmp)
To quote the documentation:
This is the counterpart of
getattr()
. The arguments are an object, a string and an arbitrary value. The string may name an existing attribute or a new attribute. The function assigns the value to the attribute, provided the object allows it. For example,setattr(x, 'foobar', 123)
is equivalent tox.foobar = 123
.
Note that since None
is a singleton in python, usually one tests for it using the is
or is not
operators:
for i in [["A", 0], ["B", 1], ["C", 2]]:
tmp = do_stuff(tmp2[i[1]])
if tmp is not None:
setattr(inst, i[0], tmp)
and the PEP 8 python styleguide discourages compound statements; keep the if
suite on it's own line, even if it is just one line.
Upvotes: 5