Storing value with limits in object
Lie
Lie.1296 at gmail.com
Mon Jun 23 23:25:49 CEST 2008
On Jun 23, 1:24 am, "Josip" <i... at i.i> wrote:
> > Why not make it a function?
>
> > function assignLimited(value, vmin, vmax):
> > value = max(vmin, value)
> > value = min(vmax, value)
> > return value
>
> > a = assignLimited(7, 0, 10)
>
> > Seems like it solves your problem relatively cleanly.
> > Note: I also removed min/max variables because they would mask the
> > built-in min/max functions.
>
> > -Larry
>
> Still, I'm going for object
> oriented solution because I want the value and it's limits to be kept
> together as I'll have many such values with different limits.
In that case, "overriding assignment" makes no sense since if an
operation is done on two values that have two different limits, what
would happen? Take the first's or second's limits, or interpolate the
new limit by some magic function? A much better solution would be for
operation to always return plain vanilla int, and we set limits
explicitly.
> Storing all
> the limits in caller namespace is not really an option.
You want to store limits in the object too?
Try this: (_LimitedInt inherits from int, so operator overloading is
unnecessary)
###
#!/usr/bin/env python
class _LimitedInt(int):
class InvalidLimitsError(Exception): pass
def __init__(self, value, base = 10):
int.__init__(value, base)
def setlimits(self, lim):
''' Set the limits and if value is not within limit,
raise ValueError
The lim argument accepts:
- A _LimitedInt instance, from which to copy the limits
- A two-tuple, which specifies the limits i.e. (min, max)
If lim isn't those or lim[0] > lim[1], raise
InvalidLimitsError
Accepting _LimitedInt instance is just for convenience
'''
if isinstance(lim, _LimitedInt):
lim = lim.limits
try:
self.min, self.max = [int(x) for x in lim]
if self.min > self.max: raise ValueError
except (ValueError, TypeError):
raise self.InvalidLimitsError, ('limit = %s' % str(lim))
if not (self.min < self < self.max):
raise ValueError, \
('val = %s, min = %s, max = %s' % \
(self, self.min, self.max))
def getlimits(self):
return (self.min, self.max)
limits = property(getlimits, setlimits)
def lint(value, limits, base = 10):
if base != 10:
ret = _LimitedInt(value, base)
else:
ret = _LimitedInt(value)
ret.limits = limits
return ret
### END OF REAL CODE ###
### THE REST ARE JUST TESTING CODES ###
if __name__ == '__main__':
print 'Instantiating lint...'
a = lint(50, (0, 200)) # Limit explicitly specified
b = lint(150, a) # Copy the limits of a
c = lint(a, (0, 1000)) # Value = a, Limit = (0, 1000)
d = lint(a, c) # Value = a, Limit = c
print
print 'Printing the value and the limits...'
print a, a.limits
print b, b.limits
print c, c.limits
print d, d.limits
print
print 'Changing limits'
print 'Note: lint is partially immutable,'
print ' its limits is mutable,'
print ' while its value is immutable'
a.limits = (0, 300)
b.limits = a
print a, a.limits
print b, b.limits
print
print '"Changing" values'
a = lint(b, a)
print a, a.limits
print
print 'Operations...'
e = lint(a + b - c * d + 100, (-10000, 1000))
f = a + b - c * d ## Operation returns plain integer
g = lint(f, (-100000, 100000)) ## Always recast result of operator
print e, e.limits, type(e) ## This is an int, not lint
print f, type(f) ## BEWARE: f is integer, it has no
limits
print g, g.limits, type(g)
## INVALIDS
# a = lint(100, (1000, 100000))
# a = lint(100, 'ab')
# a = lint(100, (10000, 0))
# a = lint(100, 10)
# a = lint(100, (10, 1000, 10000))###
More information about the Python-list
mailing list