Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #7095
| From | Terry Reedy <tjreedy@udel.edu> |
|---|---|
| Subject | Re: Lambda question |
| Date | 2011-06-06 12:52 -0400 |
| References | <20110606134215.3EYA9.180297.root@cdptpa-web25-z02> |
| Newsgroups | comp.lang.python |
| Message-ID | <mailman.2494.1307379170.9059.python-list@python.org> (permalink) |
On 6/6/2011 9:42 AM, jyoung79@kc.rr.com wrote:
>>>>>> f = lambda x, n, acc=[]: f(x[n:], n, acc+[(x[:n])]) if x else acc
>
>> Packing tail recursion into one line is bad for both understanding and
>> refactoring. Use better names and a docstring gives
>>
>> def group(seq, n):
>> 'Yield from seq successive disjoint slices of length n plus the
>> remainder'
>> for i in range(0,len(seq), n):
>> yield seq[i:i+n]
[I added back the last 'n' that got deleted somehow]
> Thank you all very much for this incredible help! The original code
> now makes sense, and I was thrilled to see better and more efficient
> ways of doing this. Thanks for taking the time to share your
> thoughts as well as the excellent detail everyone shared… I really
> appreciate it!
You are welcome.
Let me add something not said much here about designing functions: start
with both a clear and succinct definition *and* test cases. (I only
started writing tests first a year ago or so.) Test cases help test the
definition statement as well as the yet-to-be-written code. They also
make re-factoring much safer. I think test cases should start with null
inputs. For this function:
for inn,out in (
(('',1), []), # no input, no output
(('abc',0), []), # definition unclear, could be error
(('abc',1), ['a','b','c']),
(('abcd',2), ['ab','cd']),
(('abcde',2), ['ab', 'cd', 'e']), # could change this
):
assert list(group(*inn)) == out, (inn,out)
This fails with
ValueError: range() arg 3 must not be zero
I will let you think about and try out what the original code 'f=../
does with n=0. It is not good. A third problem with lambda expressions
is no test for bad inputs. They were added to Python for situations
where one needs a function as an argument and and the return expression
is self-explanatory, clearly correct, and safe for any inputs it could
get in the context it is passed into. For example, lambda x: 2*x.
This works:
def group(seq, n):
'Yield from seq successive disjoint slices of length n & the remainder'
if n<=0: raise ValueError('group size must be positive')
for i in range(0,len(seq), n):
yield seq[i:i+n]
for inn,out in (
(('',1), []), # no input, no output
#(('abc',0), ValueError), # group size positive
(('abc',1), ['a','b','c']),
(('abcd',2), ['ab','cd']),
(('abcde',2), ['ab', 'cd', 'e']), # could change this
):
assert list(group(*inn)) == out, (inn,out)
I have written a function test function that I will post or upload to
PyPI sometime. It accepts i/o pairs with error 'outputs', like the one
commented out above.
--
Terry Jan Reedy
Back to comp.lang.python | Previous | Next — Next in thread | Find similar | Unroll thread
Re: Lambda question Terry Reedy <tjreedy@udel.edu> - 2011-06-06 12:52 -0400
Re: Lambda question Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-06-06 23:16 +0000
API design before implementation (was: Lambda question) Ben Finney <ben+python@benfinney.id.au> - 2011-06-07 09:54 +1000
Re: Lambda question harrismh777 <harrismh777@charter.net> - 2011-06-06 19:00 -0500
csiph-web