Implementing a circular counter using property / descriptors?

Gerard Flanagan grflanagan at yahoo.co.uk
Mon Oct 9 06:05:06 EDT 2006


IloChab wrote:

> I'd like to implement an object that represents a circular counter, i.e.
> an integer that returns to zero when it goes over it's maxVal.
>
> This counter has a particular behavior in comparison: if I compare two of
> them an they differ less than half of maxVal I want that, for example,
> 0 > maxVal gives true.
> This is because my different counters  grew together and they never
> differ a lot between them and so a value of 0 compared with an other of
> maxVal means that the previous one just made its increment before the
> other one.
>
> The python problem that I give you it's about style.
> I'd like to write in my code something that looks almost like using an
> integer object.
>
> I mean, I'd like to write:
>
> cnt = CircularConter(maxVal=100, initialVal=10)
> cnt += 100     # cnt value is 9
> print cnt      # prints 9
> 100 > cnt      # is false
> cnt = 100      # cnt new value is 100 [NOT  rebind cnt with 100]
>

[...]

> ... and so my real writing was:
>
> cnt = CircularConter(maxVal=100, initialVal=10)
> cnt += 100
> print cnt
> 100 > cnt        # is false
> cnt.set(100)
>
> The fact is that I don't like to write cnt.set(100) or
> cnt = CircularConter(100, 100) instead of cnt = 100.
> So I thought that property or descriptors could be useful.
> I was even glad to write:
>
> cnt = CircularConterWithProperty(maxVal=100, initialVal=10)
> cnt.val += 100
> print cnt.val
> 100 > cnt.val      # is false
> cnt.val = 100
>
> just to give uniformity to counter accessing syntax.
> But I wasn't able to implement nothing working with my __cmp__ method.
>

[...]

>
> __ What I don't know __  is if there is a way to write a class that allows
> my desire of uniform syntax or if IT IS JUST A NON SENSE.
>
> I'll thank in advance for any answer.
>
> Saluti a tutti
> Licia

As Steven said, it's not possible to do what you want. I don't think
there's any way around either

    cnt.val = 100

or

    cnt.setval(100)

Here's an iterator version of your Counter class:

class Counter(object):

    def __init__(self, maxval, initval=0):
        self.maxval = maxval
        self.val = initval

    def __iter__(self):
        return self

    def next(self):
        ret = self.val
        self.__add__(1)
        return ret

    def __add__(self, increment):
        self.val = (self.val + increment) % self.maxval
        return self

    def __sub__(self, decrement):
        self.val = (self.val - decrement) % self.maxval
        return self

    def __cmp__(self, operand):
        return cmp(self.maxval/2, abs(operand - self.val)) *
cmp(self.val,operand)

    def __repr__(self):
        return str(self.val)

    def __str__(self):
        return str(self.val)


cnt = Counter(10)
print cnt
cnt += 23
print cnt, cnt > 5

cnt.val = 7
print
print cnt, cnt > 5

cnt -= 65
print
print cnt, cnt > 5

print
print zip(cnt, ['a', 'b', 'c', 'd'])

-----------------------

Gerard




More information about the Python-list mailing list