Reputation: 104
As I am learning Python 3.5 and I wanted to start comparing time on different code.
I have tried the timeit.timeit
module on a couple other simple statements and got it to work.
I can't get it to work on the below code and get the error below:
Traceback (most recent call last):
File "C:\Users\ASUS\Desktop\pythoncode\class_gen.py", line 10, in <module>
print(timeit.timeit(",".join(["#"+i+j for i in listTags for j in listTags if i != j])))
File "C:\Python35\lib\timeit.py", line 213, in timeit
return Timer(stmt, setup, timer, globals).timeit(number)
File "C:\Python35\lib\timeit.py", line 133, in __init__
code = compile(src, dummy_src_name, "exec")
File "<timeit-src>", line 7
_t1 = _timer()
^
IndentationError: expected an indented block"""
The code I am using is:
import itertools
import timeit
listTags = [ "TOT" , "WBA", "BUR", "SOU"]
print(timeit.timeit(",".join(["#" + "".join(t) for t in itertools.permutations(listTags, 2)]))
print(timeit.timeit(",".join(["#"+i+j for i in listTags for j in listTags if i != j])))
I have tried it with and without the number=number
keyword to no avail.
Upvotes: 0
Views: 699
Reputation: 160377
@Jean is correct, you need to pass it as a string to timeit
(wrap it up in single quotes '
) in order for it to work correctly. You also need to pass the appropriate setup
for name look-ups to succeed.
Still, it is interesting to note why this happens, though.
When you try and timeit
with:
print(timeit.timeit(",".join(["#" + "".join(t) for t in itertools.permutations(listTags, 2)]))
you should realize that the argument gets evaluated. timeit
is eventually called with the argument:
timeit.timeit('#TOTWBA,#TOTBUR,#TOTSOU,#WBATOT,#WBABUR,#WBASOU,#BURTOT,#BURWBA,#BURSOU,#SOUTOT,#SOUWBA,#SOUBUR')
Inside timeit
, this is formatted into a default template that gets timed; it's easy to re-create that template to see what Python tries to execute:
template = """
def inner(_it, _timer{init}):
{setup}
_t0 = _timer()
for _i in _it:
{stmt}
_t1 = _timer()
return _t1 - _t0
"""
src = template.format(stmt=",".join(["#"+i+j for i in listTags for j in listTags if i != j]), setup='', init='')
So, what gets exec
uted is:
>>> print(src)
def inner(_it, _timer):
_t0 = _timer()
for _i in _it:
#TOTWBA,#TOTBUR,#TOTSOU,#WBATOT,#WBABUR,#WBASOU,#BURTOT,#BURWBA,#BURSOU,#SOUTOT,#SOUWBA,#SOUBUR
_t1 = _timer()
return _t1 - _t0
Which, if you try and execute normally in your REPL, would result in an IndentationError
since the for
loop only has a comment in its body (which gets removed during parsing). Executing:
for i in [1, 2]:
# foo
print('fooing')
Results in:
File "<ipython-input-58-634beff715a1>", line 3
print('fooing')
^
IndentationError: expected an indented block
Upvotes: 2
Reputation: 140148
You have to pass a python code as string in the timeit
call.
You were passing the evaluated value of your expression (#TOTWBA,#TOTBUR,#TOTSOU,#WBATOT,#WBABUR,#WBASOU,#BURTOT,#BURWBA,#BURSOU,#SOUTOT,#SOUWBA,#SOUBUR
) to be executed.
Moreover, you have to pass listTags
literally, or using setup
expression, as timeit
runs in a different interpreter: it's not aware of your previously defined variables.
I rewrote the first timeit call using single quotes to protect your statement and added a setup
call to define the listTags
variable.
import itertools
import timeit
print(timeit.timeit('",".join(["#" + "".join(t) for t in itertools.permutations(listTags, 2)])',setup='listTags = [ "TOT" , "WBA", "BUR", "SOU"]'))
I get a time as a result: 5.2231671576142285
: it's working
Upvotes: 2