Hernan
Hernan

Reputation: 6063

Mimicking Python behavior for `len` and `bool`

Consider the following code:

>>> class X:
... pass
...
>>> x = X()
>>> len(x)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: object of type 'X' has no len()
>>> bool(x)
True

But when trying to mimick this writing __len__ it does not work.

>>> class Y:
...   def __len__(self):
...     raise TypeError
...
>>> y = Y()
>>> len(y)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in __len__
TypeError
>>> bool(y)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in __len__
TypeError

Is there a way to write a __len__ function that works like it is not implemented?

Upvotes: 1

Views: 1253

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1124000

bool() tests the truth value of an object, so you want to look at the rules for Truth Value Testing:

By default, an object is considered true unless its class defines either a __bool__() method that returns False or a __len__() method that returns zero, when called with the object.

You only implemented a __len__ method that's deliberately broken, raising TypeError when called. But bool() will call it when there it is an implemention and there are no other options available to determine the truth value.

When determining the truth value, __bool__ is preferred over __len__:

When this method is not defined, __len__() is called, if it is defined, and the object is considered true if its result is nonzero.

Demo:

>>> class Z:
...     def __bool__(self):
...         return True
...     def __len__(self):
...         raise TypeError
...
>>> len(Z())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 5, in __len__
TypeError
>>> bool(Z())
True

Note that it is the len() function implementation that raises TypeError when there is no implementation for the __len__ hook. There is no exception that a __len__ implementation can raise that'll let you pretent it is not actually implemented, any exceptions it raises are propagated if it is called, because you'd normally would want to know if the implementation is broken in some way.

Upvotes: 5

Related Questions