I want to inherit from integers and only redefine some methods.
The goal is to have this behaviour:
>>> i = Iter()
>>> i == 0
True
>>> next(i)
Iter<1>
>>> next(i)
Iter<2>
>>> i + 10
12
The naive approach would be to inherit from int
:
class Iter(int):
def __new__(cls, start=0, increment=1):
return super().__new__(cls, start)
def __init__(self, start=0, increment=1):
self.increment = increment
def __repr__(self):
return f"Iter<{int(self)}>"
def __next__(self):
self += self.increment # DO NOT WORK
return self.value
Unfortunately, int
is immutable. I tried to use the ABC for integers, but I don't really want to redefine all operators:
from numbers import Integral
class Iter(Integral):
...
i = Iter()
TypeError: Can't instantiate abstract class I with abstract methods
__abs__, __add__, __and__, __ceil__, __eq__, __floor__,
__floordiv__, __int__, __invert__, __le__, __lshift__, __lt__,
__mod__, __mul__, __neg__, __or__, __pos__, __pow__, __radd__,
__rand__, __rfloordiv__, __rlshift__, __rmod__, __rmul__, __ror__,
__round__, __rpow__, __rrshift__, __rshift__, __rtruediv__,
__rxor__, __truediv__, __trunc__, __xor__
Any other ideas?
Are you aware that itertools.count
exists? It does most of what you are trying to do, except for being able to use the instance itself as an integer.
It is not possible to extend either int
or itertools.count
for this purpose.
Regarding the methods for operators, the reason you would need to define them is because there is not an obvious return value in this case, even if extending int
or count
worked. What would __add__
return - an integer, or another instance of Iter
with its value incremented by the given amount? You would need to decide that, and implement them for your use case.
Rather than extending any existing builtin class, it may be easier to define your own. You can define the __int__
method to control what happens when int(...)
is called on an instance of your class.
Example implementation:
class Iter:
def __init__(self, start: int = 0, increment: int = 1):
self._value = start
self._increment = increment
def __int__(self) -> int:
return self._value
def __repr__(self) -> str:
return f'Iter<{self._value}>'
def __next__(self) -> int:
self._value += self._increment
return self._value
Example use:
>>> i = Iter()
>>> next(i)
1
>>> next(i)
2
>>> i
Iter<2>
>>> int(i)
2