簡體   English   中英

ipython%timeit“分配前引用的局部變量'a'

[英]ipython %timeit “local variable 'a' referenced before assignment”

我正在嘗試運行以下代碼,但是local variable 'a' referenced before assignment.local variable 'a' referenced before assignment.local variable 'a' referenced before assignment.

a = [x for x in range(10)]
b = [x for x in range(10)]
%timeit a+=b

該語句在沒有%timeit魔術的情況下有效。

我有什么想念的嗎?

謝謝。

您期望它做什么?

在timeit之外執行:

In [188]: a += b
In [189]: a
Out[189]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

我嘗試初始化x ,並得到一個接近無限的循環,最終以內存錯誤結束

In [192]: %%timeit x=a
     ...: x += b

In [194]: len(a)
Out[194]: 529076630

換句話說,每個timeit循環將b值的另一個列表連接到x (並擴展為a ),從而導致循環很長。 我懷疑單個x+=b速度很快,導致timeit選擇循環多次。

讓我們創建a新的each循環:

In [196]: %%timeit
     ...: a = [x for x in range(10)]
     ...: a += b
     ...: 
1.91 µs ± 4.82 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

這也會產生內存錯誤:

In [197]: %%timeit a = [x for x in range(10)]
     ...: a += b

如果我控制循環數:

In [202]: %%timeit -n 100 a = [x for x in range(10)]
     ...: a += b
     ...: 
     ...: 
208 ns ± 11 ns per loop (mean ± std. dev. of 7 runs, 100 loops each)

ns次,我可以看到為什么默認循環這么大。

我還沒有嘗試過對普通的a+=...進行計時(甚至沒有使用numpy數組),但是很顯然,它希望在循環或初始化塊中對該a進行某種本地初始化。 但是,請記住,定時操作可能會執行多次(-r和-n參數或默認值),這一點很重要。 因此,任何就地操作都可能導致全局值的位更改。 在這種情況下, timeit可能希望通過期望某種“局部”變量來保護我們免受這種意外增長的影響。


讓我們嘗試a+b ,但是要賦值:

In [215]: c=np.zeros(10)
In [216]: a
Out[216]: array([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10])
In [217]: b
Out[217]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
In [218]: %timeit c = a+b
5.33 µs ± 105 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [219]: c
Out[219]: array([ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.])

請注意,全局c尚未更改。 分配給一個臨時的本地c即使可以使用相同名稱的全局變量。

通常,在定時循環內執行的計算不應泄漏到循環外。 您必須像我在內存錯誤循環中那樣明確地進行操作,或者在這里

In [222]: %%timeit x = c
     ...: x += b
     ...: 
9.04 µs ± 238 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [223]: c
Out[223]: 
array([       0.,   811111.,  1622222.,  2433333.,  3244444.,  4055555.,
        4866666.,  5677777.,  6488888.,  7299999.])

或在這里:

In [224]: c=np.zeros(10)
In [225]: %%timeit x = c
     ...: x[:] = a+b

7.84 µs ± 199 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [226]: c
Out[226]: array([  1.,   3.,   5.,   7.,   9.,  11.,  13.,  15.,  17.,  19.])

兩者都使用就地分配給已鏈接到可變全局變量的局部變量。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM