Search code examples
pythondictionaryselfclass-variables

Python: 'self' is unsubscriptable


I have a class with a multiple dictionary variables. Is there a way to set the dictionary parameter of the class variable where variable name is passed as a string in a function?

<?php
class Test:
    var1 = { "value": 1 }
    var2 = { "value": 2 }

    def set_variable(self, var_name, value):
        ## self.var_name.value = value ### pylint: Instance of 'Test' has no 'var_name' member
        self[var_name]["value"] = value ### pylint: 'self' is unsubscriptable ###

instance = Test()
instance.set_variable("var1", 150)

While coding the linter throws error stating: " 'self' is unsubscriptable". If I execute the code, I get the error: " TypeError: 'Test' object is not subscriptable".

One way to fix this problem is by creating a temporary variable using 'getattr':

    def set_variable(self, var_name, value):
        temp = getattr(self, var_name)
        temp["value"] = value
        setattr(self, var_name, temp)

But, I find the above to be an ugly solution increasing memory usage especially for much bigger dictionaries.

Also, I would like to use self[var_name] at many places. Is there a way to do this?


Solution

  • While Python classes are implemented using dictionaries, you can't treat them as dictionaries out of the box.

    self[var_name] should be getattr(self, var_name).

    If you insist on using [ ] syntax Test should implement __getitem__:

    class Test:
        var1 = { "value": 1 }
        var2 = { "value": 2 }
    
        def set_variable(self, var_name, value):
            self[var_name]["value"] = value
            # or getattr(self, var_name)["value"] = value if not implementing __getitem__
    
        def __getitem__(self, item):
            return getattr(self, item)
    
    instance = Test()
    instance.set_variable("var1", 150)
    print(instance.var1)
    #  {'value': 150}