[False,True] and [True,True] --> [True, True]?????

B

bdb112

Is there any obvious reason why
[False,True] and [True,True]
gives [True, True]

Python 2.5.2 (r252:60911, Feb 21 2008, 13:11:45) [MSC v.1310 32 bit
(Intel)]
 
A

Andre Engels

Is there any obvious reason why
[False,True] and [True,True]
gives [True, True]

Well, whether the reason is obvious, I do not know, but the way and
seems to be implemented is:

X and Y =
* X if the boolean value of X is false
* Y if the boolean value of X is true

In this case, bool([False,True]) = true, so the second element is taken.
 
A

AggieDan04

Is there any obvious reason why
[False,True] and [True,True]
gives [True, True]

Python 2.5.2 (r252:60911, Feb 21 2008, 13:11:45) [MSC v.1310 32 bit
(Intel)]

X and Y == (Y if X else X)
X or Y == (X if X else Y)

[False, True] is true, so the and operator returns the second argument.
 
G

Gabriel Genellina

Is there any obvious reason why
[False,True] and [True,True]
gives [True, True]

Yes: short-circuit evaluation.
[False,True] and [True,True] is *not* an element-by-element operation,
it's a simple expression involving two objects (two lists).
A and B means: check the boolean value of A; if it's false, return A.
Else, return B.
A non-empty list has a boolean value of true, so the second list is
returned.

If you want an element-wise operation:
A = [False,True]
B = [True,True]
result = [a and b for a,b in zip(A,B)]
 
B

bdb112

THanks Gabriel,
Now I know about the zip function.

Your explanation of Boolean ops on lists was clear.
It leads to some intriguing results:

bool([False])
--> True

I wonder if python 3 changes any of this?
 
P

Peter Otten

bdb112 said:
Your explanation of Boolean ops on lists was clear.
It leads to some intriguing results:

bool([False])
--> True

I wonder if python 3 changes any of this?

No. Tests like

if items:
...

to verify that items is a non-empty list are a widespread idiom in Python.
They rely on the behaviour you observe.

Peter
 
G

Gerhard Häring

Peter said:
bdb112 said:
Your explanation of Boolean ops on lists was clear.
It leads to some intriguing results:

bool([False])
--> True

I wonder if python 3 changes any of this?

No. Tests like

if items:
...

to verify that items is a non-empty list are a widespread idiom in Python.
They rely on the behaviour you observe.

Are they widespread? I haven't noticed, yet.

I prefer to write it explicitly:

if len(lst) > 0:
...

if item is None:
...

etc.

-- Gerhard
 
C

Chris Rebert

Peter said:
bdb112 said:
Your explanation of Boolean ops on lists was clear.
It leads to some intriguing results:

bool([False])
--> True

I wonder if python 3 changes any of this?

No. Tests like

if items:
   ...

to verify that items is a non-empty list are a widespread idiom in Python.
They rely on the behaviour you observe.

Are they widespread? I haven't noticed, yet.

I prefer to write it explicitly:

if len(lst) > 0:

Nope, that's not idiomatic. The simpler `if lst:` version is indeed widespread.
   ...

if item is None:

That's pretty common and accepted; comparison to None is something of
a special case.

Cheers,
Chris
 
P

Peter Otten

Gerhard said:
Peter said:
bdb112 said:
Your explanation of Boolean ops on lists was clear.
It leads to some intriguing results:

bool([False])
--> True

I wonder if python 3 changes any of this?

No. Tests like

if items:
...

to verify that items is a non-empty list are a widespread idiom in
Python. They rely on the behaviour you observe.

Are they widespread? I haven't noticed, yet.

That is my impression.
I prefer to write it explicitly:

if len(lst) > 0:
...

Using google codesearch I get

matches search expression
ca. 1000 lang:python "if items:"
216 lang:python "if len(items) > 0:"

This could of course mean that "people who like 'items' as a list name also
like the 'if items:...' idiom" or "'items' is a popular name for boolean
values" or "the search result is spammed by a gazillion zope versions"...

Peter
 
S

Steven D'Aprano

Peter said:
bdb112 said:
Your explanation of Boolean ops on lists was clear. It leads to some
intriguing results:

bool([False])
--> True

I wonder if python 3 changes any of this?

No. Tests like

if items:
...

to verify that items is a non-empty list are a widespread idiom in
Python. They rely on the behaviour you observe.

Are they widespread? I haven't noticed, yet.

I prefer to write it explicitly:

if len(lst) > 0:


Do you also count the length of a list explicitly?

n = 0
for item in lst:
n += 1
if n > 0:
...

No? Of course you don't. You understand that lists know how to calculate
their own length, and you just ask the list for its length. Great.

Well, lists also know whether or not they are empty, without needing to
concern yourself with the definition of "empty".

if lst:
# not empty
else:
# empty


All Python objects have an understanding of "empty" or "not empty", and
the only time I've seen it cause problems is with iterators, because you
can't tell if an iterator is empty until you actually try to access a
value.


if item is None:
...

That's a completely different test. That's testing whether item is the
specific singleton None. It is very different from testing bool(item).
 
P

Peter Pearson

Do you also count the length of a list explicitly?

n = 0
for item in lst:
n += 1
if n > 0:
...

No? Of course you don't. You understand that lists know how to calculate
their own length, and you just ask the list for its length. Great.

Well, lists also know whether or not they are empty, without needing to
concern yourself with the definition of "empty".

if lst:
# not empty
else:
# empty

All Python objects have an understanding of "empty" or "not empty", and
the only time I've seen it cause problems is with iterators, because you
can't tell if an iterator is empty until you actually try to access a
value.

Like Gerhard, I prefer the construction that explicitly
says, "This is a list, and this is what I'll do if it's not
empty." To me, and I suspect to a great many programmers,
"if x:" does *not* mean "if x is not empty", it means "if
x is (in some sense) True, including the possibility that
x is an object from which a True or False value must be
extracted by means that might not be at all obvious." For
an object lesson in the perils of said extraction, see the
recent thread on [False,True] and [True,True] == [True,True].

People much smarter than me will no doubt rush to point out
that if I were alert, I would know from the context that x
is a list, and if I were thoroughly familiar with Python, I
would know that when x is a list, "if x:" means not empty.
True, but this is all the brain I got, so when I come back
in two months, pathetically disoriented, to peer at this
line of code through my senescent blear, I hope I'll see,
"This, Peter, is a list, and this is what I'll do . . ."

The "not empty" interpretation is a cute shortcut. But
somebody's gotta put up some resistance to cute shortcuts,
or we'll find ourselves back with Perl.
 
P

Paul Rubin

Peter Pearson said:
The "not empty" interpretation is a cute shortcut. But
somebody's gotta put up some resistance to cute shortcuts,
or we'll find ourselves back with Perl.

+ QOTW
 
M

Martin v. Löwis

Are they widespread? I haven't noticed, yet.
I prefer to write it explicitly:

if len(lst) > 0:

I prefer to test explicitly for the truth value of the
list. I don't want to test whether the length of the list
is greater than 0 (in fact, I don't care about the length
property of the list at all) - I want to know whether the
list is empty (or not empty). The Python syntax for this
test is

if lst:
# not empty

or

if not list:
#empty

The view "let me test for the precise value" leads to
formulations like

if foo is True:
return True
else:
return False

People should have more trust in boolean conversions.

Regards,
Martin
 
A

Aahz

I prefer to write it explicitly:

if len(lst) > 0:
...

At the very least, IMO you should write this as

if len(lst):
...

There's no reason to be explicit about the numeric comparison.
 
M

Martin v. Löwis

I don't want to test whether the length of the list
is greater than 0 [...] - I want to know whether the
list is empty (or not empty).

I fail to see the difference between "length greater than 0"
and "list is not empty". They are, by definition, the same
thing, aren't they?

Yes, they test the same property, and so would

for x in foo: # foo is empty if it does not have any elements
# not empty
break
else:
# empty

People also write, as a test for empty lists,

if foo == []: # foo is empty when it is equal to the empty list
# empty

if foo != []:
# not empty

Yet another equivalent test would be

try:
foo[0] # foo is empty if it does not have a zeroeth element
except IndexError:
# empty
else:
# not empty

They are *not* the same thing, by definition, as they work
in different ways. They just yield the same result.

There are many equivalent ways to spell this property; some
are more direct than others. I find that referring to the
boolean-ness of a list is the most direct way to test whether
a list is empty - just as testing for the boolean-ness of
an integer is the most direct way to test whether it is 0.

Regards,
Martin
 
M

Martin v. Löwis

I prefer to write it explicitly:
At the very least, IMO you should write this as

if len(lst):
...

There's no reason to be explicit about the numeric comparison.

I think in the mind-set that dislikes relying on boolean conversion
of lists, relying on boolean conversion of numbers is just as evil.
In this mindset (IIUC), you *have* to have an expression that is
either True or False in a boolean test (if and while).

Regards,
Martin
 
G

Gerhard Häring

Martin said:
Are they widespread? I haven't noticed, yet.

I prefer to write it explicitly:

if len(lst) > 0:

I prefer to test explicitly for the truth value of the
list. I don't want to test whether the length of the list
is greater than 0 (in fact, I don't care about the length
property of the list at all) - I want to know whether the
list is empty (or not empty). The Python syntax for this
test is

if lst:
# not empty

or

if not list:
#empty
[...]

You're right - as most of the time ;-) This makes a lot of sense to me.

The reason I preferred len(), btw., was only that len() make it clear
that the argument is a sequence.

Maybe I was just too annoyed by lots of Python code I read that looked
like this:

def foo(x, y, z):
if x:
...
else:
...

with poorly named variables where I didn't know what the heck the
variables are (bool, list, instance, ...). I hate it when I have to look
for the actual method calls to figure out what's going in. Better
variable naming and small comments would often help.

-- Gerhard
 
T

Terry Reedy

Gerhard said:
Martin said:
Are they widespread? I haven't noticed, yet.

I prefer to write it explicitly:

if len(lst) > 0:
I prefer to test explicitly for the truth value of the
list. I don't want to test whether the length of the list
is greater than 0 (in fact, I don't care about the length
property of the list at all) - I want to know whether the
list is empty (or not empty). The Python syntax for this
test is

if lst:
# not empty

or

if not list:
#empty
[...]

You're right - as most of the time ;-) This makes a lot of sense to me.

The reason I preferred len(), btw., was only that len() make it clear
that the argument is a sequence.

Maybe I was just too annoyed by lots of Python code I read that looked
like this:

def foo(x, y, z):
if x:
...
else:
...

with poorly named variables where I didn't know what the heck the
variables are (bool, list, instance, ...). I hate it when I have to look
for the actual method calls to figure out what's going in. Better
variable naming and small comments would often help.

In my view, that is only excusable in throw-away private code or in
languages like early BASIC where only one letter is allowed, and even
then, 'x' should be a number, not a collection.
 
S

Steven D'Aprano

I fail to see the difference between "length greater than 0" and "list
is not empty". They are, by definition, the same thing, aren't they?

For built-in lists, but not necessarily for arbitrary list-like sequences.

There's also the performance issue. I might have a sequence-like
structure where calling len() takes O(N**2) time, (say, a graph) but
calling __nozero__ might be O(1). Why defeat the class designer's
optimizations?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top