What is the most pythonic way to use len on a scalar?
Question:
I read this question
python: how to identify if a variable is an array or a scalar
but when using the following code I get a false on an np.array
as can be demonstrated below.
import collections
isinstance(np.arange(10), collections.Sequence)
# returns false
I find it a bit annoying that I can’t do len(1)
and simply get 1
.
The only work around I can think of is a try except
statement such as the following:
a = 1
try:
print len(a)
except TypeError:
print 1
Is there a more Pythonic way to do this?
Answers:
collections.Sequence
only applies to sequence objects, which are a very specific type of iterable object. Incidentally, a numpy.ndarray
(which is returned by numpy.arange
) is not a sequence.
You need to test for either collections.Iterable
, which represents any iterable object:
>>> isinstance([1, 2, 3], collections.Iterable)
True
>> isinstance(np.arange(10), collections.Iterable)
True
>>> isinstance(1, collections.Iterable)
False
>>>
or collections.Sized
, which represents any object that works with len
:
>>> isinstance([1, 2, 3], collections.Sized)
True
>>> isinstance(np.arange(10), collections.Sized)
True
>>> isinstance(1, collections.Sized)
False
>>>
You can then use a conditional expression or similar to do what you want:
print len(a) if isinstance(a, collections.Iterable) else 1
print len(a) if isinstance(a, collections.Sized) else 1
For a complete list of the available abstract base classes in the collections
module, see Collections Abstract Base Classes in the Python docs.
I’ll just throw in another potential option:
length = getattr(obj, '__len__', lambda:1)()
So get either the __len__
method from the object, or a function that always returns 1, then call it to get your result.
I wouldn’t say it’s Pythonic, but avoids an import and exception handling. However, I’d still go with comparing if it’s a collections.Sized
and a conditional statement and put it in a helper function called len_or_1
or something.
Although this isn’t pythonic as it uses numpy here is another neat way to make this work:
import numpy as np
a = 1
aSh = np.shape(a)
if len(aSh) == 0:
print 1
else:
print max(aSh)
which gives a behaviour that should work with scalars, lists and matrices.
to much work…
temp = [var]
print(len(temp))
I read this question
python: how to identify if a variable is an array or a scalar
but when using the following code I get a false on an np.array
as can be demonstrated below.
import collections
isinstance(np.arange(10), collections.Sequence)
# returns false
I find it a bit annoying that I can’t do len(1)
and simply get 1
.
The only work around I can think of is a try except
statement such as the following:
a = 1
try:
print len(a)
except TypeError:
print 1
Is there a more Pythonic way to do this?
collections.Sequence
only applies to sequence objects, which are a very specific type of iterable object. Incidentally, a numpy.ndarray
(which is returned by numpy.arange
) is not a sequence.
You need to test for either collections.Iterable
, which represents any iterable object:
>>> isinstance([1, 2, 3], collections.Iterable)
True
>> isinstance(np.arange(10), collections.Iterable)
True
>>> isinstance(1, collections.Iterable)
False
>>>
or collections.Sized
, which represents any object that works with len
:
>>> isinstance([1, 2, 3], collections.Sized)
True
>>> isinstance(np.arange(10), collections.Sized)
True
>>> isinstance(1, collections.Sized)
False
>>>
You can then use a conditional expression or similar to do what you want:
print len(a) if isinstance(a, collections.Iterable) else 1
print len(a) if isinstance(a, collections.Sized) else 1
For a complete list of the available abstract base classes in the collections
module, see Collections Abstract Base Classes in the Python docs.
I’ll just throw in another potential option:
length = getattr(obj, '__len__', lambda:1)()
So get either the __len__
method from the object, or a function that always returns 1, then call it to get your result.
I wouldn’t say it’s Pythonic, but avoids an import and exception handling. However, I’d still go with comparing if it’s a collections.Sized
and a conditional statement and put it in a helper function called len_or_1
or something.
Although this isn’t pythonic as it uses numpy here is another neat way to make this work:
import numpy as np
a = 1
aSh = np.shape(a)
if len(aSh) == 0:
print 1
else:
print max(aSh)
which gives a behaviour that should work with scalars, lists and matrices.
to much work…
temp = [var]
print(len(temp))