Check if a variable type is iterable?
It depends on what you mean by "iterable". It is a loose concept in C++ since you could implement iterators in many different ways.
If by foreach
you're referring to C++11's range-based for loops, the type needs begin()
and end()
methods to be defined and to return iterators that respond to operator!=
, operator++
and operator*
.
If you mean Boost's BOOST_FOREACH helper, then see BOOST_FOREACH Extensibility.
If in your design you have a common interface that all iterable containers inherit from, then you could use C++11's std::is_base_of:
struct A : IterableInterface {}
struct B {}
template <typename T>
constexpr bool is_iterable() {
return std::is_base_of<IterableInterface, T>::value;
}
is_iterable<A>(); // true
is_iterable<B>(); // false
In Python, how do I determine if an object is iterable?
Checking for
__iter__
works on sequence types, but it would fail on e.g. strings in Python 2. I would like to know the right answer too, until then, here is one possibility (which would work on strings, too):try:
some_object_iterator = iter(some_object)
except TypeError as te:
print(some_object, 'is not iterable')
The iter
built-in checks for the __iter__
method or in the case of strings the __getitem__
method.
- Another general pythonic approach is to assume an iterable, then fail gracefully if it does not work on the given object. The Python glossary:
Pythonic programming style that determines an object's type by inspection of its method or attribute signature rather than by explicit relationship to some type object ("If it looks like a duck and quacks like a duck, it must be a duck.") By emphasizing interfaces rather than specific types, well-designed code improves its flexibility by allowing polymorphic substitution. Duck-typing avoids tests using type() or isinstance(). Instead, it typically employs the EAFP (Easier to Ask Forgiveness than Permission) style of programming.
...
try:
_ = (e for e in my_object)
except TypeError:
print my_object, 'is not iterable'
The
collections
module provides some abstract base classes, which allow to ask classes or instances if they provide particular functionality, for example:from collections.abc import Iterable
if isinstance(e, Iterable):
# e is iterable
However, this does not check for classes that are iterable through __getitem__
.
Checking whether something is iterable
The proper way to check for iterability is as follows:
function isIterable(obj) {
// checks for null and undefined
if (obj == null) {
return false;
}
return typeof obj[Symbol.iterator] === 'function';
}
Why this works (iterable protocol in depth): https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Iteration_protocols
Since we are talking about for..of, I assume, we are in ES6 mindset.
Also, don't be surprised that this function returns true
if obj
is a string, as strings iterate over their characters.
how to tell a variable is iterable but not a string
Use isinstance (I don't see why it's bad practice)
import types
if not isinstance(arg, types.StringTypes):
Note the use of StringTypes. It ensures that we don't forget about some obscure type of string.
On the upside, this also works for derived string classes.
class MyString(str):
pass
isinstance(MyString(" "), types.StringTypes) # true
Also, you might want to have a look at this previous question.
Cheers.
NB: behavior changed in Python 3 as StringTypes
and basestring
are no longer defined. Depending on your needs, you can replace them in isinstance
by str
, or a subset tuple of (str, bytes, unicode)
, e.g. for Cython users.
As @Theron Luhn mentionned, you can also use six
.
Checking if a class is iterable
Checking if an object is iterable is correctly, as you've done, performed with:
isinstance(obj, collections.Iterable)
The problem here is you're supplying a class
to isinstance
and not an instance. It is False
because isinstance
will go ahead and check if type(fib)
has an __iter__
method defined:
type(fib).__iter__ # AttributeError
This of course, isn't the case. type(fib)
is type
which doesn't define an __iter__
method.
If you supply an instance to it, it correctly prints True
:
isinstance(fib(), Iterable) # True
because looking in type(fib())
it will find fib.__iter__
.
Alternatively, feeding fib
to issubclass
performs a similar check that, instead, takes a class as a first argument:
issubclass(fib, Iterable) # True
Two extra minor things to point out:
- Using
object
as an explicit base class is unnecessary in Python3
(though, if you're developing code that runs on both Py2 and Py3, it is a good thing. (See Python class inherits object for more on this.) - According to PEP 8, class names should follow the CapWords convention, so
fib
should ideally be namedFib
.
How can I check whether an object is iterable statically?
There is an Iterable
type that would do just that:
function fn(ary: Iterable<any>) {
for (let value of ary)
console.log(value)
}
Corresponding TypeScript playground here.
Note that Iterable
requires on type argument. any
allows you to specifically detect just if an object is iterable, although you could go further and specify on what you would like to iterate (eg. Iterable<Number>
).
Related Topics
Efficient Thread-Safe Singleton in C++
Should I Return Exit_Success or 0 from Main()
How to Identify Platform/Compiler from Preprocessor MACros
What Does "#Pragma Comment" Mean
Is There a Production Ready Lock-Free Queue or Hash Implementation in C++
What Do Each Memory_Order Mean
Understanding Recursion to Generate Permutations
How to Reliably Get an Object's Address When Operator& Is Overloaded
What Does Flushing the Buffer Mean
How to Properly Use Std::String on Utf-8 in C++
Why Not Use Pointers for Everything in C++
How to Append an Int to a String in C++
C++ HTML Template Framework, Templatizing Library, HTML Generator Library
List of Standard Header Files in C and C++
When Should I Use C++14 Automatic Return Type Deduction
How to Hook Windows Functions in C/C++
Error: Invalid Initialization of Non-Const Reference of Type 'Int&' from an Rvalue of Type 'Int'