BloodSexMagik
BloodSexMagik

Reputation: 398

How to access class instance attributes indirectly?

If I have a class instance with some attributes defined, how do I access them indirectly? My first thought was to put them in a dict and then access them with the keywords but that doesn't work as I expect - example below:

class Test:
    def __init__(self):
        self.testval=0
    
test=Test()
testfuncs={'A':test.testval}

print(test.testval)
testfuncs['A']=1
print(test.testval)

This prints '0' and then '0' as I have not modified the class variable, I've just altered the dictionary value to be the integer '1'.

So I want to be able to access and modify the attribute testval. The reason for this is that in a larger program there are some defined class instance variables that I want to assign once and then reuse throughout. Then by just updating the dict they will change everywhere (they are voltage channels that may change as application changes).

Upvotes: 0

Views: 1529

Answers (2)

kindall
kindall

Reputation: 184151

Use the getattr() function to get an attribute of an object if you have its name in a variable, and setattr() to set it in similar circumstances.

class Test:
    def __init__(self):
        self.testval = 0

test=Test()
A = "testval"

print(test.testval)
setattr(test, A, 1)
print(test.testval)

You can also define your class to have a __setitem__ method; then you can use dictionary-like syntax to set attributes.

class Test:

    def __init__(self):
        self.testval = 0

   def __setitem__(self, key, value):
        setattr(self, key, value)

test=Test()
A = "testval"

print(test.testval)
test[A] = 1
print(test.testval)

Finally (well, there are other ways you can handle this, but I'm only going to mention one more)... finally, you could make a class that holds a reference to an object and an attribute name. This is convenient when you want to pass around such references.

class Test:
    def __init__(self):
        self.testval = 0

class IndirectAttribute:

    def __init__(self, obj, attr):
        self.obj = obj
        self.attr = attr

    def set(self, value):
        setattr(self.obj, self.attr, value)

test = Test()
A = IndirectAttribute(test, "testval")

print(test.testval)
A.set(1)
print(test.testval)

Upvotes: 1

pandascope
pandascope

Reputation: 147

You can set the value of the dictionary to be your test object

class Test:
    def __init__(self):
        self.testval = 0


test = Test()
testfuncs = {'A': test}

print(test.testval) # prints 0
testfuncs['A'].testval = 1
print(test.testval) # prints 1

Upvotes: 1

Related Questions