ipython %timeit "local variable 'a' referenced before assignment"
ipython %timeit "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
魔法的情况下有效。
有什么我遗漏的吗?
谢谢。
您希望它做什么?
在它执行的时间之外:
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
新鲜的每个循环:
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
可能试图通过预期某种 'local' 变量来保护我们免受这种意外增长的影响。
让我们试试 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.])
两者都对已链接到可变全局变量的局部变量使用就地赋值。
我正在尝试 运行 以下代码,但我得到 local variable 'a' referenced before assignment.
a = [x for x in range(10)]
b = [x for x in range(10)]
%timeit a+=b
该语句在没有 %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
新鲜的每个循环:
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
可能试图通过预期某种 'local' 变量来保护我们免受这种意外增长的影响。
让我们试试 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.])
两者都对已链接到可变全局变量的局部变量使用就地赋值。