Table of Contents
回复内容:
Home Backend Development Python Tutorial 为什么 Python 不是 lexical scoping?

为什么 Python 不是 lexical scoping?

Jun 06, 2016 pm 04:23 PM
def print return

这似乎背离了现代程序设计语言的一般设计思路。

比如

1

2

3

4

5

6

<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>

Copy after login

回复内容:

这段代码是lexical scoping,静态作用域是指我们可以根据代码文本的位置,确定变量的存在区域。

按照python的LEGB(Local,Enclosing,Global,Built-in)规则,当调用inner()时,x实际上是在foo的scope中找到的。inner之所能够访问foo中的x,是因为inner is inside the text of foo,这正是lexical的含义
为什么 Python 不是 lexical scoping?
Bash是Dynamic Scoping的

1

2

3

4

5

<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>

Copy after login
你以为Python是

1

2

3

4

5

<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>

Copy after login
python的闭包里的自由变量是按引用传递的,而不是按值传递,所以会有这个结果。
这和scoping没有关系。
C++的lambda就可以选择capture by copy或者capture by reference. 根据之前阅读Python源码的经验(如果记错请指正),在题主的例子里面,这个inner是一个闭包。闭包在Python里面的实现方式是保存一个通往外部namespace的指针(可以理解成一个dictionary)。

楼主可以参看这个例子

1

2

3

4

5

6

7

<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>

Copy after login

这分明就是lexical scoping嘛,譬如说等价的C#代码


1

2

3

4

5

6

7

<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><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>

Copy after login
把楼主的代码改写成 lua 可以看看 Python 和 Lua 在处理上的不同:

第一个例子结果都是一样的,因为变量绑定的是引用而不是值。第二个例子:

1

2

3

4

5

6

7

8

9

<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>

Copy after login
题主所说的 现代化的编程语言指的是什么? js经过这么多代的更新迭代,现在也是这样~

1

2

3

4

5

6

7

<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>

Copy after login

1

2

3

4

5

6

7

8

<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>

Copy after login
我觉得完全没有背离啊。。
输出感觉当前 x 走的 這個問題很好回答:x是inner函數的環境變量,所以在inner的定義中出現的x其實就是對定義外面的,也就是inner的環境變量的一個引用而已。

函數只有在被調用的時候才會執行,你前面將置為1,後面又改為3,不過是改變了x的引用值而已,相當於給x重新賦值。然後執行inner函數,使用x所對應的值為3,因此答案就是4了。
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Detailed explanation of the usage of return in C language Detailed explanation of the usage of return in C language Oct 07, 2023 am 10:58 AM

The usage of return in C language is: 1. For functions whose return value type is void, you can use the return statement to end the execution of the function early; 2. For functions whose return value type is not void, the function of the return statement is to end the execution of the function. The result is returned to the caller; 3. End the execution of the function early. Inside the function, we can use the return statement to end the execution of the function early, even if the function does not return a value.

What is the execution order of return and finally statements in Java? What is the execution order of return and finally statements in Java? Apr 25, 2023 pm 07:55 PM

Source code: publicclassReturnFinallyDemo{publicstaticvoidmain(String[]args){System.out.println(case1());}publicstaticintcase1(){intx;try{x=1;returnx;}finally{x=3;}}}#Output The output of the above code can simply conclude: return is executed before finally. Let's take a look at what happens at the bytecode level. The following intercepts part of the bytecode of the case1 method, and compares the source code to annotate the meaning of each instruction in

How does Vue3 use setup syntax sugar to refuse to write return How does Vue3 use setup syntax sugar to refuse to write return May 12, 2023 pm 06:34 PM

Vue3.2 setup syntax sugar is a compile-time syntax sugar that uses the combined API in a single file component (SFC) to solve the cumbersome setup in Vue3.0. The declared variables, functions, and content introduced by import are exposed through return, so that they can be used in Vue3.0. Problems in use 1. There is no need to return declared variables, functions and content introduced by import during use. You can use syntactic sugar //import the content introduced import{getToday}from'./utils'//variable constmsg='Hello !'//function func

Use the return keyword in JavaScript Use the return keyword in JavaScript Feb 18, 2024 pm 12:45 PM

Usage of return in JavaScript requires specific code examples In JavaScript, the return statement is used to specify the value returned from a function. Not only can it be used to end the execution of a function, it can also return a value to the place where the function was called. The return statement has the following common uses: Return a value The return statement can be used to return a value to the place where the function is called. Here is a simple example: functionadd(a,b){

Detailed explanation of JavaScript function return values ​​and return statements Detailed explanation of JavaScript function return values ​​and return statements Aug 04, 2022 am 09:46 AM

JavaScript functions provide two interfaces to interact with the outside world. The parameters serve as the entrance to receive external information; the return value serves as the outlet to feed back the operation results to the outside world. The following article will take you to understand the JavaScript function return value and briefly analyze the usage of the return statement. I hope it will be helpful to you!

How to use return statement in JavaScript How to use return statement in JavaScript Feb 26, 2024 am 09:21 AM

How to use return in JavaScript requires specific code examples. In JavaScript, return is a very important keyword. It is usually used to return a value in a function or end the execution of a function. The return statement is used to return a value to the caller of the function and terminate the execution of the function. The return statement can be used anywhere in a function and can return any JavaScript data type, including numbers, strings, booleans,

How to use return value in Python How to use return value in Python Oct 07, 2023 am 11:10 AM

Python return value return usage is that when the function executes the return statement, execution will stop immediately and the specified value will be returned to the place where the function was called. Detailed usage: 1. Return a single value; 2. Return multiple values; 3. Return a null value; 4. End the execution of the function early.

Where is print on the keyboard? Where is print on the keyboard? Jun 19, 2023 am 09:37 AM

The printscreen key is on the arrow keys of the keyboard device, with the words "prtsc sysrq" on it, and is located to the right of f12. If there is no button with the word "prtsc sysrq", you can find "fn" and "insert(prt sc)", click "fn" first, and then click "insert(PRT sc)" to realize the printscreen screenshot function.

See all articles