Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #89570

Re: Useful module to be written by a newbie

References <87y4lbasvf.fsf@Equus.decebal.nl> <mailman.88.1430324895.3680.python-list@python.org> <87pp6mc100.fsf@Equus.decebal.nl> <mhr9u0$858$1@ger.gmane.org>
From Ian Kelly <ian.g.kelly@gmail.com>
Date 2015-04-29 13:40 -0600
Subject Re: Useful module to be written by a newbie
Newsgroups comp.lang.python
Message-ID <mailman.94.1430336500.3680.python-list@python.org> (permalink)

Show all headers | View raw


On Wed, Apr 29, 2015 at 1:03 PM, Peter Otten <__peter__@web.de> wrote:
> I was judging from the look of your MovingAverage.
>
> I don't like the interface, it really should take an iterable so that you
> can write
>
>>>> list(moving_average([1,2,3], 2))
> [1.5, 2.5]

The problem with this is that many use cases for moving averages need
to access the current average before future items become available.
For example, a download speed indicator: it needs to average the
transfer rate over the last few seconds. There will be more transfer
rate data in the future, but it's not available yet, so you can't add
it to the iterable unless the iterable is actually some sort of
read/write buffer that can be appended to once iteration has already
started.

That seems overly complex, though; for one, you need to be careful not
to exhaust the buffer, since the iteration protocol requires that once
next() raises StopIteration, it will always raise StopIteration. But
also, why add the data to object A so that it can be consumed by
object B if you could just add it to object B directly?

So I think the iterable interface that you're describing really needs
to be a coroutine of some sort:

>>> from collections import deque
>>> def moving_average(length):
...     values = deque([(yield)], maxlen=length)
...     while True:
...         values.append((yield sum(values) / len(values)))
...
>>> mavg = moving_average(5)
>>> next(mavg)
>>> mavg.send(1)
1.0
>>> mavg.send(2)
1.5
>>> mavg.send(3)
2.0
>>> mavg.send(4)
2.5
>>> mavg.send(5)
3.0
>>> mavg.send(6)
4.0
>>> mavg.send(7)
5.0

This works, but I don't really like it. For one, our moving_average
"iterable" isn't really an iterable any more; we need to call send
instead of next, which means we can't just stick it inside a for loop.
And if we can't iterate over it, then what's the point of using a
generator? If we make it a class, then we can give it a more flexible
API.

class MovingAverage(object):

    def __init__(self, length):
        self.values = deque(maxlen=length)

    def append(self, value):
        self.values.append(value)

    def average(self):
        return sum(self.values) / len(self.values)

Which is pretty much back to where we started.

Back to comp.lang.python | Previous | NextPrevious in thread | Find similar | Unroll thread


Thread

Useful module to be written by a newbie Cecil Westerhof <Cecil@decebal.nl> - 2015-04-29 16:53 +0200
  Re: Useful module to be written by a newbie Peter Otten <__peter__@web.de> - 2015-04-29 18:27 +0200
    Re: Useful module to be written by a newbie Cecil Westerhof <Cecil@decebal.nl> - 2015-04-29 19:12 +0200
      Re: Useful module to be written by a newbie Peter Otten <__peter__@web.de> - 2015-04-29 21:03 +0200
        Re: Useful module to be written by a newbie Cecil Westerhof <Cecil@decebal.nl> - 2015-04-29 22:47 +0200
          Re: Useful module to be written by a newbie Peter Otten <__peter__@web.de> - 2015-04-30 00:00 +0200
          Re: Useful module to be written by a newbie Michael Welle <mwe012008@gmx.net> - 2015-05-09 08:10 +0200
            Re: Useful module to be written by a newbie Cecil Westerhof <Cecil@decebal.nl> - 2015-05-09 10:28 +0200
              Re: Useful module to be written by a newbie Michael Welle <mwe012008@gmx.net> - 2015-05-09 11:43 +0200
      Re: Useful module to be written by a newbie Ian Kelly <ian.g.kelly@gmail.com> - 2015-04-29 13:40 -0600

csiph-web