306

I have a class like the following:

class User:
    def __init__(self):
        self.data = []
        self.other_data = []

    def doSomething(self, source):
        // if source = 'other_data' how to access self.other_data

I want to pass a string for the source variable in doSomething and access the class member of the same name.

I have tried getattr which only works on functions (from what I can tell) as well as having User extend dict and using self.__getitem__, but that doesn't work either. What is the best way to do this?

0

4 Answers 4

406

x = getattr(self, source) will work just perfectly if source names ANY attribute of self, including the other_data in your example.

Sign up to request clarification or add additional context in comments.

1 Comment

(realizing this is an old thread). I was confused/always forget this because of dicts. If I want to get a value from a dict, I can say: myDict.get('keyy'), so I would expect attributes to work the same way: myObject.getattr('attr_name'). But instead they take the object as a first argument...ok to do, but the apparent inconsistency is why I had trouble.
285

A picture's worth a thousand words:

>>> class c:
        pass
o = c()
>>> setattr(o, "foo", "bar")
>>> o.foo
'bar'
>>> getattr(o, "foo")
'bar'

2 Comments

I like this answer in particular because it illustrates, simply, that the getattr() function works outside class methods as well.
It does not, however, demonstrate that getattr() and setattr() work inside the __init__() function, as well, which they do. So, instead of doing self[myStr] = myValue, which won't work, you can do setattr(self, myStr, myValue), which does work, even inside of __init__(). Just to clarify that for others.
123
  • getattr(x, 'y') is equivalent to x.y
  • setattr(x, 'y', v) is equivalent to x.y = v
  • delattr(x, 'y') is equivalent to del x.y

4 Comments

How I can access x.y according to the value string of v?
@user2284570: If v contains the string 'y' then getattr(x, v) gives the value of x.y.
@md2perpe except it is not the case.
@user2284570: How was your case, then?
5

Extending Alex's answer slightly:

class User:
    def __init__(self):
        self.data = [1,2,3]
        self.other_data = [4,5,6]
    def doSomething(self, source):
        dataSource = getattr(self,source)
        return dataSource

A = User()
print A.doSomething("data")
print A.doSomething("other_data")

will yield:

[1, 2, 3]
[4, 5, 6]

However, personally I don't think that's great style - getattr will let you access any attribute of the instance, including things like the doSomething method itself, or even the __dict__ of the instance. I would suggest that instead you implement a dictionary of data sources, like so:

class User:
    def __init__(self):

        self.data_sources = {
            "data": [1,2,3],
            "other_data":[4,5,6],
        }

    def doSomething(self, source):
        dataSource = self.data_sources[source]
        return dataSource

A = User()

print A.doSomething("data")
print A.doSomething("other_data")

again yielding:

[1, 2, 3]
[4, 5, 6]

2 Comments

I didn't explain properly... my apologies. I am able to get the data via the string. However, I am having problems setting the data using the above methods. Specifically I have tried getattr(self, "other_data") = [1, 2, 3] as well as self.__setitem__("other_data", [1, 2, 3])
@sberry2A, getattr() is only for getting, setattr() is for setting. You can't assign to the return value from getattr().