checking if a list is empty

J

Jabba Laci

Hi,

If I want to check if a list is empty, which is the more pythonic way?

li = []

(1) if len(li) == 0:
....
or
(2) if not li:
....

Thanks,

Laszlo
 
R

Richard Thomas

Hi,

If I want to check if a list is empty, which is the more pythonic way?

li = []

(1) if len(li) == 0:
...
or
(2) if not li:
...

Thanks,

Laszlo

I prefer (1), it feels more explicit about what I'm testing. The fact
that empty sequences evaluate as false feels like a bit of a quirk to
me. Actually the fact that 0 evaluates as false feels like a bit of a
quirk to me, I more of a "use booleans in boolean contexts" kind of
programmer.
 
S

scattered

Hi,

If I want to check if a list is empty, which is the more pythonic way?

li = []

(1) if len(li) == 0:
...
or
(2) if not li:
...

Thanks,

Laszlo

is there any problem with

(3) if li == []:

?

Seems to work when I test it and seems to clearly test what you are
trying to test. The only problem might be if in some contexts == has
the semantics of checking for object identity.
 
P

Philip Semanchuk

Hi,

If I want to check if a list is empty, which is the more pythonic way?

li = []

(1) if len(li) == 0:
...
or
(2) if not li:
...

Thanks,

Laszlo

is there any problem with

(3) if li == []:

?

What if it's not a list but a tuple or a numpy array? Often I just want to iterate through an element's items and I don't care if it's a list, set, etc. For instance, given this function definition --

def print_items(an_iterable):
if not an_iterable:
print "The iterable is empty"
else:
for item in an_iterable:
print item

I get the output I want with all of these calls:
print_items( list() )
print_items( tuple() )
print_items( set() )
print_items( numpy.array([]) )

Given this slightly different definition, only the first call gives me the output I expect:

def print_items(an_iterable):
if an_iterable == []:
print "The iterable is empty"
else:
for item in an_iterable:
print item


I find I use the the former style ("if not an_iterable") almost exclusively.


bye
Philip
 
I

Ian Kelly

What if it's not a list but a tuple or a numpy array? Often I just want to iterate through an element's items and I don't care if it's a list, set, etc. For instance, given this function definition --

def print_items(an_iterable):
   if not an_iterable:
       print "The iterable is empty"
   else:
       for item in an_iterable:
           print item

I get the output I want with all of these calls:
print_items( list() )
print_items( tuple() )
print_items( set() )
print_items( numpy.array([]) )

But sadly it fails on iterators:
print_items(xrange(0))
print_items(-x for x in [])
print_items({}.iteritems())
 
J

Jon Clements

What if it's not a list but a tuple or a numpy array? Often I just wantto iterate through an element's items and I don't care if it's a list, set, etc. For instance, given this function definition --
def print_items(an_iterable):
   if not an_iterable:
       print "The iterable is empty"
   else:
       for item in an_iterable:
           print item
I get the output I want with all of these calls:
print_items( list() )
print_items( tuple() )
print_items( set() )
print_items( numpy.array([]) )

But sadly it fails on iterators:
print_items(xrange(0))
print_items(-x for x in [])
print_items({}.iteritems())

My stab:

from itertools import chain

def print_it(iterable):
it = iter(iterable)
try:
head = next(it)
except StopIteration:
print 'Empty'
return
for el in chain( (head,), it ):
print el

Not sure if I'm truly happy with that though.

Jon
Jon.
 
S

Steven D'Aprano

is there any problem with

(3) if li == []:

?

Seems to work when I test it and seems to clearly test what you are
trying to test. The only problem might be if in some contexts == has the
semantics of checking for object identity.

Yes, if li == [] works too. But how do you know li is a list and not some
other sequence type?

The advantage of the "if x" test is that it is independent of the type of
x.
 
H

Hans Georg Schaathun

On 07 May 2011 02:51:50 GMT, Steven D'Aprano
: On Fri, 06 May 2011 14:57:21 -0700, scattered wrote:
:
: > is there any problem with
: >
: > (3) if li == []:
: >
: > ?
: >
: > Seems to work when I test it and seems to clearly test what you are
: > trying to test. The only problem might be if in some contexts == has the
: > semantics of checking for object identity.
:
: Yes, if li == [] works too. But how do you know li is a list and not some
: other sequence type?

It says so in the Subject header :)

: The advantage of the "if x" test is that it is independent of the type of
: x.

Sure, but the question wasn't ...

The problem with 'if x' is that it requires a much more detailed
understanding of python. li == [] is as explicit as it gets, and
leaves no room for doubt. len(li) == 0 is almost as explicit and
much more flexible. Just x is as generic as it gets, but depends
on python's convolved rules for duck processing and if you aim at
legibility it is better avoided.
 
S

Steven D'Aprano

The problem with 'if x' is that it requires a much more detailed
understanding of python.

"Much" more detailed? Hardly.

Understanding that Python accepts any and all objects in truth-testing
concepts, and the rules thereof, is Python 101 territory. It's beginner-
level knowledge. It is far less advanced than the knowledge that ** is
used for exponentiation. After all, many programmers have never needed to
raise a number to a power, and might not learn about it for years, but
every programmer writes if or while statements at some point.

Not knowing that you can write "if x" instead of "if x == []" is like not
knowing that you can write

elif condition

instead of

else:
if condition

If somebody were to argue that it is "better to write else if explicitly,
instead of the confusing elif", we'd all laugh at them.

Every time the question of conditional testing comes up here, it never
ceases to astonish me how many developers argue against learning the
idioms of the language, and prefer to re-use the idioms of other
languages in Python.

Python is an object-oriented language where objects get to decide for
themselves whether they should be treated as true or false. Writing:

if x == []:

instead of

if x:

merely[1] because you worry that it isn't explicit enough, or could
confuse other developers, or out of some nagging concern that maybe
Python will do the wrong thing[2] unless you hold its hand through the
process, is as silly as writing this:

count = 0
for item in x:
count += 1


instead of:

count = len(x)

(As silly, but not as verbose.)

I don't mean to insult anyone, but I've heard and read all the arguments
against Python's truth-testing, and they don't impress me in the
slightest. Most of them strike me as silly. The only argument that
carries any weight to me is one which I haven't seen anyone raise:

"if x:" turns something which arguably could have been a mistake ("oops,
I forgot to write the condition!") into valid code.





[1] It may be that there are good, solid reasons for writing explicit
len(x)==0 tests, although I'm hard-pressed to think of any. The closest I
come to is when you wish to emphasize "equal to some number that just
happens to be zero" rather than "it's a false/empty value". If so, you
get a free pass to write the test the long way. E.g. you might write
"x % 2 == 1" rather than just "x % 2" because you want to highlight that
the remainder equals one, rather than the remainder merely being a true
value.


[2] Of course, a custom object x might misbehave when you test it for
truth value. That would be a bug, just like it would be a bug if it
misbehaved when you call len(x) == 0. If you can't trust "if x" to work,
what makes you think you can trust "len(x) == 0" either?
 
R

Roy Smith

Hans Georg Schaathun said:
li == [] is as explicit as it gets, and
leaves no room for doubt.

I was about to write, "this fails if li is an instance of a subclass of
list", but then I tried it. I was astounded to discover that:

class MyList(list):
"I'm a subclass"

li = MyList()
print li == []
print [] == li

prints True, twice! I expected them both to be false. In fact, the
docs (http://tinyurl.com/3qga3lb) explicitly say:
If both are numbers, they are converted to a common type. Otherwise,
objects of different types always compare unequal

Since these are different types, i.e.

print type(li)
print type([])
print type(li) == type([])

prints

<class '__main__.MyList'>
<type 'list'>
False

I conclude that li == [] should have returned False. Either I'm not
understanding things correctly, or this is a bug.
 
S

Steven D'Aprano

Hans Georg Schaathun said:
li == [] is as explicit as it gets, and leaves no room for doubt.

I was about to write, "this fails if li is an instance of a subclass of
list", but then I tried it. I was astounded to discover that:

class MyList(list):
"I'm a subclass"

li = MyList()
print li == []
print [] == li

prints True, twice! I expected them both to be false. In fact, the
docs (http://tinyurl.com/3qga3lb) explicitly say:
If both are numbers, they are converted to a common type. Otherwise,
objects of different types always compare unequal

That should be understood as only applying for built-in types, not
arbitrary types. For arbitrary types, you can decide what counts as equal
by writing an __eq__ method, and you can do *anything*:

def __eq__(self, other):
if today() == "Tuesday": return True
else: ...


To understand the behaviour you are seeing, it helps to understand that
while li is a MyList, it is also a list:
True

It therefore inherits the same behaviour as list, unless you override or
overload it. Since you did neither, MyLists work just like lists, right
down to their __eq__ method.

It is normally considered The Right Thing To Do for subclasses to be
usable anywhere where a superclass was. That is, subclasses like MyList
should only *add* behaviour, never *subtract* it. Since:
True

applies, you should be able to replace list() with any subclass of list
and it should still work. (This is known as the Liskov Substitution
Principle, if you wish to google on it.)

This being Python, it's more of a guideline than a law, and you can
violate it if you choose, but you probably shouldn't unless you have good
reason. But if you want, just add a method:

def __eq__(self, other):
# untested
if type(self) is not type(other): return False
return super(self, MyList).__eq__(other)

to get the behaviour you are after.


So, not a bug, but a subtle point that isn't explained terribly well in
the docs.
 
H

Hans Georg Schaathun

On 11 May 2011 12:14:46 GMT, Steven D'Aprano
: Not knowing that you can write "if x" instead of "if x == []" is like not
: knowing that you can write
:
: elif condition
:
: instead of
:
: else:
: if condition

My concern was with the reader and not the writer.

What could elif mean other than else: if?

if x could, for instance, mean "if x is defined".
 
D

D'Arcy J.M. Cain

What could elif mean other than else: if?

If run by an elf? Who knows. You do, of course, if you have learned
the basics of the language you are using.
if x could, for instance, mean "if x is defined".

It could also mean "if x was created on a Tuesday." A short
introduction to the language explains what it actually means.

When did we come to the idea that people should be able to program in a
language without actually learning it? The fact that Python comes so
close to that possibility is nothing short of revolutionary. I suppose
one day a reasoning android will be able to sit down at the terminal of
a star ship computer and ask simple questions while making random hand
movements across a screen but for now I am afraid that programmers
still have to learn programming.
 
S

Steven D'Aprano

My concern was with the reader and not the writer.

What could elif mean other than else: if?

It could mean "Oh, the author has made a stupid typo, I better fix it."

It could mean "What does the elif command do?"

The first time I read Python code, I had literally no idea what to make
of elif. It seemed so obvious to me that any language would let you write
"else if ..." (on a single line) that I just assumed that elif must be
some other construct, and I had no idea what it was. It never even
crossed my mind that it could be "else if" rammed together into one word.

I soon learned better though.

Once you start dumbing down your code for readers who don't know your
language, it's a race to the bottom. There's very little you can write
that *somebody* won't misunderstand.


if x could, for instance, mean "if x is defined".

Yes it could, if you're programming in Perl. But we're not.

When I write a sentence in English, and I use the word "gift" to mean a
thing which is given, I don't worry that German or Swedish readers will
think I'm talking about poison. If I use "preservative", I mean something
which preserves, and if Italian and Spanish readers mistake it for a
condom, that's their problem, not mine. Writing code is no different.
When I'm coding in Python, I use Python rules and meanings, not some
other language.

Why should I code according to what some hypothetical Python dummy
*might* think the code will do, instead of what the code *actually* does?
 
P

Prasad, Ramit

I don't mean to insult anyone, but I've heard and read all the arguments against Python's truth-testing, and they
don't impress me in the slightest. Most of them strike me as silly. The only argument that carries any weight to me is
one which I haven't seen anyone raise:

"if x:" turns something which arguably could have been a mistake ("oops, I forgot to write the condition!") into valid
code.

The only problem I have had with the "if x:" notation is when I have values that might be empty lists, empty strings, None, or a boolean value being returned from the same source. But this is probably an instance when a good programmer would explicitly check the type instead of the naive "if x:" notation.

On the other hand, as a fairly n00b Python (and n00b Perl) developer, I find the notation "if not x:" to be far more English readable than "if x==None or len(x)== 0 or x==0 or bool(x):" (or some derivative/combination of those).



Ramit

Ramit Prasad | JPMorgan Chase Investment Bank | Currencies Technology
712 Main Street | Houston, TX 77002
work phone: 713 - 216 - 5423
This communication is for informational purposes only. It is not
intended as an offer or solicitation for the purchase or sale of
any financial instrument or as an official confirmation of any
transaction. All market prices, data and other information are not
warranted as to completeness or accuracy and are subject to change
without notice. Any comments or statements made herein do not
necessarily reflectthose of JPMorgan Chase & Co., its subsidiaries
and affiliates.

This transmission may contain information that is privileged,
confidential, legally privileged, and/or exempt from disclosure
under applicable law. If you are not the intended recipient, you
arehereby notified that any disclosure, copying, distribution, or
use ofthe information contained herein (including any reliance
thereon) is STRICTLY PROHIBITED. Although this transmission and any
attachments are believed to be free of any virus or other defect
that might affectany computer system into which it is received and
opened, it is the responsibility of the recipient to ensure that it
is virus free and no responsibility is accepted by JPMorgan Chase &
Co., its subsidiariesand affiliates, as applicable, for any loss
or damage arising in any way from its use. If you received this
transmission in error, pleaseimmediately contact the sender and
destroy the material in its entirety, whether in electronic or hard
copy format. Thank you.

Please refer to http://www.jpmorgan.com/pages/disclosures for
disclosures relating to European legal entities.
 
H

Hans Georg Schaathun

In a Bourne shell script, if ends with fi... case ends with esac... so
: file would end with... hmm. Yeah, I think it's best to know the
: language you're trying to comprehend, and/or actually look at context
: instead of shoving a piece of code under someone's nose and saying "I
: bet you can't figure out what THIS does!".

Code is quite often published to document algorithms, methods and
formulæ for the purpose of scientific research. Since there is no
universal language which suits everything and everyone, this
is exactly what happens. One has to have the rudimentary knowledge
to read half a dozen different languages to be able to read the
code and extract the algorithms. If one tried to maintain the
necessary programming skills to exploit all of those languages to
their full potential, one would simply not be able to keep up with
the application discipline.

If all you do is to write software for computer illiterate users, YMWV.
 
H

Hans Georg Schaathun

When did we come to the idea that people should be able to program in a
: language without actually learning it? The fact that Python comes so
: close to that possibility is nothing short of revolutionary.

Revolutionary indeed, so why don't we exploit the revolution
and write the programs to be as accessible as possible?

(Although, python is not the most revolutionary in this respect.)
 
H

harrismh777

Hans said:
Code is quite often published to document algorithms, methods and
formulæ for the purpose of scientific research. Since there is no
universal language which suits everything and everyone, this
is exactly what happens. One has to have the rudimentary knowledge
to read half a dozen different languages to be able to read the
code and extract the algorithms.

+1 QOTW
 
A

alex23

Hans Georg Schaathun said:
Revolutionary indeed, so why don't we exploit the revolution
and write the programs to be as accessible as possible?

Where do you draw the line, though?

No decorators, as they're not intuitively obvious? No custom
descriptors, as that requires a deeper knowledge of Python internals
that utter ignorance allows?

Both of those aspects alone seem far more complex and advanced than
treating empty collections as False.
 

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,982
Messages
2,570,190
Members
46,736
Latest member
zacharyharris

Latest Threads

Top