class AttrSquare:
    def __init__(self, start):
        self.value = start                  # Wywołuje __setattr__!

    def __getattribute__(self, attr):       # Przy pobraniu wszystkich atrybutów
        if attr == 'X':
            return self.value ** 2          # Ponownie wywołuje __getattribute__!
        else:
            return object.__getattribute__(self, attr)

    def __setattr__(self, attr, value):     # Przy przypisaniu wszystkich atrybutów
        if attr == 'X':
            attr = 'value'
        object.__setattr__(self, attr, value)

A = AttrSquare(3)       # 2 instancje klasy z przeciążaniem operatorów
B = AttrSquare(32)      # Każda ma inne informacje o stanie

print(A.X)              # 3 ** 2
A.X = 4
print(A.X)              # 4 ** 2
print(B.X)              # 32 ** 2 (1024)

