Maison > Article > développement back-end > 为什么 Python 不是 lexical scoping?
这似乎背离了现代程序设计语言的一般设计思路。
比如
<span class="k">def</span> <span class="nf">foo</span><span class="p">():</span> <span class="n">x</span> <span class="o">=</span> <span class="mi">1</span> <span class="k">def</span> <span class="nf">inner</span><span class="p">():</span> <span class="k">return</span> <span class="n">x</span> <span class="o">+</span> <span class="mi">1</span> <span class="n">x</span> <span class="o">=</span> <span class="mi">3</span> <span class="k">print</span> <span class="n">inner</span><span class="p">()</span>
<code class="language-bash"><span class="nv">x</span><span class="o">=</span><span class="m">1</span>
<span class="k">function</span> g <span class="o">()</span> <span class="o">{</span> <span class="nb">echo</span> <span class="nv">$x</span> <span class="p">;</span> <span class="nv">x</span><span class="o">=</span><span class="m">2</span> <span class="p">;</span> <span class="o">}</span>
<span class="k">function</span> f <span class="o">()</span> <span class="o">{</span> <span class="nb">local </span><span class="nv">x</span><span class="o">=</span><span class="m">3</span> <span class="p">;</span> g <span class="p">;</span> <span class="o">}</span>
f <span class="c">#f中的g执行时打印出的x是3而不是1</span>
<span class="nb">echo</span> <span class="nv">$x</span> <span class="c">#这时打印出的x是1</span>
</code>
你以为Python是<code class="language-ocaml"><span class="k">let</span> <span class="n">foo</span> <span class="bp">()</span> <span class="o">=</span>
<span class="k">let</span> <span class="n">x</span> <span class="o">=</span> <span class="mi">1</span> <span class="k">in</span>
<span class="k">let</span> <span class="n">inner</span> <span class="bp">()</span> <span class="o">=</span> <span class="n">x</span> <span class="o">+</span> <span class="mi">1</span> <span class="k">in</span>
<span class="k">let</span> <span class="n">x</span> <span class="o">=</span> <span class="mi">3</span> <span class="k">in</span>
<span class="n">print</span> <span class="o">(</span><span class="n">inner</span> <span class="bp">()</span><span class="o">)</span>
</code>
python的闭包里的自由变量是按引用传递的,而不是按值传递,所以会有这个结果。<code class="language-python"><span class="k">def</span> <span class="nf">foo</span><span class="p">():</span>
<span class="k">def</span> <span class="nf">inner</span><span class="p">():</span>
<span class="k">return</span> <span class="n">x</span> <span class="o">+</span> <span class="mi">1</span>
<span class="n">x</span> <span class="o">=</span> <span class="mi">1</span>
<span class="k">print</span> <span class="n">inner</span><span class="p">()</span> <span class="c"># output 2</span>
<span class="n">x</span> <span class="o">=</span> <span class="mi">2</span>
<span class="k">print</span> <span class="n">inner</span><span class="p">()</span> <span class="c"># output 3</span>
</code>
这分明就是lexical scoping嘛,譬如说等价的C#代码
<code class="language-csharp"><span class="k">void</span> <span class="nf">Foo</span><span class="p">()</span>
<span class="p">{</span>
<span class="kt">int</span> <span class="n">x</span><span class="p">=</span><span class="m">1</span><span class="p">;</span>
<span class="n">Func</span><span class="p"><span class="kt">int</span><span class="p">></span> <span class="n">inner</span> <span class="p">=</span> <span class="p">()=></span><span class="n">x</span><span class="p">+</span><span class="m">1</span><span class="p">;</span>
<span class="n">x</span><span class="p">=</span><span class="m">3</span><span class="p">;</span>
<span class="n">Console</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span><span class="n">inner</span><span class="p">());</span>
<span class="p">}</span>
</span></code>
把楼主的代码改写成 lua 可以看看 Python 和 Lua 在处理上的不同:<code class="language-lua"><span class="k">function</span> <span class="nf">foo</span><span class="p">()</span>
<span class="k">function</span> <span class="nf">inner</span><span class="p">()</span>
<span class="k">return</span> <span class="n">x</span> <span class="o">+</span> <span class="mi">1</span>
<span class="k">end</span>
<span class="kd">local</span> <span class="n">x</span> <span class="o">=</span> <span class="mi">3</span>
<span class="nb">print</span><span class="p">(</span><span class="n">inner</span><span class="p">())</span>
<span class="k">end</span>
<span class="n">foo</span><span class="p">()</span>
</code>
题主所说的 现代化的编程语言指的是什么? js经过这么多代的更新迭代,现在也是这样~<code class="language-js"><span class="p">(</span><span class="kd">function</span> <span class="nx">foo</span><span class="p">()</span> <span class="p">{</span>
<span class="kd">function</span> <span class="nx">inner</span><span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">x</span><span class="o">+</span><span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">x</span> <span class="o">=</span> <span class="mi">3</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">inner</span><span class="p">());</span>
<span class="p">})();</span>
</code>
<span class="k">def</span> <span class="nf">foo</span><span class="p">():</span>
<span class="n">x</span> <span class="o">=</span> <span class="mi">1</span>
<span class="k">def</span> <span class="nf">inner</span><span class="p">():</span>
<span class="k">return</span> <span class="n">x</span> <span class="o">+</span> <span class="mi">1</span>
<span class="n">x</span> <span class="o">=</span> <span class="mi">3</span>
<span class="k">print</span> <span class="n">inner</span><span class="p">()</span>
<span class="n">foo</span><span class="p">()</span>
<span class="c"># 输出4</span>
我觉得完全没有背离啊。。