0

My Goal is to use dot notation to select strings from dictionarys using the SimpleNamespace modeule while having the ability to change which dictionary to use.

To do this i have tried modifying the class __call__ method to change the output based on a previously set variable. However, due to the use of the __call__ method it requires the use of () to be included which breaks the simple formatting of dot notation. Additinally i need to be able to use class methods as well to change the option i am looking for.

class i: x, y = 1, 2
class j: x, y = 3, 4
class myClass:
    def __init__(self):
        self.a, self.b = i(), j()
        self.selection = "a"
    def set_selection(self, selection):
        self.selection = selection
    def __call__(self):
        return getattr(self, self.selection)

mc = myClass()
print(mc().x) ## this generates the output i am wanting by using the __call__ method
mc.set_selection("b") ## i still need to call class methods
print(mc().x)
print(mc.x) ## this is the syntax i am trying to achive

although mc().x works it is not dot notation.

The output i am looking for in this example would be similar to:

import myClass
data = myCalss()

print(data.x + data.y) 
#>>> 3
data.set_selection("b")
print(data.x + data.y) 
#>>> 7

1 Answers1

2

Seem like __call__() is the wrong choice for the interface you want. Instead, maybe __getattr__() is what you want:

class i: x, y = 1, 2
class j: x, y = 3, 4
    
class myClass:
    def __init__(self):
        self.a, self.b = i(), j()
        self.selection = "a"
        
    def set_selection(self, selection):
        self.selection = selection
        
    def __getattr__(self, at):
        return getattr(getattr(self, self.selection), at)

data = myClass()

print(data.x + data.y)
# 3
data.set_selection("b")
print(data.x + data.y) 
# 7

Might want some checks to make sure the selection is valid.

Also, probably worth reading up on descriptors if you will be exploring this kind of stuff more deeply.

Mark
  • 90,562
  • 7
  • 108
  • 148
  • thanks, when i tried using __getarrt__ before i went in a infinite loop after setting self.selecting. can you explain what the at arg is ? – user3310078 Jan 14 '23 at 04:15
  • You want to first get the object at `getattr(self, self.selection)`, then you want to get the attribute of *that* object using the argument `at` passed into the function. – Mark Jan 14 '23 at 04:17
  • Another source of an infinite loop could be that `selection` is neither `'a'` nor `'b'`, you need to check for that first – Max Jan 14 '23 at 04:20
  • ah i see. when using __getarrt__ the first arg is the string value of what ever is after the `.` in my case it would be 'x' and 'y'. I did try to create the infinite loop but it just gives Attribute Error so i think it works perfectly as is, if not i can add in checks. Thanks so much! – user3310078 Jan 14 '23 at 04:26