一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

腳本之家,腳本語言編程技術(shù)及教程分享平臺!
分類導(dǎo)航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務(wù)器之家 - 腳本之家 - Python - Python編程中閉包的變量作用域問題解析

Python編程中閉包的變量作用域問題解析

2022-02-15 15:24曉鵬-King Python

這篇文章主要介紹了Python編程中閉包的變量作用域問題解析,在學(xué)習(xí)Python的返回函數(shù)的時候,我發(fā)現(xiàn)里面涉及了幾個問題,在這里為大家分享講解下

閉包

? 在我們使用返回函數(shù)的時候,由于我們在一個函數(shù)中需要返回另一個函數(shù),因此,我們在這個函數(shù)中就需要重新定義一個函數(shù)。而這樣,就造成了我們的函數(shù)嵌套問題。外面的函數(shù)相對于里面的函數(shù)而言是外函數(shù)(outer function),而里面的我們叫他內(nèi)函數(shù)(inner function)。

?
1
2
3
4
5
6
7
def outerFunction(): #外函數(shù)
    def innerFunction(): #內(nèi)函數(shù)
        x = 1
        return x
    return innerFunction #返回值是一個函數(shù)
a = outerFunction()
print(a)

這里我們打印 a 的值得時候,實際上打印的是我們的返回函數(shù)的地址 :

<function outerFunction.<locals>.innerFunction at 0x0000019C278C0E50>

? 一般情況下,我們在使用函數(shù)作為返回值得時候,我們會在內(nèi)函數(shù)中使用我們外函數(shù)中的變量,這種情況就會產(chǎn)生一個有意思的事情了。內(nèi)函數(shù)會被返回給外部的其他調(diào)用者,而我們的變量是在我們的外函數(shù)中定義的。此時,我們的變量的作用域會發(fā)生怎樣的變化呢?

測試:

?
1
2
3
4
5
6
7
def outerFunction(x): #外函數(shù)
    y = 10
    def innerFunction(): #內(nèi)函數(shù)
        return x + y
    return innerFunction #返回值是一個函數(shù)
a = outerFunction(10)
print(a())

?打印:

20

? 這里可以看到,我們的在給 a 賦值的時候,同時給外函數(shù)傳進去了一個值10,然后,我們直接把 a() 打印出來,此時,我們的 a 返回了 20,說明我們的變量和參數(shù)在進入內(nèi)函數(shù)后,我們的內(nèi)函數(shù)會保留這個變量的值。

? 這里,我們把這種現(xiàn)象叫做“閉包(Closure)”,我試著多次返回這個內(nèi)函數(shù),看看他們的地址是否一致:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
def outerFunction(x): #外函數(shù)
    y = 10
    def innerFunction(): #內(nèi)函數(shù)
        return x + y
    return innerFunction #返回值是一個函數(shù)
a = outerFunction(10)
b = outerFunction(20)
c = outerFunction(30)
print(a())
print(b())
print(c())
print(a)
print(b)
print(c)

? 打印:

20
30
40
<function outerFunction.<locals>.innerFunction at 0x0000020C480C0DC0>
<function outerFunction.<locals>.innerFunction at 0x0000020C480C0D30>
<function outerFunction.<locals>.innerFunction at 0x0000020C480CD280>

? 這里我們可以看到每個 innerFunction 的地址都不同,當(dāng)我們多次調(diào)用返回函數(shù)的時候,每調(diào)用一次,我們的返回函數(shù)就會新創(chuàng)建一個函數(shù)給我們的變量。

? 那么,如果我們在外函數(shù)里面多次調(diào)用我們的內(nèi)函數(shù),我們的外函數(shù)的變量的作用域是什么樣的呢?

? 我們測試一下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def outerFunction(x): #外函數(shù)
    L=[] #定義一個List
    y = 10
    for i in range(1, 4):
        def innerFunction(): #內(nèi)函數(shù)
            return (x + y) * i #使用我們外函數(shù)得變量
        print(innerFunction()) #打印內(nèi)函數(shù)返回得值
        #print(innerFunction)
        L.append(innerFunction) #把內(nèi)函數(shù)添加到我們得List中
    return L #返回這個List
a = outerFunction(10)
print(a[0])
print(a[1])
print(a[2])
print(a[0]())
print(a[1]())
print(a[2]())

? 看打印:

20
40
60
<function outerFunction.<locals>.innerFunction at 0x00000274AD6B0E50>
<function outerFunction.<locals>.innerFunction at 0x00000274AD6BD040>
<function outerFunction.<locals>.innerFunction at 0x00000274AD6BD3A0>
60
60
60

? 這里我們可以看到一個有意思得現(xiàn)象:

? 當(dāng)我們在我們的函數(shù)內(nèi)多次調(diào)用我們的內(nèi)函數(shù),并把它的返回值打印出來的時候,我們可以看到這個值是正常的(依次遞增)。而如果我們把這個內(nèi)函數(shù)傳遞到我們的 List 中,在函數(shù)外部調(diào)用它的時候,我們的函數(shù)的返回值全部變成了 60 也就是他們的只得到了我們外函數(shù)中變量的最終的值。這個就是我們的閉包特有的現(xiàn)象。

閉包中的變量

? 一般情況下,當(dāng)一個函數(shù)結(jié)束的時候,在內(nèi)存中,我們這個函數(shù)內(nèi)部的局部變量會連同這個函數(shù)一起被釋放掉。

? 但是,當(dāng)我們這個函數(shù)包含閉包的時候,也就是說,當(dāng)這個函數(shù)的返回值是一個函數(shù)的引用的時候。此時,當(dāng)這個函數(shù)結(jié)束時,由于它內(nèi)部的局部變量需要被釋放掉,因此,它會把這個變量的值給傳遞給它所要返回的這個函數(shù)的內(nèi)部。正是因為這樣,當(dāng)我們在外部調(diào)用我們的返回函數(shù)的時候,我們會看到它使用的變量全都是這個變量在函數(shù)內(nèi)的最終的值,因為這個變量是這個外函數(shù)在結(jié)束的時候才傳遞給我們的返回函數(shù)的。而此時,我們函數(shù)內(nèi)的變量只能有一個值。

? 但是,我們可以使用另一個辦法來規(guī)避這種情況:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def outerFunction(x): #外函數(shù)
    L=[] #定義一個List
    y = 10
    def innerFunction(i): #內(nèi)函數(shù)
        def f():
            return (x + y) * i #使用我們外函數(shù)得變量
        return f
    for i in range(1, 4):
        print(innerFunction(i)()) #打印內(nèi)函數(shù)中的內(nèi)函數(shù)的返回值
        L.append(innerFunction(i)) #把內(nèi)函數(shù)添加到我們得List中
    return L #返回這個List
a = outerFunction(10)
print(a[0])
print(a[1])
print(a[2])
print(a[0]())
print(a[1]())
print(a[2]())

? 打印如下:

20
40
60
<function outerFunction.<locals>.innerFunction.<locals>.f at 0x00000155B0F80040>
<function outerFunction.<locals>.innerFunction.<locals>.f at 0x00000155B0F803A0>
<function outerFunction.<locals>.innerFunction.<locals>.f at 0x00000155B0F80430>
20
40
60

? 這里我們可以看到我們在外部調(diào)用的時候,函數(shù)的返回值和在內(nèi)部調(diào)用的返回值是一樣的。那么我們分析一下這個函數(shù)的執(zhí)行過程以及函數(shù)內(nèi)的變量的作用域情況。

? 首先,我們在我們由于的內(nèi)函數(shù)的基礎(chǔ)又添加了一層內(nèi)函數(shù) f() ,并且,在這個內(nèi)函數(shù)里面,我們使用了外部的內(nèi)函數(shù) innerFunction 的參數(shù)作為了返回值。然后,我們在 for 循環(huán)內(nèi)部把我們的 innerFunction 這個函數(shù)的返回值添加進來我們的 List 里面。

? 這里我們應(yīng)該已經(jīng)發(fā)現(xiàn)了。在 for 循環(huán)內(nèi)部,當(dāng)我們把 innerFunction 的返回值 f 添加到我們的 List 中的時候,由于 innerFunction 相對于函數(shù) f() 而言,f() 是屬于 innerFunction 的內(nèi)函數(shù)的,因此,當(dāng)我們返回 f() 這個函數(shù)的時候,此時,f() 函數(shù)內(nèi)部使用的值就是它的最終值了,而此時,我們的 innerFunction 函數(shù)還在 for 循環(huán)內(nèi)部,因此,在循環(huán)內(nèi)部,每次調(diào)用我們的 innerFunction 的返回值時,我們的傳遞到我們的 f() 函數(shù)中的值就是我們的最終值了。

? 此時,即使是我們在外部調(diào)用這個 f() 函數(shù),它返回的值和內(nèi)部調(diào)用時也是一樣的。

以上就是Python編程中閉包的變量作用域問題解析的詳細內(nèi)容,更多關(guān)于Python閉包中變量作用域的資料請關(guān)注服務(wù)器之家其它相關(guān)文章!

原文鏈接:https://blog.csdn.net/qq_25827755/article/details/120859552

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 国产a免费观看 | 小早川怜子视频在线观看 | 2020最新版的ab片 | 久久精品国产清白在天天线 | 色老板在线免费视频 | 精品成人一区二区三区免费视频 | 亚洲黄色三级视频 | 美女扒开两腿露出尿口的视频 | 久久精品国产只有精品 | 国产精品一级片 | 国内精品视频一区二区三区 | 99国产精品热久久久久久夜夜嗨 | 暖暖 免费 高清 日本 在线 | 亚洲性视频在线观看 | 999久久精品国产 | 91麻豆精品国产 | 操碰人人| 青青草一区二区免费精品 | 午夜视频网站 | 成人小视频在线免费观看 | 乳环贵妇堕落开发调教番号 | 日本不卡视频免费的 | 门房秦大爷在线阅读 | 男人猛进猛出女人下面视频 | 星星动漫在线观看无删减 | 农村妇女野外性生话免费视频 | 国产91素人搭讪系列天堂 | 小小水蜜桃视频高清在线播放 | 特级夫妻大片免费在线播放 | 色8 | 色伦网 | 亚洲AV蜜桃永久无码精品红樱桃 | 美女禁区视频无遮挡免费看 | 大好硬好深好爽想要视频 | 久草在线福利资站免费视频 | 娇小XXXXX第一次出血 | 日韩一区二区三区不卡视频 | 国色天香社区视频免费观看3 | 大学生按摩黄a级中文片 | 福利三区 | 亚洲 色 欧美 爱 视频 日韩 |