Python class __call__ method and dot notation

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

>Solution :

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.

Leave a Reply