pythondictionarysetattr

How to not mess up self.__dict__ generation when using self.__setattr__()


I'm trying to implement special behavior, so that values in self and self.aux_gate are always the same. I tried doing this by implementing __setattr__(), but in doing this, I've ran in many problems regarding __dict__.

From what I could gather, it seems like whenever self.__setattr__() is called normally, it adds a key-value pair to self.__dict__, corresponding to the arguments self.__setattr__() is given.

However, the self.__setattr__() I've written seems to create extra self.__dict__ entries, I've seen self.__dict__["conditional"],self.__dict__["current_Position"], and self.__dict__["current_Track"]. I don't see how those values have made their way into self.__dict__.

Here is the class, I've copied and pasted it's superclass below

class SWAP_Gate(Quantum_Gate):
    
    def __init__(self, cost, conditional, current_Track, current_Position, rectangle = None, aux_gate = None):
        if aux_gate is None:
            self.aux_gate = SWAP_Gate(cost,conditional,current_Track,current_Position, aux_gate = self)
        else:
            self.aux_gate = aux_gate
        self.cost = cost
        self.__SWAPconditional = conditional
        self.__SWAPcurrent_Track = current_Track
        self.__SWAPcurrent_Position = current_Position
        if rectangle is None:
            self.rectangle = pg.Rect(430, 0, 1480, 150)
        else:
            self.rectangle = rectangle
    
    def __setattr__(self, name, value):
        super(SWAP_Gate, self).__setattr__(name, value)
        if name == "conditional":
            self.aux_gate.conditional = value
        #I've deleted some code on this line that jsut made the whole post a lot harder to read, it's not relevant to my problem
        elif name == "current_Position":
            self.current_Position = value
            self.aux_gate.current_Position = value
        elif name == "aux_gate":
            self.__dict__["aux_gate"] == value
        else:
            self.__dict__[name] == value
    
    def __getattr__(self, name):
        if name == "conditional":
            return self.__SWAPconditional
        elif name == "current_Track":
            return self.__SWAPcurrent_Track
        elif name == "current_Position":
            return self.__SWAPcurrent_Position
class Quantum_Gate():
        
    def __init__(self, cost, conditional, current_Track, current_Position, rectangle = None):
        self.cost = cost
        self.conditional = conditional
        self.current_Track = current_Track
        self.current_Position = current_Position
        if rectangle is None:
            self.rectangle = pg.Rect(0, 0, 100, 100)
        else:
            self.rectangle = rectangle```

Solution

  • The main thing I see is that the first statement in your __setattr__ function is

    super(SWAP_Gate, self).__setattr__(name, value)
    

    This statement will cause the default setattr behavior to occur in addition to any other code you have in __setattr__, so seeing "current_Track" in __dict__ is expected anytime current_Track is set (unless a super class to SWAP_Gate prevents the default behavior of setattr) .

    If you don't want that default behavior to occur, then remove the super() statement at the top of __setattr__ and replace the self.__dict__ statement with it in the final else statement:

    def __setattr__(self, name, value):
            # Removed super() statement from here
            if name == "conditional":
                self.aux_gate.conditional = value
            elif name == "current_Track":
                if self.current_Track:
            #...
            elif name == "aux_gate":
                self.__dict__["aux_gate"] == value
            else:
                #replaced self.__dict__[name]=value with super() statement:
                super(SWAP_Gate, self).__setattr__(name, value)