Lisp mentality vs. Python mentality

Arnaud Delobelle arnodel at googlemail.com
Sun Apr 26 10:05:25 CEST 2009


namekuseijin <namekuseijin.nospam at gmail.com> writes:

> Ciprian Dorin, Craciun wrote:
>> On Sun, Apr 26, 2009 at 7:54 AM, Steven D'Aprano
>> <steve at remove-this-cybersource.com.au> wrote:
>>     I liked very much your implementation for the compare function, it
>> is very short and at the same time readable:
>>
>>> def compare(a, b, comp=operator.eq):
>>>     return (len(a) == len(b)) and all(comp(*t) for t in zip(a, b))
>>
>>     But I have only one problem, it is suboptimal, in the sense that:
>>     * it constructs two intermediary lists (the list comprehension and
>> the zip call);

No, it only constructs one list (the zip() one) and only in Python 2.x -
in Python 3.x, zip return a special 'zip object'.  There is no list
comprehension.  It's a generator expression [1].

To avoid the list created by zip in python 2.x (for x large enough!),
just do:

from itertools import izip as zip

Another way to define the function that may appeal to you, as a lisper.

def compare(a, b, comp=operator.eq):
    return len(a) == len(b) and all(map(comp, a, b))

The same remark applies to map() here as to zip() above.

>
>>     * it evaluates all the elements, even if one is false at the beginning;

It does not [2].

> This evaluates just until finding one that is false:
>
>      return (len(a) == len(b)) and not any(not comp(*t) for t in
> (zip(a, b)))
>
> plus the zip call enclosed in parentheses got turned into an iterator.

not any(not i for i in iterable) is not an optimisation of
all(iterable).  Refer to [2].  Moreover, putting a list in parenthesis
does not magically turn it into a generator.

-- 
Arnaud

[1] http://www.python.org/dev/peps/pep-0289/
[2] http://docs.python.org/library/functions.html



More information about the Python-list mailing list