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

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

tuple() 增加這么多運行時間是正常的嗎?

tuple() 增加這么多運行時間是正常的嗎?

慕村225694 2022-11-01 16:52:45
我有一個相對較長(20,000 行)的 CSV 文件和一個簡單的函數來打開它:def read_prices():    with open('sp500.csv', 'r') as f:        reader = csv.DictReader(f)        for row in reader:            yield float(row['Adj Close'].strip())當我按原樣計時時3e-05s:print(timeit.timeit(lambda: read_prices(), number=100))當我計時相同的功能但tuple(...)它需要一個驚人的27s:print(timeit.timeit(lambda: tuple(read_prices()), number=100))這是正常的tuple()嗎?為什么會這樣?我是初學者,所以歡迎 ELI5 解釋:)
查看完整描述

2 回答

?
慕斯709654

TA貢獻1840條經驗 獲得超5個贊

發生這種情況是因為read_prices它不是一個函數 - 它實際上是一個generator. 那是因為yield關鍵字。

正如函數式編程 HOWTO中所解釋的:

任何包含yield關鍵字的函數都是生成器函數;這是由 Python 的字節碼編譯器檢測到的,該編譯器專門編譯該函數作為結果。

當您調用生成器函數時,它不會返回單個值;相反,它返回一個支持迭代器協議的生成器對象。

所以當你第一次運行時發生的read_prices()只是一個generator對象的創建,等待被告知yield元素。

在第二個版本中tuple(read_prices()),您像以前一樣創建generator對象,但tuple()實際上會一次性耗盡它和yield所有元素。


一個簡單的演示:

>>> def yielder():

...     yield from [1, 2, 3]

...     

>>> y = yielder()

>>> y

<generator object yielder at 0x2b5604090de0>

>>> next(y)

1

>>> list(y)

[2, 3]

>>> tuple(yielder())

(1, 2, 3)


查看完整回答
反對 回復 2022-11-01
?
達令說

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

這是因為這是一個生成器 read_prices('SP500.csv'),當這樣調用時它幾乎什么都不做。

但是,當您這樣做時,tuple(read_prices('SP500.csv'))它會操作生成器并提供值。

生成器是可迭代的,由 a 操作:

  • for 循環

  • 下一個

  • 使用解包tuple(如您所述)或list

在涉及集合構造的其他操作中。

這是一個更具體的生成器示例:

def f():

    print("First value:")

    yield "first"

    print("Second value:")

    yield "second"

這是在行動:


### Nothing prints when called (analogous to your first timeit  without tuple)


In [2]: v = f()


In [3]:


### However when I call `next` the first value is provided:


In [3]: next(v)

First value:

Out[3]: 'first'


## etc, until there is no more values and a "StopIteration` exception is raised:


In [4]: next(v)

Second value:

Out[4]: 'second'


In [5]: next(v)

------------------------------------

...


StopIteration:


## by unpacking using "tuple" the "StopIteration" 

## exception is handled and all the values are provided at once

##  (like your timeit using the tuple):


In [6]: tuple(f())

First value:

Second value:

Out[6]: ('first', 'second')


查看完整回答
反對 回復 2022-11-01
  • 2 回答
  • 0 關注
  • 107 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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