Storing value with limits in object
George Sakkis
george.sakkis at gmail.com
Sun Jun 22 09:36:51 EDT 2008
On Jun 22, 5:44 am, "Josip" <fake.m... at noone.be> wrote:
> I'm trying to limit a value stored by object (either int or float):
>
> class Limited(object):
> def __init__(self, value, min, max):
> self.min, self.max = min, max
> self.n = value
> def set_n(self,value):
> if value < self.min: # boundary check
> self.n = self.min
> if value > self.max:
> self.n = self.max
> else:
> self.n = value
> n = property(lambda self : self._value, set_n)
>
> This works,
I bet you didn't even try this, unless your definition of "works"
includes a "RuntimeError: maximum recursion depth exceeded". Here's a
a working version:
class Limited(object):
def __init__(self, value, min, max):
self.min, self.max = min, max
self.n = value
n = property(lambda self : self._value,
lambda self,value:
self.__dict__.__setitem__('_value',
max(self.min, min(value,
self.max))))
def __int__(self): return int(self._value)
def __float__(self): return float(self._value)
a = Limited(11, 0, 9)
print float(a)
import math
print math.sqrt(a)
> except I would like the class to behave like built-in types, so
> I can use it like this:
>
> a = Limited(7, 0, 10)
> b = math.sin(a)
>
> So that object itself returns it's value (which is stored in a.n). Is this
> possible?
For (most) math.* functions it suffices to define __float__, so the
above works. For making it behave (almost) like a regular number,
you'd have to write many more special methods: http://docs.python.org/ref/numeric-types.html.
Here's a possible start:
import operator
class Limited(object):
def __init__(self, value, min, max):
self.min, self.max = min, max
self.n = value
n = property(lambda self : self._value,
lambda self,value:
self.__dict__.__setitem__('_value',
max(self.min, min(value,
self.max))))
def __str__(self): return str(self.n)
def __repr__(self): return 'Limited(%r, min=%r, max=%r)' %
(self.n, self.min, self.max)
def __int__(self): return int(self._value)
def __float__(self): return float(self._value)
def __add__(self, other): return self._apply(operator.add, self,
other)
def __sub__(self, other): return self._apply(operator.sub, self,
other)
# a few dozens more methods follow ...
def __radd__(self, other): return self._apply(operator.add, other,
self)
def __rsub__(self, other): return self._apply(operator.sub, other,
self)
# a few dozens more methods follow ...
@classmethod
def _apply(cls, op, first, second):
minmax = None
if isinstance(first, cls):
minmax = first.min,first.max
first = first._value
if isinstance(second, cls):
if minmax is None:
minmax = second.min,second.max
second = second._value
return cls(op(first,second), *minmax)
a = Limited(11, 0, 9)
print a+1
print 1+a
print a-1
print 1-a
Needless to say, this is almost two orders of magnitude slower than
the builtin numbers, so you'd better not use it for any serious number
crunching.
HTH,
George
More information about the Python-list
mailing list