Relying on the behaviour of empty container in conditional statements

Steven D'Aprano steve at REMOVETHIScyber.com.au
Tue Jul 11 19:52:09 EDT 2006


On Tue, 11 Jul 2006 19:43:57 +0000, Roel Schroeven wrote:

> I know that that is the consensus, and I mostly the form without len(), 
> but somehow I still feel it is not as explicit. In
> 
> if seq:
> 
> there is no distinction between seq is None on the one hand and seq 
> being a valid empty sequence on the other hand.

If seq can be None as well as a sequence, doing a test "if len(seq) > 0"
won't save you because len(None) will fail. You need an explicit test
for seq being None:

if seq is not None and len(seq) > 0

Or even better:

if seq

which Just Works regardless of the type of seq.



> I feel that that is an import distinction, and it's the reason I find 
> myself using len() from time to time (even though I can't think of a use 
> case right now).

If you are writing code where the argument in question could be None or a
list, then obviously you need to explicitly test for it being None -- but
that doesn't mean you have to explicitly test for the length of the list.
Likewise if the argument could be an integer as well as a sequence, you
need a more complex test again:

if x is not None and (isinstance(x, int) and x > 0) or len(x) > 0

(and I hope I got that right... so many potential bugs in that "safer"
code)

Or, the right way to do it:

if x

which Just Works for any x without worrying about type-checking or
combining boolean expressions or the precedence of operators.


Explicit doesn't mean you have to spell out every last detail. We don't
normally write:

x.__getitem__(0) instead of x[0]
s.split(None, 0) instead of s.split()
range(0, 100, 1) instead of range(100)
locals().__getitem__('name') instead of name

because they are "more explicit". There are times when more is too much.
The idiom "if seq" is a well-understood, well-defined, explicit test of
whether the sequence is true in a Boolean context, which for many
containers (lists, tuples, dicts, etc.) corresponds to them having
non-zero length, but that is not an invariant. There are potential
container types that either don't define a length or always have a
non-zero length even when they are false.


-- 
Steven.




More information about the Python-list mailing list