亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

在python中生成元組的最快方法是什么:

在python中生成元組的最快方法是什么:

喵喔喔 2021-11-16 10:48:47
尋找使用標題中提到的模式生成元組的最快方法,即:(1.0, 0.0, 0.0, 2.0, 0.0, 0.0, ..., N, 0.0, 0.0)對于任意的正n表示方面:round(N) == N。
查看完整描述

3 回答

?
神不在的星期二

TA貢獻1963條經驗 獲得超6個贊

誰知道?;-) 在 CPython 中,“技巧”通常涉及避免顯式的 Python 級循環,以及避免二次時間串聯。這是一種方法:


def gentup(N):

    NI = round(N)

    assert N == NI

    result = [0.] * (3 * NI)

    result[::3] = map(float, range(1, NI + 1))

    return tuple(result)

然后,例如,


>>> gentup(4)

(1.0, 0.0, 0.0, 2.0, 0.0, 0.0, 3.0, 0.0, 0.0, 4.0, 0.0, 0.0)

然后所有實際工作都以“C 速度”運行,甚至float只查找一次(盡管被調用了 round(N)多次)。


查看完整回答
反對 回復 2021-11-16
?
德瑪西亞99

TA貢獻1770條經驗 獲得超3個贊

我能想到的最快的方法是使用itertools函數將所有工作推送到 C 層:


from itertools import chain, repeat


def make_tuple(N):

    return return tuple(chain.from_iterable(zip(map(float, range(1, round(N)+1)), repeat(0.0), repeat(0.0))))

repeat制作零,map(float, range(1, round(N)+1))制作非零值,將zip它們組合在一起形成三個tuple,從而chain.from_iterable扁平化從而tuple直接構建最終結果。


雖然它確實涉及臨時三tuple(與帕特里克的回答不同),但在 CPython 參考解釋器上,它實際上根本不創建新tuple的;如果在請求下一個值時不存在對 的其他引用(并且每次都釋放其引用),zip則優化為將tuple來自上一個結果的 重用于新結果。tuplechain.from_iterable


為了與其他答案進行比較,微ipython基準測試為N150:


>>> %timeit -r5 make_tuple(150)

28.1 μs ± 1.67 μs per loop (mean ± std. dev. of 5 runs, 10000 loops each)

>>> %timeit -r5 make_tuple_tim_peters(150)

17.1 μs ± 52 ns per loop (mean ± std. dev. of 5 runs, 100000 loops each)

>>> %timeit -r5 make_tuple_julien(150)

154 μs ± 1.85 μs per loop (mean ± std. dev. of 5 runs, 10000 loops each)

>>> %timeit -r5 tuple(values_patrick_haugh(150))  # Modified to convert to float properly

40.7 μs ± 1.29 μs per loop (mean ± std. dev. of 5 runs, 10000 loops each)

我嘗試了一些其他方法,類似于我上面的 listcomps 和 genexprs 自己的方法,但沒有一個低于 40 μs,所以我沒有費心發布它們。


Tim Peter 的解決方案絕對是迄今為止發布的最快的解決方案,并且不太可能被改進。正如他所指出的,它需要更多的內存,因為在內存使用高峰期,它需要存儲整個結果tuple和臨時結果list(盡管每個都應該精確調整大小,沒有過度分配),這意味著容器的峰值內存大約是兩倍是“需要”的。我的確實需要tuple在進行時進行過度分配(因為它不知道結果會有多大),在當前的 CPython 中,作為一個實現細節,這意味著過度分配大約 25%。節省,但不是很大;如果性能很重要,我幾乎總是采用 Tim 的解決方案。


后來的更新:我最終設法找到了打敗 Tim 答案的東西,但只能求助于numpy,而且增量改進非常微不足道:


from numpy import arange, zeros


def make_tuple_numpy(N):

    ret = zeros(3*round(N))

    ret[::3] = arange(1., N+1.)

    return tuple(ret.tolist())

它與 Tim 的回答基本相同,它只是用來numpy批量處理原始 C 原始類型的工作(例如,np.arange直接以浮點形式生成一個范圍,而無需創建一堆 Python ints 僅將它們轉換為floats),使用tolist方法在不涉及 Python 迭代器的情況下numpy執行轉換list,然后包裝在tuple構造函數中(特殊情況list,因此再次不涉及迭代器)。即便如此,優勢也很微不足道:


>>> %timeit -r5 make_tuple_numpy(150)

13.8 μs ± 158 ns per loop (mean ± std. dev. of 5 runs, 100000 loops each)

這是在約20%,而蒂姆的解決方案運行時間進一步減少,但除非你做這樣的很多,進口的成本numpy可能消除了節約。


查看完整回答
反對 回復 2021-11-16
?
搖曳的薔薇

TA貢獻1793條經驗 獲得超6個贊

這是一種不會生成任何臨時元組的方法。


def values(N):

    nums = range(1, N+1)

    for n in nums:

        yield n

        yield 0

        yield 0


print(tuple(values(5)))

# (1, 0, 0, 2, 0, 0, 3, 0, 0, 4, 0, 0, 5, 0, 0)


查看完整回答
反對 回復 2021-11-16
  • 3 回答
  • 0 關注
  • 195 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號