为什么用扩展片反转字符串这么快?

时间:2019-05-23 21:02:36

标签: python slice

我只是timed a couple of string reversal methods,当然扩展的切片非常快。实际上,使用Python 3.6.7的印象是它具有恒定的时间:

enter image description here

20 chars            : min:   0.6μs, mean:   0.7μs, max:    3.7μs
2000 chars          : min:   0.5μs, mean:   0.6μs, max:    5.8μs
200000 chars        : min:   0.5μs, mean:   0.6μs, max:    2.5μs
200000000 chars     : min:   0.5μs, mean:   0.6μs, max:    2.5μs

为什么会这样?我以为它至少需要遍历所有元素并因此具有线性时间?是否有一些cPython的指针魔术?我的评估中有错误吗?

代码

#!/usr/bin/env python

import numpy as np
import random
import timeit
random.seed(0)


def main():
    string_20 = ''.join(random.choices("ABCDEFGHIJKLM", k=20))
    string_2000 = ''.join(random.choices("ABCDEFGHIJKLM", k=2000))
    string_200000 = ''.join(random.choices("ABCDEFGHIJKLM", k=200000))
    string_200000000 = ''.join(random.choices("ABCDEFGHIJKLM", k=200000000))
    functions = [(list_comprehension, '20 chars', string_20),
                 (list_comprehension, '2000 chars', string_2000),
                 (list_comprehension, '200000 chars', string_200000),
                 (list_comprehension, '200000000 chars', string_200000000),
                 ]
    duration_list = {}
    for func, name, params in functions:
        durations = timeit.repeat(lambda: func(params), repeat=100, number=3)
        duration_list[name] = list(np.array(durations) * 1000)
        print('{func:<20}: '
              'min: {min:5.1f}μs, mean: {mean:5.1f}μs, max: {max:6.1f}μs'
              .format(func=name,
                      min=min(durations) * 10**6,
                      mean=np.mean(durations) * 10**6,
                      max=max(durations) * 10**6,
                      ))
        create_boxplot('Reversing a string of various lengths', duration_list)


def list_comprehension(string):
    return string[::1]


def create_boxplot(title, duration_list, showfliers=False):
    import seaborn as sns
    import matplotlib.pyplot as plt
    import operator
    plt.figure(num=None, figsize=(8, 4), dpi=300,
               facecolor='w', edgecolor='k')
    sns.set(style="whitegrid")
    sorted_keys, sorted_vals = zip(*duration_list.items())
    flierprops = dict(markerfacecolor='0.75', markersize=1,
                      linestyle='none')
    ax = sns.boxplot(data=sorted_vals, width=.3, orient='h',
                     flierprops=flierprops,
                     showfliers=showfliers)
    ax.set(xlabel="Time in ms", ylabel="")
    plt.yticks(plt.yticks()[0], sorted_keys)
    ax.set_title(title)
    plt.tight_layout()
    plt.savefig("output-string-list-comp.png")


if __name__ == '__main__':
    main()

1 个答案:

答案 0 :(得分:1)

只需检查一下即可。 list_comprehension方法必须为

def list_comprehension(string):
    return string[::-1]

由于花了很长时间,我没有列出最大的列表。这是我的输出:

/usr/bin/python3 ./boxplot.py 
20 chars            : min:   1.7μs, mean:   2.0μs, max:    7.5μs
2000 chars          : min:   6.7μs, mean:   6.8μs, max:   13.4μs
200000 chars        : min: 567.6μs, mean: 609.9μs, max:  997.2μs

似乎不是预期的恒定:-)

enter image description here

顺便说一句漂​​亮的箱线图!