久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

如何避開變量作用域的陷阱

 豬一樣迷人 2019-12-14

講這個知識點之前,,先看一個例子:

x=99
def func1():
global x
x=88

def func2():
global x
x=77

問題:大家覺得x最后的是值到底是多少:88還是77,?先思考一下,最后我來揭曉謎底....

python的變量跟其他語言一樣,,分為全局變量和局部變量,,這個概念比較好理解,我們來看看python中是如何實現(xiàn)的:

1.全局變量與局部變量

x=100
def func():
print ('Inside func: x is {}'.format(x))
func()
print 'x is still:{}'.format(x)

>> # 打印結果
Inside func: x is 100
x is still:100

這個比較好理解x是全局變量,,作用域是整個文件,函數(shù)內(nèi)部是可以引用的.接著看下面一個例子:

x=100
def func():
x=10 #多了這一行
print ('Changed local x to :{}'.format(x))

func()
print 'x is still:{}'.format(x)

>>># 打印結果
Changed local x to :10
x is still:100 

大家看在函數(shù)外部有一個變量x,在函數(shù)內(nèi)部也有一個變量x,這兩個變量雖然名字長的一樣,,但是是完全不同的:

函數(shù)內(nèi)部的是本地變量,它的生命周期只在函數(shù)內(nèi)部,,出了函數(shù)就結束了,

而x在函數(shù)外部模塊文件中聲明的(python一個文件也叫一個模塊),,是全局變量,不會被函數(shù)里面的局部變量影響,所以最后print的x還是100,

有人要問了,有的時候我需要讓這個全局變量在函數(shù)里面處理,,改變它的值,,怎么辦?這個python早就考慮到了,,往下看~~

2.全局變量聲明:

x=100
def func():
global x #注意加了一個global 關鍵字,,表示x是全局作用域
print 'x is :{}'.format(x)
x=10
print ('Changed local x to :{}'.format(x))

func()
print 'Value of x:{}'.format(x)

>>> # 打印結果
x is :100
Changed local x to :10
Value of x:10

這個函數(shù)內(nèi)部多了一個global關鍵字,結果就差很多:

原因在于x被聲明為函數(shù)內(nèi)的全局變量,,通過global這個語句是自己明確地映射到了模塊的作用域

函數(shù)內(nèi)對x重新賦值x=10,會改變函數(shù)外x的值,所以最后print x是10

全局變量簡單說就是這3點:

全局變量是位于模塊文件內(nèi)部的頂層的變量名

全局變量如果是在函數(shù)內(nèi)被改變的話,,一定要用global

全局變量名在函數(shù)內(nèi)部不經(jīng)過聲明也可以被引用

3.函數(shù)內(nèi)的變量解析原則

有的書上叫LEGB法則,其實講白了就是下面4個過程,當在函數(shù)中使用沒有聲明過的變量時,,python的搜索順序是:

先是在函數(shù)內(nèi)部的本地作用域(L)  

然后是在上一層的函數(shù)的本地作用域(E)

然后是全局作用域(G)

最后是內(nèi)置作用域(B)

簡單說就是從局部到中央,,好比你找一個人,村里找不到找鄉(xiāng)->鄉(xiāng)里找不到找市里->市里找不到找到全國檔案局

我們來一一解釋一下這些原則

1).本地函數(shù)

在函數(shù)內(nèi)部(def或者lambda)通過任何方式賦值的,,而且沒有在該函數(shù)內(nèi)聲明為全局變量的變量名

2).上層函數(shù)的本地作用域

python函數(shù)是支持嵌套,,而且多層嵌套,當你在最里層的函數(shù)找不到這個變量的時候,,會往上一層的函數(shù)找,,一層一層由內(nèi)往外找,舉個例子

def f1():
x=100
def f2():
print
f2()

print f1()
>>
100
None 

#因為f2()打印了之后沒有return,對沒有return的函數(shù)就默認返回None

我來解釋一下:

def定義了一個f1()函數(shù),里面又嵌套了一個f2()函數(shù),這個def生成了一個函數(shù)并將其賦值給變量名f2

f2是f1的本地作用域內(nèi)的一個本地變量,可以把f2看做一個臨時函數(shù),僅僅在f1內(nèi)部執(zhí)行的過程中存在.

f2函數(shù)干了一件事打印x,當在f2()內(nèi)部找不到的時候,,就通過LEGB法則往上找,,f1()里面找到了x.

3).全局(模塊)

在模塊文件的頂層賦值的變量名,或者在該文件中的def生成的名為全局變量的變量名(函數(shù)內(nèi)global聲明的變量)

4).內(nèi)置的作用域

這個很多初學者不明白,,啥內(nèi)置,,內(nèi)置了什么,其實很簡單,python在運行之前會自動的引用一個內(nèi)置模塊,叫做__builein__,這是python的一個標準庫模塊,,直接import進來,,可以用dir(__builein__)看一下,,里面都是預定義的一些變量名

是不是看到了很多熟悉的面孔(type,sum.sorted,open),,對的那些就是內(nèi)置的變量名,前面3種方法都找不到了就會去內(nèi)置作用域這個列表里面.

換句話時候若你本地變量有一個跟內(nèi)置變量一樣的,就會被本地變量覆蓋 

def hider():
sum='newsum'
return sum([1,2,3])

print hider()
>>TypeError: 'str' object is not callable

就是因為LEGB法則,,本地的sum變量把內(nèi)置作用域的sum變量覆蓋了

下面總結一下:

開頭的例子的答案,,其實X的值不是88也不是77,而是都有可能,,因為不確定你先調(diào)用那個函數(shù),變量的值取決于函數(shù)調(diào)用的順序,,而函數(shù)自身是任意順序進行排列的,所以88,77都有可能,看哪個函數(shù)最后調(diào)用.

這會導致很難debug,,你必須要跟蹤整個程序的控制流程,這其實就引出了另外一個話題,,全局變量有相關性,用全局變量來記憶狀態(tài)信息太復雜,最后是通過面向對象的方法,,用類進行封裝.

    本站是提供個人知識管理的網(wǎng)絡存儲空間,,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點,。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導購買等信息,謹防詐騙,。如發(fā)現(xiàn)有害或侵權內(nèi)容,,請點擊一鍵舉報。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多