0

I have a long list of if statements that are checking if an object (self) contains a series of optional attributes.

As an example:

if(hasattr(self, variableList)):
    var1 = self.var1

if(hasattr(self, "var2")):
    var2 = self.var2  

if(hasattr(self, "var3")):
    var3 = self.var3

if(hasAttr(self, "var4")):
    var4 = self.var4

I was trying to figure out if there was a simple way of using a for loop that would use variable names from a list to check the object, and if they exist to store them locally in the method, which I think would require a dictionary in some way. Is it bad practice to try the above? Would it be more appropiate to have the more explicit list or to reduce the code with something like

for x in variableList:
    if(hasattr(self,variableList[x]))
        localvariable = variableList[x]
Xivilai
  • 2,481
  • 3
  • 15
  • 15
  • 3
    Should that be `hasattr` instead of `hasAttr`? – mgilson Jul 28 '14 at 20:49
  • 2
    The answer is yes, you _can_ do something here, but before you do, have a look at http://nedbatchelder.com/blog/201112/keep_data_out_of_your_variable_names.html – mgilson Jul 28 '14 at 20:49
  • I would store those values in a list instead. What you're trying to do is a little weird. – cdonts Jul 28 '14 at 20:50
  • 1
    Why would you want this? Why not just use the attributes directly? – jonrsharpe Jul 28 '14 at 21:01
  • I have a function that uses **kwargs. I want to check if certain attributes exist in an object, and only doing work with them if they do – Xivilai Jul 28 '14 at 21:04
  • 1
    @Xivilai: If you're trying to look up attributes dynamically, they're probably not really attributes of an object, but members of a dictionary, so you should use them that way. (I say "probably" because there are cases where 90% of your code wants to treat them as static attributes and the other 10% as dynamic, or vice-versa; they're very rare cases, but they do exist.) – abarnert Jul 28 '14 at 22:04

2 Answers2

1

This should work for you:

var_list = ['var1', 'var2', 'var3'] # create list of variable string names

for var in var_list: # iterate over list of variable names

    try:
        # use exec to execute assignments, assuming attribute exists
        exec('{0} = {1}'.format(var, getattr(self, var))) 

    except AttributeError: # catch the Exception if the attribute does not exist

        exec('{0} = None'.format(var)) # set var to some default value, whatever
                                       # is convenient for later code to check
                                       # for and handle

As others suggested in the comments, you seem to be using an odd construct. After you get your code working, I would suggest taking it over to CodeReview and ask about better methods to achieve what you're trying to do. Without seeing the rest of your code it's hard to tell, but I suspect there's a better way to accomplish your overall goal.

Community
  • 1
  • 1
skrrgwasme
  • 9,358
  • 11
  • 54
  • 84
1

Every object has a __dict__ property that stores the instance members in a dictionary. Very useful for highly dynamic/introspective things. For instance:

class c():
    def __init__(self):
        self.a = 1
    def test(self):
        print self.__dict__


>>> o = c()
>>> o.test()

prints

{'a': 1}

EDIT: getattr is probably a better suggestion than __dict__

Another useful tidbit is that locals() is the dictionary of local variables that you can read and write to.

For instance:

>>> locals()["TEST"] = 1
>>> TEST

prints

1

From these two facts, you should be able to do whatever you're trying to do. Whether or not it's a good idea is a completely different story. :) (I'm guessing it probably isn't. See @mgilson 's comment).

Mike Bell
  • 1,356
  • 11
  • 9