checking if a list is empty

Steven D'Aprano steve+comp.lang.python at pearwood.info
Wed May 11 17:42:10 EDT 2011


On Wed, 11 May 2011 19:05:03 +0000, Chris Torek wrote:

> In article <4dcab8bf$0$29980$c3e8da3$5496439d at news.astraweb.com> Steven
> D'Aprano  <steve+comp.lang.python at pearwood.info> wrote:
>>When you call len(x) you don't care about the details of how to
>>calculate the length of x. The object itself knows so that you don't
>>have to. The same applies to truth testing.
>>
>>I have a data type that is an array of lists. When you call "if len(x) >
>>0" on it, it will blow up in your face, because len(x) returns a list of
>>lengths like [12, 0, 2, 5]. But if you say "if x", it will do the right
>>thing. You don't need to care how to truth-test my data type, because it
>>does it for you. By ignoring my type's interface, and insisting on doing
>>the truth-test by hand, you shoot yourself in the foot.
> 
> What this really points out is that "if x" and "if len(x) > 0" are
> *different tests*.

*Potentially* different tests. Which is exactly the point. Given an 
arbitrary object, the developer doesn't know what test is appropriate. 
Should I write len(x) == 0 or list(x) == [] or x.next is None or 
something else? How can I tell which is appropriate without knowing 
everything about the internals of every object I ever see?

But if x is a non-broken object, then you don't have to. Just test on x 
itself, because it knows what to do to be considered a truth value.

Of course there may be objects where this doesn't work. There are no 
guarantees in Python. You can't even guarantee that printing an object 
won't blow up:

>>> class Broken:
...      def __str__(self):
...          return "... %s ..." % 1/2
...      __repr__ = __str__
...
>>> b = Broken()
>>> b
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in __str__
TypeError: unsupported operand type(s) for /: 'str' and 'int'


> Consider xml.etree.ElementTree "Element" objects.
> The documentation says, in part:
> 
>     In ElementTree 1.2 and earlier, the sequence behavior means that an
>     element without any subelements tests as false (since it's an empty
>     sequence), even if it contains text and attributions. ...
> 
>     Note: This behavior is likely to change somewhat in ElementTree 1.3.
>      To write code that is compatible in both directions, use ...
>     "len(element)" to test for non-empty elements.
> 
> In this case, when x is an Element, the result of bool(x) *could* mean
> just "x has sub-elements", but it could also/instead mean "x has
> sub-elements, text, or attributions".

Either behaviour is correct, but a semantic change to the class means 
that you have to do more work if you care about supporting both versions 
in the same code base. That is a neat example of where you might choose 
*not* to let an object decide for itself whether it is true or false, but 
instead impose your own definition on it.




-- 
Steven



More information about the Python-list mailing list