Lisp mentality vs. Python mentality

bearophileHUGS at lycos.com bearophileHUGS at lycos.com
Sun Apr 26 08:07:25 EDT 2009


Paul Rubin:
> Arnaud Delobelle:
> > Do you mean imap(comp, a, b)?
>
> Oh yes, I forgot you can do that.  Thanks.

That works and is nice and readable:


import operator
from itertools import imap

def equal_sequences(a, b, comp=operator.eq):
    """
    a and b must have __len__

    >>> equal_sequences([1, 2, 3], [1, 2, 3])
    True
    >>> L1, L2 = [1, 2, 3], [1, -2, 3]
    >>> equal_sequences(L1, L2)
    False
    >>> equal_sequences(L1, L2, lambda x,y: abs(x) == abs(y))
    True
    >>> L3, L4 = ["hello", "HALLO"], ["hello", "hallo"]
    >>> equal_sequences(L3, L4)
    False
    >>> equal_sequences(L3, L4, lambda x,y: x.lower() == y.lower())
    True
    """
    return len(a) == len(b) and all(imap(comp, a, b))


if __name__ == "__main__":
    import doctest
    doctest.testmod()
    print "Doctests finished.\n"



But both sequences must have a len. Otherwise you may use (if you
don't have izip_longest the folllowing code gets longer):


"""
>>> equal_items([1, 2], [1, 2, 3])
False
>>> equal_items([1, 2, 3], [1, 2, 3])
True
>>> equal_items([1, 2, 3], [1, -2, 3])
False
>>> equal_items([1, 2, 3], [1, -2, 3], abs)
True
>>> equal_items([1, 2, 3], [1, -2, 4], abs)
False
>>> L1, L2 = ["hello", "HALLO"], ["hello", "hallo"]
>>> equal_items(L1, L2)
False
>>> equal_items(L1, L2, str.lower)
True
>>> equal_items(xrange(3), (i for i in xrange(3)))
True
>>> equal_items([0, 1, 2], (i for i in xrange(3)))
True
>>> equal_items([0, 1, 2, 3], (i for i in xrange(3)))
False
>>> equal_items([-0, -1, -2], (i for i in xrange(3)), key=abs)
True
>>> equal_items([-0, -1, -2, -3], (i for i in xrange(3)), key=abs)
False
>>> x = []
>>> equal_items( (x for i in range(3)), (x for i in range(3)) )
True
>>> equal_items( (x for i in range(3)), (x for i in range(4)) )
False
>>> equal_items( (x for i in range(3)), (x for i in range(3)), key=id)
True
>>> equal_items( (x for i in range(3)), (x for i in range(4)), key=id)
False
>>> equal_items( (x for i in range(3)), (x for i in range(3)), key=lambda x:x)
True
>>> equal_items( (x for i in range(3)), (x for i in range(4)), key=lambda x:x)
False
"""

from itertools import izip_longest


def equal_items(iter1, iter2, key=None):
    try:
        len_iter1 = len(iter1)
        len_iter2 = len(iter2)
    except TypeError:
        pass
    else:
        if len_iter1 != len_iter2:
            return False

    class Guard(object): pass

    if key is None:
        for x, y in izip_longest(iter1, iter2, fillvalue=Guard()):
            if x != y:
                return False
    else:
        try:
            for x, y in izip_longest(iter1, iter2, fillvalue=Guard()):
                if key(x) != key(y):
                    return False
        except TypeError: # intercepts key(guard)
            return False

    return True


if __name__ == "__main__":
    import doctest
    doctest.testmod()
    print "Doctests finished.\n"

You can write hairy code in Python too, not just in CLisp :-)


Bye,
bearophile



More information about the Python-list mailing list