Чтобы отслеживать текущее и предыдущее значение определенных переменных, которые постоянно обновляются внутри цикла, я создал класс-обертку, который автоматически сохраняет старое значение внутри него при его обновлении:
class Updatable:
def __init__(self, value=None, prev_value=None):
# Initial conditions
self._value = value
self._prev_value = prev_value
@property
def value(self):
return self._value
@property
def prev_value(self):
return self._prev_value
def update(self, new_value):
self._prev_value = self._value
self._value = new_value
def has_value(self):
return self._value is not None
def has_prev_value(self):
return self._prev_value is not None
Однако, чтобы она работала больше как обычная переменная, я хочу, чтобы все обычные операторы работали как положено (кроме присваивания, которое не может быть перегружено в Python), поэтому я определил многие специальныеметоды, которые может иметь класс:
# Object representation
def __str__(self):
return str(self._value)
def __repr__(self):
return repr(self._value)
# Iteration
def __len__(self):
return len(self._value)
def __getitem__(self, key):
return self._value[key]
def __reversed__(self):
return reversed(self._value)
# Arithmetic operations
def __add__(self, other):
return self._value + other
def __sub__(self, other):
return self._value - other
def __mul__(self, other):
return self._value * other
def __matmul__(self, other):
return self._value @ other
def __truediv__(self, other):
return self._value / other
def __floordiv__(self, other):
return self._value // other
def __mod__(self, other):
return self._value % other
def __divmod__(self, other):
return divmod(self._value, other)
def __pow__(self, other, *args):
return pow(self._value, other, *args)
def __lshift__(self, other):
return self._value << other
def __rshift__(self, other):
return self._value >> other
def __and__(self, other):
return self._value & other
def __xor__(self, other):
return self._value ^ other
def __or__(self, other):
return self._value | other
# Comparison operators
def __eq__(self, other):
return self._value == other
def __ne__(self, other):
return self._value != other
def __lt__(self, other):
return self._value < other
def __gt__(self, other):
return self._value > other
def __le__(self, other):
return self._value <= other
def __ge__(self, other):
return self._value >= other
Хотя это может показаться большим количеством специальных методов, это все еще далеко от всех специальных методов , и поддержка всех их будет означать дажебольше кода, чем у меня уже есть.
Более того, определение этих специальных методов не позволяет мне использовать экземпляр в качестве второго операнда в двоичной операции.Например, хотя код
a = Updatable(2)
a + 3
работает, код
a = Updatable(2)
3 + a
приводит к ошибке TypeError: unsupported operand type(s) for +: 'int' and 'Updatable'
, которая нежелательна, если ее удобно использовать.
Существует ли какой-то другой подход к созданию класса-оболочки, который (почти) столь же удобен в использовании, как и использование типа данных, который он переносит напрямую (игнорируя тот факт, что при использовании обнаженного типа данных у вас не будет доступа кпредыдущее значение, если вы не храните его явно)?