0

I have a class that contains a nested dictionary that I want to make getters and setters for. I use a depth first search to generate the functions and add them to the class's __dict__ attribute, but when I try to call any of the generated functions, I just get an AttributeError: 'MyClass' object has no attribute 'getA'.

import operator
from functools import reduce


class MyClass:
    def __init__(self):
        self.dictionary = {
            "a": {
                "b": 1,
                "c": 2
            },
            "d": {
                "e": {
                    "f": 3,
                    "g": 4
                }
            }
        }

        self.addGettersSetters()

    def addGettersSetters(self):
        def makegetter(self, keyChain):
            def func():
                return reduce(operator.getitem, keyChain, self.dictionary)
            return func

        def makesetter(self, keyChain):
            def func(arg):
                print("setter ", arg)
                path = self.dictionary
                for i in keyChain[:-1]:
                    path = path[i]
                path[keyChain[-1]] = arg
            return func

        # depth first search of dictionary
        def recurseDict(self, dictionary, keyChain=[]):
            for key, value in dictionary.items():
                keyChain.append(key)
                # capitalize the first letter of each part of the keychain for the function name
                capKeyChain = [i.title().replace(" ", "")
                            for i in keyChain]
                # setter version
                print('set{}'.format("".join(capKeyChain)))
                self.__dict__['set{}'.format(
                    "".join(capKeyChain))] = makesetter(self, keyChain)
                # getter version
                print('get{}'.format("".join(capKeyChain)))
                self.__dict__['set{}'.format(
                    "".join(capKeyChain))] = makegetter(self, keyChain)
                # recurse down the dictionary chain
                if isinstance(value, dict):
                    recurseDict(self, dictionary=value,
                                keyChain=keyChain)
                # remove the last key for the next iteration
                while keyChain[-1] != key:
                    keyChain = keyChain[: -1]
                keyChain = keyChain[: -1]

        recurseDict(self, self.dictionary)
        print(self.__dict__)


if __name__ == '__main__':
    myclass = MyClass()
    print(myclass.getA())

If you run this code, it outputs the names of all of the generated functions as well as the state of __dict___ after generating the functions and terminates with the AttributionError.

What has me puzzled is that I used another piece of code that uses essentially the same methodology as an example for how to generate getters and setters this way. That piece of code works just fine, but mine does not and, per my eyes and research, I am at a loss as to why. What am I missing here?

For reference I am running Anaconda Python 3.6.3

Aran-Fey
  • 39,665
  • 11
  • 104
  • 149
  • 1
    You have a typo. You're assigning the getter functions to the names `setX`. Change `self.__dict__['set{}'.format(` to `self.__dict__['get{}'.format(`. – Aran-Fey Apr 06 '18 at 17:56
  • That was it. There are other logic problems, but I can now at least call the functions. Thanks a ton! I looks like I just needed an extra pair of eyes! – Clayton Ramstedt Apr 06 '18 at 18:08

0 Answers0