You can't achieve this:
y = MyClass()
y = 3
y = 5
y.previous_value() # will yield 3
Assignment in Python rebinds the name to another object. When you do y = 3
, y
is now a name for the integer 3, not for an instance of MyClass
. This behaviour doesn't depend on the old RHS at all, and can't be intercepted by it without deep magic (you could possibly do something with context managers). The instance of MyClass
that y used to refer to has no knowledge that y no longer refers to it (or that it did in the first place); and even if it did, y.previous_value()
would call a method on the int, not on the MyClass
instance.
The closest you can do is to play with __setitem__
. This is the hook that Python calls when you do something like this:
x = [1, 2, 3]
x[2] = 5
the second line translates to x.__setitem__(2, 5)
. Using this, you can play fun games like this:
class MyClass:
def __init__(self):
self.values = []
def __setitem__(self, item, value):
self.value.append(value)
def previousvalue(self):
return self.values[-2]
def __str__(self):
return str(self.values[-1])
x = MyClass()
x[:] = 5
x[:] = 6
print(x.previousvalue())
Note that you need the []
to trigger __setitem__
, and it needs to have a value - this can be any object, since it is ignored, so I use an empty slice. The fact that you need to jump through syntactic hoops like this should be a big indicator that you should rethink why you want to do this - there is almost certainly a better way to achieve your goal.