奇怪的行为 Django shell 和 iPython

Strange behaviour Django shell and iPython

我在 Django 控制台中做了一些事情,我意识到在 lambda 表达式中无法识别全局变量,例如,如果您在 python 中执行以下代码,甚至在 iPython 控制台中它完美运行:

a = 10
foo = lambda x: x + a
foo(10) # returns 20

但是如果你在 Django shell 中使用 iPython 执行它,它就不起作用:

In [8]: foo = lambda x: x + a

In [9]: a = 10

In [10]: foo(10)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
/usr/local/lib/python2.7/dist-packages/django/core/management/commands/shell.pyc in <module>()
----> 1 foo(10)

/usr/local/lib/python2.7/dist-packages/django/core/management/commands/shell.pyc in <lambda>(x)
----> 1 foo = lambda x: x + a

NameError: global name 'a' is not defined

iPython版本0.13.2

提前致谢!

编辑

事件如果我在 lambda 函数之前分配 a 问题仍然存在:

In [1]: a = 10

In [2]: foo = lambda x: x + a                                                                                                                                                                                                                  

In [3]: foo(10)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
/usr/local/lib/python2.7/dist-packages/django/core/management/commands/shell.pyc in <module>()
----> 1 foo(10)

/usr/local/lib/python2.7/dist-packages/django/core/management/commands/shell.pyc in <lambda>(x)
----> 1 foo = lambda x: x + a

NameError: global name 'a' is not defined

In [4]: 
───────────

您可能遇到了其他人在这里遇到的错误:

https://github.com/ipython/ipython/issues/62#issuecomment-3854940

正如线程中进一步解释的那样,在版本 1.6 之前,django 使用 IPython.embed() 函数启动 ipython shell,这会强制 ipython 从单独的本地和全局命名空间开始。

django 团队在此提交中修复了 1.6 中的这个问题:https://github.com/django/django/commit/3570ff734e93f493e023b912c9a97101f605f7f5

这是旧版本 Django(在本例中为 1.4.14)的反向移植修复:https://github.com/theatlantic/django/commit/9dfe12c40af23956dc12e3427e3e7e63ebc360c9

如果您在另一个函数内手动调用 IPython.embed()(创建闭包),则可以重现此问题,即使您使用常规 python/ipython shell。使用 ipython 3.1.0:

测试
>>> from IPython import embed
>>> def test():
...     embed()
... 
>>> test()
Python 2.7.9 (default, Feb 10 2015, 03:28:08) 
Type "copyright", "credits" or "license" for more information.

IPython 3.1.0 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

In [1]: a = 10

In [2]: foo = lambda x: x+a

In [3]: foo(10)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-3-08cbc4a9df91> in <module>()
----> 1 foo(10)

<ipython-input-2-3ecd5afea150> in <lambda>(x)
----> 1 foo = lambda x: x+a

NameError: global name 'a' is not defined