I'm looking for a way to test if an object is not of a "list-ish" type, that is - not only that the object is not iterable (e.g. - you can also run iter on a string, or on a simple object that implements iter) but that the object is not in the list family. I define the "list" family as list/tuple/set/frozenset, or anything that inherits from those, however - as there might be something that I'm missing, I would like to find a more general way than running isinstance
against all of those types.
I thought of two possible ways to do it, but both seem somewhat awkward as they very much test against every possible list type, and I'm looking for a more general solution.
First option:
return not isinstance( value, (frozenset, list, set, tuple,) )
Second option:
return not hasattr(value, '__iter__')
Is testing for the __iter__
开发者_StackOverflow社区 attribute enough? Is there a better way for finding whether an object is not a list-type?
Thanks in advance.
Edit:
(Quoted from comment to @Rosh Oxymoron's Solution):
Thinking about the definition better now, I believe it would be more right to say that I need to find everything that is not array-type in definition, but it can still be a string/other simple object...Checking againstcollections.Iterable
will still give me True for objects which implement the __iter__
method.There is no term 'list-ish' and there is no magic build-in check_if_value_is_an_instance_of_some_i_dont_know_what_set_of_types
.
You solution with not isinstance( value, (frozenset, list, set, tuple,) )
is pretty good - it is clear and explicit.
There is no such family – it's not well-defined, and naturally there's no way to check for it. The closest thing possible is an iterable that is not a string. You can test if the object for iterability and then explicitly check if it is a string:
if isinstance(ob, collections.Iterable) and not isinstance(ob, types.StringTypes):
print "An iterable container"
A better approach would be to always ask for an iterable object, and when you need to pass a single string S
, pass [S]
instead. The ability to pass a string is a feature, e.g.:
alphabet = set('abcdefgijklmopqrstuvwxyz')
If you special-case string, you will:
- Break the ability to use your function with the most natural way to pass a collection of characters.
- Create inconsistency for user-defined string types and/or other containers that are string-ish (e.g.
array.array
can represent a chunk of data, just like string).
A string can be used to represent both a single piece of text and a collection of characters, and because of the second it is also list-ish.
精彩评论