# Implicit lists

Alex Martelli aleax at aleax.it
Thu Jan 30 18:55:17 CET 2003

```Mike Meyer wrote:

> Alex Martelli <aleax at aleax.it> writes:
>
>> def iteron(something):
>>     # string-like objects: treat as non-sequences
>>     try: something+''
>>     except TypeError: pass
>>     else:
>>         yield something
>>         return
>>     # other sequences
>>     try:
>>         for x in something: yield x
>>     except TypeError:
>>         yield something
>
> I always thought that exceptions were expensive. Which makes me wonder

Let's check, e.g. with this code:

import time

def timeit(func):
repts = [None] * 1000000
start = time.clock()
for x in repts:
func()
stend = time.clock()
return stend-start

def isin_y():
return isinstance('ciao', str)

def isin_n():
return isinstance(23, str)

def exce_y():
try:
return 'ciao'+''
except:
return False

def exce_n():
try:
return 23+''
except:
return False

for f in isin_y, isin_n, exce_y, exce_n:
t = timeit(f)
print "%.2f %s" % (t, f.__name__)

On my years-old PC, we measure:

[alex at lancelot ball]\$ python -O tim.py
1.47 isin_y
1.44 isin_n
0.86 exce_y
13.14 exce_n
[alex at lancelot ball]\$

So, yes: exceptions are expensive *when taken*
(they're cheaper than isinstance when NOT taken).
Specifically, a taken exceptions seems to cost
over 10 microseconds on my old PC.

How much of a problem are those 10 microseconds
going to be in the typical use of this function?

for item in iteron(whatever):
something(item)

my guess is -- probably not much.  If profiling
later tells me this isn't the case, then I can
get into studying how often various kinds of
objects get passed to function iteron and tune
it accordingly -- specialcasing some kinds of
arguments, if need be -- no hurry.

Premature optimization is the root of all evil
in programming, remember...

> why you aren't using "isinstance(something, str)" for that first test.

That wouldn't catch unicode objects, instances of UserString,
and other such string-like objects.

Alex

```