Reputation:
I have a function that may take in a number or a list of numbers. Whats the most pythonic way of checking which it is? So far I've come up with try/except block checking if i can slice the zero item ie. obj[0:0]
Edit:
I seem to have started a war of words down below by not giving enough info. For completeness let me provide more details so that I may pick and get the best answer for my situation:
I'm running Django on Python 2.6 and I'm writing a function that may take in a Django model instance or a queryset object and perform operations on it one of which involves using the filter 'in' that requires a list (the queryset input), or alternately if it is not a list then I would use the 'get' filter (the django get filter).
Upvotes: 10
Views: 930
Reputation: 70324
I don't want to be a pest, BUT: Are you sure the query set/object is a good interface? Make two functions, like:
def fobject(i):
# do something
def fqueryset(q):
for obj in q:
fobject( obj )
Might not be the pythonic way to discern an int from a list, but seems a far better design to me.
Reason being: Your function should be working on ducks. As long as it quacks, whack it. Actually picking the duck up, turning it upside down to check the markings on the belly before choosing the right club to whack it is unpythonic. Sorry. Just don't go there.
Upvotes: 2
Reputation: 126105
You don't.
This works only for Python >= 2.6. If you're targeting anything below use Alex' solution.
Python supports something called Duck Typing. You can look for certain functionality using the ABC classes.
import collections
def mymethod(myvar):
# collections.Sqeuence to check for list capabilities
# collections.Iterable to check for iterator capabilities
if not isinstance(myvar, collections.Iterable):
raise TypeError()
Upvotes: 11
Reputation: 88757
I think the way OP is doing, checking if it supports what he wants, is ok.
Simpler way in this scenario would be to not check for list which can be of many types depending on definition, you may check if input is number, do something on it else try to use it as list if that throws exception bail out.
e.g you may not want iterate over list but just wanted to append something to it if it is list else add to it
def add2(o):
try:
o.append(2)
except AttributeError:
o += 2
l=[]
n=1
s=""
add2(l)
add2(n)
add2(s) # will throw exception, let the user take care of that ;)
So bottom line is answer may vary depending on what you want to do with object
Upvotes: 0
Reputation: 881665
In such situations, you normally need to check for ANY iterable, not just lists -- if you're accepting lists OR numbers, rejecting (e.g) a tuple would be weird. The one kind of iterable you might want to treat as a "scalar" is a string -- in Python 2.*, this means str
or unicode
. So, either:
def isNonStringIterable(x):
if isinstance(x, basestring):
return False
try: iter(x)
except: return False
else: return True
or, usually much handier:
def makeNonStringIterable(x):
if isinstance(x, basestring):
return (x,)
try: return iter(x)
except: return (x,)
where you just go for i in makeNonStringIterable(x): ...
Upvotes: 21
Reputation: 15416
Just use the type method? Or am I misinterpreting the question
if type(objectname) is list:
do something
else:
do something else :P
Upvotes: -3
Reputation: 7638
if isinstance(your_object, list):
print("your object is a list!")
This is more Pythonic than checking with type.
Seems faster too:
>>> timeit('isinstance(x, list)', 'x = [1, 2, 3, 4]')
0.40161490440368652
>>> timeit('type(x) is list', 'x = [1, 2, 3, 4]')
0.46065497398376465
>>>
Upvotes: 13
Reputation: 229593
You can use isinstance
to check a variables type:
if isinstance(param, list):
# it is a list
print len(list)
Upvotes: 1