checking if a list is empty
Steven D'Aprano
steve+comp.lang.python at pearwood.info
Wed May 11 09:29:38 EDT 2011
On Wed, 11 May 2011 08:26:53 -0400, Roy Smith wrote:
> Hans Georg Schaathun <hg at schaathun.net> wrote:
>
>> 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:
>>> isinstance(li, 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:
>>> li = list()
>>> li == []
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.
--
Steven
More information about the Python-list
mailing list