[Numpy-discussion] logical priority
Fernando Perez
Fernando.Perez at colorado.edu
Tue Feb 8 17:14:29 EST 2005
Stephen Walton wrote:
> Fernando Perez wrote:
>
>
>>Travis Oliphant wrote:
>>
>>
>>>Currently, I don't think Python allows "over-riding" the "and" operation.
>>
>>
>>You are correct:
>
>
> What I want must be possible somehow, though:
>
> In [6]: a=[True,False]
>
> In [7]: b=[False,False]
>
> In [8]: a and b
> Out[8]: [False, False]
>
> In [9]: a or b
> Out[9]: [True, False]
>
> In [10]: not a
> Out[10]: False
>
> So, standard Python does apply logical "and" and "or", but not "not",
> element by element to a list or tuple of booleans. Is there no way to
> get access to this for a numarray bool array? Can we get Guido to
> change "not" to also operate element-wise on a list of booleans?
I think you are misunderstanding something. Python does not "apply logical
"and" and "or", but not "not", element by element to a list or tuple of
booleans", as you say. Look again at the decompiled bytecode:
In [2]: dis.dis(compile('a and b','<>','eval'))
0 0 LOAD_NAME 0 (a)
3 JUMP_IF_FALSE 4 (to 10)
6 POP_TOP
7 LOAD_NAME 1 (b)
>> 10 RETURN_VALUE
What it does is execute the JUMP_IF_FALSE bytecode, which is mapped to the
__nonzero__ special method. From http://docs.python.org/ref/customization.html:
__nonzero__( self)
Called to implement truth value testing, and the built-in operation
bool(); should return False or True, or their integer equivalents 0 or 1. When
this method is not defined, __len__() is called, if it is defined (see below).
If a class defines neither __len__() nor __nonzero__(), all its instances are
considered true.
Now, lists don't actually have this method, so a call to __len__ is made, and
any non-empty list is considered true. The return value is then whatever is
on the stack, which will be either be a, or b if a tested false:
In [6]: a
Out[6]: [True, False]
In [7]: a and 0
Out[7]: 0
In [8]: a and 1
Out[8]: 1
In [9]: a and 'hello'
Out[9]: 'hello'
The point is that and/or only operate on one operand at a time, with unary
functions/methods. They do NOT call a binary function, the way & does:
In [5]: dis.dis(compile('a & b','<>','eval'))
0 0 LOAD_NAME 0 (a)
3 LOAD_NAME 1 (b)
6 BINARY_AND
7 RETURN_VALUE
This means that certain things which can be done with & are fundamentally
impossible with 'and', since you never have both arguments in your hands at
the same time.
Bytecode analysis can be really useful to understand this kind of subtle
issues. I can't think of any language where this approach is as easy to do
and friendly as in python.
Cheers,
f
More information about the NumPy-Discussion
mailing list