简体   繁体   中英

Unable to pass list to this Python function when using timeit

I wrote a small script to generate the running times of a function with varying input. My intent was to plot the numbers and prove to myself that the function indeed had a quadratic running time. Here's the code:

import timeit

seq = [875011, 549220, 400865, 913974, 699921, 108386, 328934, 593902, 805659, 916502, 597662]

subseq = []
num = 1000000 # How many times the algorithm must run

# Quadratic running time
def quad (S):
    n = len(S)
    A = [0] * n

    for j in range(n):
        total = 0
        for i in range(j+1):
            total += S[i]
        A[j] = total / (j+1)

    return A

def plot_func (name):
    print('\n')
    for i in range(len(seq)):
        subseq = seq[0:i+1]
        t = timeit.Timer('{}(subseq)'.format(name), 'from __main__ import {}, subseq'.format(name))
        print(t.timeit(number=num))

plot_func('quad')

The problem is that the running time doesn't vary, and that's because every time it runs, the function quad refers to the global subseq , which is empty. How can I pass this sub-sequence correctly to this function?

PS: I'm also fine using another tool for this job, as long as it can give me the exact running time (in terms of CPU time used) of each iteration of the function.

By default, Python thinks that subseq is a variable local to your function. This local name shadows the global variable that you're passing a parameter to the timeit timer.

To make the assignment operation globally-visible, you need to declare the subseq variable as global before using it in the function:

def plot_func (name):
    global subseq
    print('\n')
    for i in range(len(seq)):
        subseq = seq[0:i+1]

To separate your code with code you want to measure usually is not a good idea.
As your goal is just measure your algorithm to check results, I recommend you to run everything inside timeit scope, like the following

import timeit

num = 1000000 # How many times the algorithm must run
setup = """
    seq = [875011, 549220, 400865, 913974, 699921, 108386, 328934, 593902, 805659, 916502, 597662]

    subseq = []

    # Quadratic running time
    def quad (S):
        n = len(S)
        A = [0] * n

        for j in range(n):
            total = 0
            for i in range(j+1):
                total += S[i]
            A[j] = total / (j+1)

        return A
    """
run_function = """
    def plot_func (name):
        print('\n')
        for i in range(len(seq)):
            subseq = seq[0:i+1]
            print(t.timeit(number=num))
    plot_func('quad')
"""
timeit.timeit(stmt=run_function, setup=setup, number=num)

This way, timeit will setup everything inside its scope and run your defined function within it as well.
It is important to notice that the time taken from print statement to run will also be counted, however, that will not alter significantly the results and most importantly, will not make it lose its quadratic context

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM