29

I have a function

def foo(bar):
    #do some things
    len(bar)

If I call

foo(42)

it throws an exception of

TypeError: object of type 'int' has no len()

How do I check if the entered value can be used with len()?

DeadEli
  • 893
  • 2
  • 12
  • 26

4 Answers4

38

You can do:

if hasattr(bar, '__len__'):
    pass

Alternatively, you can catch the TypeError.

Nathaniel Flath
  • 14,862
  • 19
  • 62
  • 93
  • 2
    Wouldn't this need to be `__len__ in dir(bar)`? Either way, using `hasattr` is better if you go with this approach – Daenyth May 09 '14 at 14:54
  • 3
    Even an object has `__len__` attribute, it doesn't mean it's valid (or OP should define what is **valid**). For example, a class can define a `__len__` function which returns a `str`, and it will pass the `hasattr` test but still throw the `TypeError` exception when you call `len()` on it. This is exactly what **exception handling** is designed for, punish them for giving me dirty input. – Nier Apr 08 '16 at 03:45
21

You can test if the object is Sized:

import collections.abc

if isinstance(bar, collections.abc.Sized):

The isinstance() test is true if all abstract methods of Sized are implemented; in this case that's just __len__.

Personally, I'd just catch the exception instead:

try:
    foo(42)
except TypeError:
    pass  # oops, no length
Martijn Pieters
  • 963,270
  • 265
  • 3,804
  • 3,187
  • 2
    Should import `Sized` from `collections.abc` (`collections.Sized` and others are deprecated since Python 3.3 and scheduled to stop working in 3.9) – stav Sep 23 '20 at 14:50
7

Since len() calls __len__() magic method under the hood, you can check if an object has __len__ method defined with the help of hasattr():

>>> def has_len(obj):
...     return hasattr(obj, '__len__')
... 
>>> has_len([1,2,3])
True
>>> has_len('test')
True
>>> has_len(1)
False
Community
  • 1
  • 1
alecxe
  • 441,113
  • 110
  • 1,021
  • 1,148
5

You can do it using try and except for best results:

def foo(bar):
    #do some things
    try:
        print(len(bar))
    except TypeError:
        print('Input not compatible with len()')
sshashank124
  • 29,826
  • 8
  • 62
  • 75
  • As a general rule, that's arguably the most Pythonic, duck-typing approach. It doesn't work for some use cases, e.g. list or dict comprehensions. – jcomeau_ictx Feb 17 '21 at 03:39