Account Options

  1. Sign in
The old Google Groups will be going away soon, but your browser is incompatible with the new version.
Google Groups Home
« Groups Home
seeking to improve Python skills
There are currently too many topics in this group that display first. To make this topic appear first, remove this option from another topic.
There was an error processing your request. Please try again.
flag
  7 messages - Collapse all  -  Translate all to Translated (View all originals)
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
mk  
View profile  
 More options Jan 23 2009, 6:17 am
Newsgroups: comp.lang.python
From: mk <mrk...@gmail.com>
Date: Fri, 23 Jan 2009 12:17:41 +0100
Local: Fri, Jan 23 2009 6:17 am
Subject: seeking to improve Python skills
Hello everyone,

I wrote the following program mainly for educational purpose of
improving my Python programming skills -- would Pythonistas here please
look at it and point out areas that could use improvement?

This thing analyzes the stored load average record file, calculates
simple moving average and produces Gnuplot program to plot the thing.

Constructive criticism is welcome.

#!/usr/bin/python

import re
import sys
import tempfile
import subprocess
import os

class MovingAvg(object):

         def __init__(self, fname):
                 try:
                         self.fo = open(fname)
                 except IOError, e:
                         print "Problem with opening file:", e
                         sys.exit(4)
                 self.reslist = []
                 self.smalist = []
                 self.maxval = 0

         def extrfromfile(self):
                 vre = re.compile("(\d+-\d+-\d+) (\d\d:\d\d) (\d+\.\d+)")
                 for line in self.fo:
                         res = vre.search(line)
                         if res:
                                 self.reslist.append({'day':res.group(1),\
                                 'time':res.group(2),\
                                 'val':float(res.group(3))})

         def calc_sma(self, smalen=4):
                 if smalen == 0:
                         raise AssertionError, "Moving Average sample
length cannot be 0"
                 if not isinstance(smalen, int):
                         raise AssertionError, "Moving Average sample
length has to be integer"
                 total = 0
                 total = sum( [ x['val'] for x in self.reslist[0:smalen] ] )
                 sma = total / smalen
                 smaidx = int(smalen/2)
                 self.smalist.append((self.reslist[0]['day'],\
                         self.reslist[0]['time'],\
                         self.reslist[0]['val'],\
                         self.reslist[0]['val']))
                 for i in range(smalen, len(self.reslist)):
                         curval = self.reslist[i]['val']
                         self.maxval = max(self.maxval, curval)
                         total += curval
                         total -= self.reslist[i - smalen]['val']
                         sma = total / smalen
                         smaidx += 1
                         self.smalist.append((self.reslist[smaidx]['day'],\
                                 self.reslist[smaidx]['time'],\
                                 self.reslist[smaidx]['val'],\
                                 sma))

         def return_results(self):
                 return (self.reslist, self.smalist, self.maxval)

class GnuplotWrapper(object):
         def __init__(self, smalist, maxval, outfname = "calc.png",
graphlen=640, graphheight=480, gnuplot = '/usr/bin/gnuplot'):
                 self.outfname = outfname
                 self.smalist = smalist
                 self.gnuplot = gnuplot
                 self.gprog = None
                 self.gdata = None
                 self.graphlen = graphlen
                 self.graphheight = graphheight

         def _writefiles(self):
                 self.gprog = tempfile.mkstemp()
                 self.gdata = tempfile.mkstemp()
                 self.gprogfile = open(self.gprog[1], 'wb')
                 self.gdatafile = open(self.gdata[1], 'wb')
                 labelnum = int(self.graphlen / 110)
                 labelstep = int(len(self.smalist) / labelnum)
                 labels = []
                 for i in range(0, len(self.smalist), labelstep):
                         labels.append("\"%s %s\" %d" %
(self.smalist[i][0], self.smalist[i][1], i))
                 labelstr = ", ".join(labels)

                 self.gprogfile.write("""set terminal png size %d, %d
set style line 1 lt 1 lw 2
set style line 2 lt 2 lw 2
set output "%s"
set xtics(%s)
set yrange [0:%f]
set y2range [0:%f]
plot "%s" using 1 with lines ls 1 title "orig" axes x1y1, "%s" using 2
with lines ls 2 title "Moving Average" axes x1y2
""" % (self.graphlen, self.graphheight, self.outfname, labelstr,
float(maxval), float(maxval),\
                 self.gdata[1], self.gdata[1]) )
                 self.gprogfile.close()
                 for elem in self.smalist:
                         self.gdatafile.write("%f, %f\n" % (elem[2],
elem[3]))
                 self.gdatafile.close()

         def plot(self):
                 self._writefiles()
                 gplot = subprocess.Popen(self.gnuplot + " " +
self.gprog[1],\
                         shell=True, stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
                 print "Plotting data (%s)..." % self.outfname
                 so, se = gplot.communicate()
                 if se:
                         print "Gnuplot problem output:", se
                 os.remove(self.gprog[1])
                 os.remove(self.gdata[1])

if __name__ == "__main__":
         try:
                 fname = sys.argv[1]
         except IndexError:
                 print "Specify filename with data as first argument."
                 sys.exit(1)
         except Exception, e:
                 print "Error:", e
                 sys.exit(2)
         values = MovingAvg(fname)
         values.extrfromfile()
         values.calc_sma(smalen = 10)
         (reslist, smalist, maxval) = values.return_results()
         gp = GnuplotWrapper(smalist, maxval)
         gp.plot()

Example data:

08-11-19 12:41 0.11 0.45 0.40 2/158 27091
08-11-19 12:42 0.08 0.43 0.39 9/171 27113
08-11-19 12:43 0.57 0.53 0.43 4/163 12350
08-11-19 12:44 0.21 0.43 0.40 8/176 12422
08-11-19 12:45 0.08 0.36 0.37 6/166 12507
08-11-19 12:46 0.66 0.51 0.43 4/163 30147
08-11-19 12:47 0.32 0.43 0.40 4/163 30195
08-11-19 12:48 0.12 0.35 0.37 9/174 30263
08-11-19 12:49 0.47 0.43 0.40 6/162 15513
08-11-19 12:50 0.17 0.35 0.37 2/159 15562
08-11-19 12:51 0.11 0.30 0.35 6/162 15613
08-11-19 12:52 0.68 0.47 0.41 5/161 779
08-11-19 12:53 0.25 0.38 0.38 4/161 859
08-11-19 12:54 0.16 0.33 0.36 9/174 927
08-11-19 12:55 0.62 0.44 0.39 5/166 18633
08-11-19 12:56 0.36 0.42 0.39 6/162 18672
08-11-19 12:57 0.23 0.37 0.37 5/163 18757
08-11-19 12:58 0.56 0.46 0.40 4/161 4026
08-11-19 12:59 0.26 0.39 0.37 4/220 4134
08-11-19 13:00 0.16 0.33 0.35 7/169 4232
08-11-19 13:01 0.56 0.44 0.39 1/162 21882
08-11-19 13:02 0.22 0.37 0.36 4/161 21921
08-11-19 13:03 0.14 0.32 0.35 5/163 21972
08-11-19 13:04 0.78 0.53 0.42 5/173 7246
08-11-19 13:05 0.34 0.45 0.40 5/163 7299
08-11-19 13:06 0.20 0.39 0.38 5/167 7369
08-11-19 13:07 0.54 0.48 0.41 5/165 24993
08-11-19 13:08 0.25 0.40 0.38 8/174 25071
08-11-19 13:09 0.18 0.36 0.36 6/168 25148
08-11-19 13:10 0.54 0.45 0.39 5/172 10397
08-11-19 13:11 0.27 0.39 0.37 4/167 10440
08-11-19 13:12 0.22 0.36 0.36 5/168 10517
08-11-19 13:13 1.05 0.67 0.47 4/169 28210
08-11-19 13:14 0.46 0.56 0.44 6/172 28266
08-11-19 13:15 0.17 0.45 0.41 6/172 28346
08-11-19 13:16 0.63 0.55 0.45 5/171 13597
08-11-19 13:17 0.42 0.53 0.45 4/172 13679
08-11-19 13:18 0.20 0.44 0.42 5/172 13735
08-11-19 13:19 0.59 0.54 0.45 4/170 31370
08-11-19 13:20 0.21 0.44 0.42 5/172 31431
08-11-19 13:21 0.08 0.36 0.40 6/172 31511
08-11-19 13:22 0.64 0.51 0.45 4/172 16756
08-11-19 13:23 0.23 0.42 0.42 4/172 16804
08-11-19 13:24 0.13 0.35 0.40 9/185 16881
08-11-19 13:25 0.64 0.48 0.44 5/174 2074
08-11-19 13:26 0.26 0.40 0.41 4/172 2120
08-11-19 13:27 0.14 0.34 0.39 5/174 2176
08-11-19 13:28 0.64 0.47 0.43 6/174 19887
08-11-19 13:29 0.23 0.38 0.40 4/172 19972
08-11-19 13:30 0.12 0.32 0.38 4/182 20042
08-11-19 13:31 0.80 0.51 0.44 6/174 5302
08-11-19 13:32 0.29 0.42 0.41 6/173 5360
08-11-19 13:33 0.11 0.34 0.38 5/174 5446
08-11-19 13:34 0.46 0.42 0.40 4/172 23086
08-11-19 13:35 0.22 0.36 0.38 5/172 23137
08-11-19 13:36 0.28 0.38 0.39 7/175 23188
08-11-19 13:37 0.62 0.49 0.42 4/172 8464
08-11-19 13:38 0.28 0.41 0.40 4/172 8512
08-11-19 13:39 0.10 0.33 0.37 6/175 8571
08-11-19 13:40 0.51 0.42 0.39 6/173 26216
08-11-19 13:41 0.18 0.34 0.37 4/172 26296
08-11-19 13:42 0.07 0.28 0.34 6/173 26345
08-11-19 13:43 0.49 0.38 0.37 5/172 11590
08-11-19 13:44 0.25 0.33 0.35 6/173 11639
08-11-19 13:45 0.09 0.26 0.33 8/179 11747
08-11-19 13:46 0.58 0.40 0.37 4/175 29375
08-11-19 13:47 0.27 0.34 0.35 4/175 29423
08-11-19 13:48 0.10 0.28 0.33 6/176 29472
08-11-19 13:49 0.55 0.40 0.37 4/174 14752
08-11-19 13:50 0.20 0.33 0.34 4/170 14803
08-11-19 13:51 0.15 0.28 0.32 6/171 14852
08-11-19 13:52 0.52 0.39 0.36 5/172 32488
08-11-19 13:53 0.23 0.33 0.34 4/170 32566
08-11-19 13:54 0.08 0.27 0.32 6/173 32624
08-11-19 13:55 0.50 0.38 0.35 4/172 17880
08-11-19 13:56 0.24 0.32 0.33 6/174 17930
08-11-19 13:57 0.09 0.26 0.31 9/184 18044
08-11-19 13:58 0.51 0.37 0.35 4/167 3383
08-11-19 13:59 0.18 0.30 0.32 4/167 3449
08-11-19 14:00 0.10 0.26 0.30 6/171 3509
08-11-19 14:01 0.50 0.36 0.34 7/168 21261
08-11-19 14:02 0.25 0.32 0.32 7/176 21318
08-11-19 14:03 0.09 0.26 0.30 6/169 21359
08-11-19 14:04 0.59 0.39 0.34 5/170 6613
08-11-19 14:05 0.21 0.31 0.32 5/251 6774
08-11-19 14:06 0.08 0.25 0.29 5/170 6832
08-11-19 14:07 0.59 0.39 0.34 4/168 24469
08-11-19 14:08 0.28 0.34 0.32 6/179 24530
08-11-19 14:09 0.10 0.27 0.30 6/172 24600
08-11-19 14:10 0.55 0.40 0.34 4/175 9857
08-11-19 14:11 0.20 0.32 0.31 4/172 9898
08-11-19 14:12 0.07 0.26 0.29 8/183 9967
08-11-19 14:13 0.51 0.37 0.33 4/169 27631
08-11-19 14:14 0.19 0.30 0.30 4/175 27705
08-11-19 14:15 0.18 0.27 0.29 6/171 27763
08-11-19 14:16 0.65 0.41 0.34 5/171 13019
08-11-19 14:17 0.24 0.34 0.31 7/176 13109
08-11-19 14:18 0.09 0.27 0.29 5/171 13155
08-11-19 14:19 0.46 0.37 0.32 4/169 30800
08-11-19 14:20 0.21 0.31 0.30 5/171 30852
08-11-19 14:21 0.12 0.27 0.28 6/171 30937
08-11-19 14:22 0.52 0.38 0.32 4/167 16174
08-11-19 14:23 0.25 0.32 0.30 4/167 16225
08-11-19 14:24 0.09 0.26 0.28 9/180 16293

08-11-19 14:25 0.47 0.36 0.31 4/175 1505
08-11-19 14:26 0.20 0.30 0.29 4/167 1550
08-11-19 14:27 0.07 0.25 0.27 5/172 1607
08-11-19 14:28 0.73 0.42 0.33 6/169 19351
08-11-19 14:29 0.87 0.55 0.37 4/143
...

read more »


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Jean-Paul Calderone  
View profile  
 More options Jan 23 2009, 8:34 am
Newsgroups: comp.lang.python
From: Jean-Paul Calderone <exar...@divmod.com>
Date: Fri, 23 Jan 2009 08:34:18 -0500
Local: Fri, Jan 23 2009 8:34 am
Subject: Re: seeking to improve Python skills

You should have a docstring here.  It should describe the overall purpose
of the MovingAvg class and it should probably document the meaning of each
attribute instances of the class have.

>         def __init__(self, fname):
>                 try:
>                         self.fo = open(fname)
>                 except IOError, e:
>                         print "Problem with opening file:", e
>                         sys.exit(4)

This isn't very good.  Your MovingAvg class is otherwise relatively general-
purpose and re-usable, but this makes it unusable instead.  You shouldn't
use print to report errors in general code and you shouldn't turn specific
exceptions into SystemExit.  This kind of whole-program error handling
belongs in a different layer if your code.  Your moving average code should
just focus on computing a moving average.

Also, filenames are rather clunky.  Another improvement here would be to
pass in a file object which the calling code has already opened.  Or, better
still, just pass in an iterator of data.  Do the file handling and the
parsing in a different layer.  Then you'll be able to re-use your moving
average class with data files in a different format - all you'll have to do
is write another parser for the new format.

>                 self.reslist = []
>                 self.smalist = []
>                 self.maxval = 0

>         def extrfromfile(self):

There should be a docstring here describing what this method does.

>                 vre = re.compile("(\d+-\d+-\d+) (\d\d:\d\d) (\d+\.\d+)")
>                 for line in self.fo:
>                         res = vre.search(line)
>                         if res:
>                                 self.reslist.append({'day':res.group(1),\
>                                 'time':res.group(2),\
>                                 'val':float(res.group(3))})

The trailing backslashes on the previous lines are superfluous.  The code
is just as valid without them.

>         def calc_sma(self, smalen=4):

Another missing docstring.  Make sure you also document the meaning of the
parameter the method accepts.

>                 if smalen == 0:
>                         raise AssertionError, "Moving Average sample length
>cannot be 0"
>                 if not isinstance(smalen, int):
>                         raise AssertionError, "Moving Average sample length
>has to be integer"

The conventional way to write the previous lines would be:

    assert smallen != 0, "Moving Average sample length cannot be 0"
    assert isinstance(smallen, int), "Moving Average Sample length has to be integer"

However, I would just leave them out.  If you document the meaning of the
smalen parameter, then callers will know it can't be 0 and must be an int.

>                 total = 0

Superfluous line above.

>                 total = sum( [ x['val'] for x in self.reslist[0:smalen] ] )
>                 sma = total / smalen
>                 smaidx = int(smalen/2)
>                 self.smalist.append((self.reslist[0]['day'],\
>                         self.reslist[0]['time'],\
>                         self.reslist[0]['val'],\
>                         self.reslist[0]['val']))

Superfluous backslashes again.

>                 for i in range(smalen, len(self.reslist)):
>                         curval = self.reslist[i]['val']
>                         self.maxval = max(self.maxval, curval)
>                         total += curval
>                         total -= self.reslist[i - smalen]['val']
>                         sma = total / smalen
>                         smaidx += 1
>                         self.smalist.append((self.reslist[smaidx]['day'],\
>                                 self.reslist[smaidx]['time'],\
>                                 self.reslist[smaidx]['val'],\
>                                 sma))

And again.

>         def return_results(self):

Missing docstring.  

>                 return (self.reslist, self.smalist, self.maxval)

Generally, I wonder whether MovingAvg should just be a function rather
than a class.  The only place it maintains state it does so confusingly.
I would just make the input data a parameter to calc_sma and have it return
the results it computes.  Drop the rest of the class and make calc_sma a free
function.

>class GnuplotWrapper(object):

Docstring.

>         def __init__(self, smalist, maxval, outfname = "calc.png",
>graphlen=640, graphheight=480, gnuplot = '/usr/bin/gnuplot'):

Again, the comment about filenames.  You could just make outfname a file-like
object and skip the naming.

>                 self.outfname = outfname
>                 self.smalist = smalist
>                 self.gnuplot = gnuplot
>                 self.gprog = None
>                 self.gdata = None
>                 self.graphlen = graphlen
>                 self.graphheight = graphheight

>         def _writefiles(self):

Docstring.

Superfluous backslash.

>                 self.gdata[1], self.gdata[1]) )
>                 self.gprogfile.close()
>                 for elem in self.smalist:
>                         self.gdatafile.write("%f, %f\n" % (elem[2],
>elem[3]))
>                 self.gdatafile.close()

>         def plot(self):

Docstring.

>                 self._writefiles()
>                 gplot = subprocess.Popen(self.gnuplot + " " +
>self.gprog[1],\
>                         shell=True, stdout=subprocess.PIPE,
>stderr=subprocess.PIPE)

You should *avoid* using shell=True with subprocess.Popen.  There's no
reason to use it here, as far as I can tell.

>                 print "Plotting data (%s)..." % self.outfname
>                 so, se = gplot.communicate()
>                 if se:
>                         print "Gnuplot problem output:", se
>                 os.remove(self.gprog[1])
>                 os.remove(self.gdata[1])

Reporting the gnuplot failure with print is not the best thing.  Reporting
errors to users should be done at a separate layer.  This is your gnuplot
wrapper - its job is to wrap gnuplot, not to talk to the user.  If there's
a problem, make it available via some documented API (for example, the plot
method might raise an exception if there is a gnuplot problem).  Handle the
exception at a higher level in your application where you know it's correct
to print things for the user to read.

>if __name__ == "__main__":
>         try:
>                 fname = sys.argv[1]
>         except IndexError:
>                 print "Specify filename with data as first argument."
>                 sys.exit(1)
>         except Exception, e:
>                 print "Error:", e
>                 sys.exit(2)

What is the second exception handler doing?  There is no expected other
exception from the code being protected, so you should just get rid of
this handler.  If, through some crazy accident, another exception gets
raised, Python will take care of reporting it to the user, and it will
do so with far more information - information that will make your job of
debugging the problem vastly easier.

>         values = MovingAvg(fname)
>         values.extrfromfile()
>         values.calc_sma(smalen = 10)
>         (reslist, smalist, maxval) = values.return_results()
>         gp = GnuplotWrapper(smalist, maxval)
>         gp.plot()

The most significant thing missing from this code is unit tests.  Developing
automated tests for your code will help you learn a lot.

Jean-Paul


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
mk  
View profile  
 More options Jan 23 2009, 10:57 am
Newsgroups: comp.lang.python
From: mk <mrk...@gmail.com>
Date: Fri, 23 Jan 2009 16:57:16 +0100
Local: Fri, Jan 23 2009 10:57 am
Subject: Re: seeking to improve Python skills
Jean-Paul Calderone wrote:

<snip>

> The most significant thing missing from this code is unit tests.  
> Developing automated tests for your code will help you learn a lot.

Thanks for all the remarks, I'll restructure my code. Probably the
biggest mistake was not keeping "moving average" class and others
focused on its respective jobs only.

However, unit tests are a tougher cookie, do you have any resource
that's truly worth recommending for learning unit tests? The only
resource I found that was talking at some length about it was "Dive into
Python" and I was wondering if there's anything better out there...

Regards,
mk


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Jean-Paul Calderone  
View profile  
 More options Jan 23 2009, 11:09 am
Newsgroups: comp.lang.python
From: Jean-Paul Calderone <exar...@divmod.com>
Date: Fri, 23 Jan 2009 11:09:08 -0500
Local: Fri, Jan 23 2009 11:09 am
Subject: Re: seeking to improve Python skills

On Fri, 23 Jan 2009 16:57:16 +0100, mk <mrk...@gmail.com> wrote:
>Jean-Paul Calderone wrote:
><snip>
>>The most significant thing missing from this code is unit tests.
>>Developing automated tests for your code will help you learn a lot.

>Thanks for all the remarks, I'll restructure my code. Probably the biggest
>mistake was not keeping "moving average" class and others focused on its
>respective jobs only.

>However, unit tests are a tougher cookie, do you have any resource that's
>truly worth recommending for learning unit tests? The only resource I found
>that was talking at some length about it was "Dive into Python" and I was
>wondering if there's anything better out there...

I haven't read it, but a skilled colleague of mine recommends
<http://www.amazon.com/xUnit-Test-Patterns-Refactoring-Addison-Wesley/...>.

Jean-Paul


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Scott David Daniels  
View profile  
 More options Jan 23 2009, 3:47 pm
Newsgroups: comp.lang.python
From: Scott David Daniels <Scott.Dani...@Acm.Org>
Date: Fri, 23 Jan 2009 12:47:00 -0800
Subject: Re: seeking to improve Python skills

mk wrote:
> Jean-Paul Calderone wrote:
> <snip>
>> The most significant thing missing from this code is unit tests.  
>> Developing automated tests for your code will help you learn a lot.

> However, unit tests are a tougher cookie, do you have any resource
> that's truly worth recommending for learning unit tests? The only
> resource I found that was talking at some length about it was "Dive into
> Python" and I was wondering if there's anything better out there...

Do the "Dive In" thing.  You'll quickly develop instincts.
Start with the simplest possible test of your function,
run it, and fix your code until it passes.  Add another test,
and loop.  The simplest possible test will unfortunately need
a bit of bolerplate, but adding tests is easy.

to start:

     import unittest
     import moving_average as ma

     class MovingAverageTest(unittest.TestCase):
         def test_simplest(self):
             'Check the mechanics of getting a simple result'
             self.assertEqual(ma.moving_average(3, []), [])

     if __name__ == '__main__':
         unittest.main()

Once that works, add another test:
         def test_simple(self):
             self.assertAlmostEqual(ma.moving_average(3, [1, 2, 3]), [2])

Once that works, check something a bit easier to get wrong:
         def test_floating(self):
             'Check we have reasonable results'
             self.assertAlmostEqual(ma.moving_average(3, [1, 1, 3])[0],
                                    1.6666667)

and, as they so often say, "lather, rinse, repeat."

--Scott David Daniels
Scott.Dani...@Acm.Org


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Terry Reedy  
View profile  
 More options Jan 23 2009, 5:26 pm
Newsgroups: comp.lang.python
From: Terry Reedy <tjre...@udel.edu>
Date: Fri, 23 Jan 2009 17:26:09 -0500
Local: Fri, Jan 23 2009 5:26 pm
Subject: Re: seeking to improve Python skills

mk wrote:
> Jean-Paul Calderone wrote:
> <snip>
>> The most significant thing missing from this code is unit tests.  
>> Developing automated tests for your code will help you learn a lot.

> Thanks for all the remarks, I'll restructure my code. Probably the
> biggest mistake was not keeping "moving average" class and others
> focused on its respective jobs only.

I would consider writing the moving-average 'function' as a generator
function.  First version takes a sequence and window size as inputs.
Second, slightly more difficult, takes an iterator and window size as
inputs.  An exponentially-weighted average generator would, of course,
take an iterator and weight as input.

 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Aahz  
View profile  
 More options Jan 23 2009, 11:34 pm
Newsgroups: comp.lang.python
From: a...@pythoncraft.com (Aahz)
Date: 23 Jan 2009 20:34:04 -0800
Local: Fri, Jan 23 2009 11:34 pm
Subject: Re: seeking to improve Python skills
In article <mailman.7816.1232726406.3487.python-l...@python.org>,

mk  <mrk...@gmail.com> wrote:

>However, unit tests are a tougher cookie, do you have any resource
>that's truly worth recommending for learning unit tests?

Start with the doctest module.
--
Aahz (a...@pythoncraft.com)           <*>         http://www.pythoncraft.com/

Weinberg's Second Law: If builders built buildings the way programmers wrote
programs, then the first woodpecker that came along would destroy civilization.


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
End of messages
« Back to Discussions « Newer topic     Older topic »