Serzhev
Serzhev

Reputation: 41

__getattribute__ getting attributes from custom dict

how to get attributes from the instance «custome» dict (here it is d_new), rather than instance «standard» __dict__ ?

I am trying to use __getattribute__ for this purpose.

class FTr:
    def __init__(self):
        self.d_new = {}

    def __getattribute__(self, name):
        # if hasattr(something, 'd_new'):
        #     return 
        # else:
            return super().__getattribute__(name)

    def __setattr__(self, name, value):        
        if hasattr(self, 'd_new'):
            self.d_new[name] = value
        else:
            self.__dict__[name] = value
        
    def base(self, val):
        return getattr(self, val)


class Point(FTr):
    fields = ('x', 'y', 'z')

    def __init__(self, x, y, z):
        self.x, self.y, self.z = x, y, z
        super().__init__()


p = Point(1, 2, 3)
print(p.base('x'))
p.x = 4
print(p.base('x'))
print(p.x)

The result I would like to have is (the last output 4 not 1):

#1
#1
#4

Upvotes: 0

Views: 71

Answers (1)

jsbueno
jsbueno

Reputation: 110121

__getattribute__ is a bit tricky to implement, because it is used for any attribute access, even that access occur from inside itself - so, you can't just use self.d_new in that code.

By calling the original __getattribute__, however, that is feasible.

class FTr:
    fields = ()
    def __init__(self):
        self.d_new = {}
        for name in self.__class__.fields:
            self.d_new[name] = None

    def __getattribute__(self, name):
        try:
            namespace = super().__getattribute__("d_new")
        except AttributeError:
            return {}
        if name in namespace:
            return namespace[name]
        return super().__getattribute__(name)

    def __setattr__(self, name, value):        
        if name in self.d_new:
            self.d_new[name] = value
            return
        return super().__setattr__(name, value)


class Point(FTr):
    fields = ('x', 'y', 'z')

    def __init__(self, x, y, z):
        super().__init__()
        self.x, self.y, self.z = x, y, z
        

Upvotes: 1

Related Questions