This is a companion exercise to my earlier articles:
I'll be using exactly the same logic as in those two, just working within Python's constraints. I freely admit to not knowing Python from a bar of soap - indeed this is the third bit of Python I have ever written - so I would not vouch for this being anything other than a comparison to the other two pieces of code, and not a demonstration of what a Python dev might consider "good code". This is not a Python tutorial.
As a comparison for my - mostly CFML-oriented - base readership, here's the earlier CFML version again:
// getSubseries.cfm
function getSubseries(series, threshold){
var working = []
return series.reduce(function(reduction, current){
working.append(current)
while (working.sum() > threshold){
working.deleteAt(1)
}
var workingIsBetterForLength = working.len() > reduction.len()
var workingIsBetterForTotal = working.len() == reduction.len() && working.sum() > reduction.sum()
return (workingIsBetterForLength || workingIsBetterForTotal) ? duplicate(working) : reduction
}, [])
}
I just have a wrapper for a call to
reduce()
, which does all the work.Here's the Python version (/logical equivalent) I came up with:
# getSubseries.py
def getSubseries(series,threshold):
import functools
working = []
def reduceCallback(reduction, current):
working.append(current)
while sum(working) > threshold:
working.pop(0)
workingIsBetterForLength= len(working) > len(reduction)
workingIsBetterForTotal = len(working) == len(reduction) and sum(working) > sum(reduction)
return list(working) if workingIsBetterForLength or workingIsBetterForTotal else reduction
return functools.reduce(reduceCallback, series, [])
Some notes:
- I need to import the functools library for the
reduce()
function. In Python 2, there was a built-inreduce()
function, but in Python 3 it's been removed, instead pushed out into a library. It's a pity it's not a method of the List class. - As far as I can tell there is no way to do an inline function expression in Python. There are lambda expressions, but they're pretty useless compared to what CFML (etc) can do inline. This means I need to declare a function, then use that as a callback. This seems really clumsy to me.
- The best way to duplicate the working list is to construct a new one with the List constructor. This makes sense.
- Python doesn't have the short-hand ternary operator (
?:
), but does have this long-winded way of doing it. I guess the idea is it's slightly more readable for a person who has never encountered the construct before, but I dunno whether this is actually true. I also don't know a language should be specifically catering to first-time readers. - As Ryan pointed out in a comment to y/day's article, Python does have methods for
len()
etc, but the implementation is a bit shit (that's my assessment, not his). Python allows for implementation of a__len__()
method, which thelen()
function will call. This is getting things arse-backwards if you ask me. - I don't think the "meaningful whitespace" does actually improve code readability. In fact I think it reduces it. This is perhaps my untrained eye looking for block-like constructs where I'm not going to find them.
That was a bit short, but I need to crack on with my day job now.
--
Adam