[Tutor] check for nested sequences & flatten [and/or special forms]

Danny Yoo dyoo@hkn.eecs.berkeley.edu
Thu, 14 Feb 2002 10:35:21 -0800 (PST)


On Thu, 14 Feb 2002, Remco Gerlich wrote:

> > Here's a function that checks to see if a certain condition is true
> > anywhere in the list:
> > 
> > ###
> > def any(condition_function, seq):
> >     """Returns 1 if any element in our sequence 'seq'
> >     responds favorably to our 'condition_function'."""
> >     for element in seq:
> >         if condition_function(element):
> >             return 1
> >     return 0
> > ###
> 
> If we're addicted, surely then this should read
> 
> any = lambda condition, seq: reduce(lambda a,b: a or b, map(condition, seq))
> 
> :)

Noooooo!  *grin*  Ok, I'm chastised.



> (and why isn't the 'or' operator in the operator module?)

Ah!  This is a tricky one: 'or' and 'and' behave in a particularly special
way.  Let's say that we try defining our own version of 'and' as a
function:

###
>>> def myand(a, b): return a and b
... 
###


In many cases, it will appear to do the right thing... but what about
something like this?

###
>>> 0 and 1/0
0
>>> myand(0, 1/0)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
ZeroDivisionError: integer division or modulo by zero
###


What's particularly special about 'and' and 'or' is that they
automagically short-circuit --- when we do something like:

    0 and y

Python doesn't even need to look at 'y', since it knows that it's just
useless to proceed.  By the same short-circuiting logic:

    1 or y

just doesn't even try to evaluate y, since it sees a true value.


The reason that 'myand(0, 1/0)' breaks is because, when we do function
calls, Python needs to know what all the argument values are, so 'myand'
doesn't have the ability to short-circuit.  This is probably why they're
not in the operator module, because there's no mechanism available for
them to work as functions.


Hope that made some sort of sense!