ipython%timeit" local variable'a'在赋值之前引用' [英] ipython %timeit "local variable 'a' referenced before assignment"

查看:237
本文介绍了ipython%timeit" local variable'a'在赋值之前引用'的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试运行以下代码,但我在分配之前得到一个本地变量'a'。

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

该语句不使用%timeit magic。 / p>

我缺少什么?



谢谢。

解决方案

您期望它做什么?



超出时间范围:

 在[188]中:a + = b 
在[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 ,并获得了近乎无限的循环,最终以内存错误结束

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

在[194]中:len(a)
Out [194]:529076630

换句话说,每个时间循环c oncatenated另一个 b 值列表到 x (并且扩展名为 a ),结果是非常长的循环。我怀疑个人 x + = b 很快,导致 timeit 选择多次循环。



让我们创建一个 a 新的每个循环:

 在[196]中:%% timeit 
...:a = [x代表范围内的x(10)]
...:a + = b
。 ..:
每循环1.91μs±4.82 ns(7次运行的平均值±标准差,每次1000000次循环)

这也会产生内存错误:

 在[197]中:%% timeit a = [x代表范围内的x(10)] 
...:a + = b

如果我控制循环次数:

 在[202]中:%% timeit -n 100 a = [x代表x在范围(10)] 
...:a + = b
...:
...:
每循环208 ns±11 ns(平均值±标准差。开发7次,每次100次循环)

ns 次我可以看到为什么默认循环如此之大。



我还没有尝试过一个普通的 a + = ... 之前(甚至没有numpy数组),但显然它期望在 a 中进行某种本地初始化,循环或在初始化块中。但重要的是要记住,定时动作可以执行多次(-r和-n参数或默认值)。因此,任何就地操作都可能导致对全局值的位更改。在这种情况下, timeit 可能会试图通过预期某种本地变量来保护我们免受这种意外增长。






让我们尝试 a + b ,但有一项任务:

 在[215]中:c = np.zeros(10)
在[216]中:a
Out [216]:array([ 1,2,3,4,5,6,7,8,9,10]
在[217]中:b
输出[217]:[0,1,2,3,4] ,5,6,7,8,9]
在[218]中:%timeit c = a + b
每循环5.33μs±105 ns(平均值±标准偏差,7次运行,100000次)每个循环)
在[219]中:c
输出[219]:数组([0,0,0,0,0,0,0,0,0,0,0,0] 。,0。])

请注意全局 c 没变。分配到临时本地 c - 即使可以使用同名的全局。



作为一般规则,在定时循环内执行的计算不应泄漏到循环外部。你必须像我在内存错误循环中所做的那样明确,或者这里

 在[222]中:%% timeit x = c 
...:x + = b
...:
每循环9.04μs±238 ns(平均值±标准偏差,7次运行,每次100000次循环)
在[223]中:c
Out [223]:
array([0.,811111.,1622222。,2433333。,3244444。,4055555。,
4866666.,5677777。 ,6488888.,7299999.])

或者这里:

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

每循环7.84μs±199 ns(7次运行的平均值±标准差,每次100000次循环)
在[226]中:c
Out [226]:array([1.,3.,5.,7.,9.,11.,13.,15.,17.,19。])

两者都使用就地变量进行就地分配,该变量已链接到可变全局变量。


I am trying to the run the following code but I get a local variable 'a' referenced before assignment.

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

The statement works without the %timeit magic.

Is there something I am missing?

Thank you.

解决方案

What do you expect it to do?

Outside of the timeit it does:

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]

I tried initializing x, and got a near infinite loop, eventually ending with a memory error

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

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

In other words each timeit loop concatenated another list of b values to x (and by extension a), resulting are very long loop. I suspect an individual x+=b was fast, resulting in timeit choosing to loop many times.

Lets create an a fresh each loop:

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)

This produces the memory error as well:

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

If I control the number of loops:

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)

With ns times I can see why the default loops is so large.

I haven't tried timing a plain a+=... before (not even with numpy arrays), but evidently it expects some sort of local initialization for that a, either within the loop or in the initialization block. But it is important to keep in mind that the timed actions may be performed many times (the -r and -n parameters or the default values). So any in-place action might result bit changes to the global values. In this case timeit might be trying to protect us from that kind of unexpected growth, by expecting some sort of 'local' variable.


Lets try the a+b, but with an assignment:

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.])

Notice that the global c has not changed. The assignment is to a temporary local c - even though a global of the same name is available.

As a general rule, calculations performed inside the timing loop should not leak outside the loop. You have to something explicit as I did in the memory error loop, or here

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.])

or here:

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.])

Both use an in-place assignment to a local variable which has been linked to a mutable global.

这篇关于ipython%timeit" local variable'a'在赋值之前引用'的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆