python 全局变量使用报错没有定义_Python变量作用域代码解析
本篇文章小編給大家分享一下Python變量作用域代碼解析,文章代碼介紹的很詳細(xì),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家供大家參考,有需要的小伙伴們可以來(lái)看看。
特點(diǎn)
python的作用域是靜態(tài)的,在源代碼中變量名被賦值的位置決定了該變量能被訪(fǎng)問(wèn)的范圍。即Python變量的作用域由變量所在源代碼中的位置決定。Python中并不是所有的語(yǔ)句塊中都會(huì)產(chǎn)生作用域。只有當(dāng)變量在Module(模塊)、Class(類(lèi))、def(函數(shù))中定義的時(shí)候,才會(huì)有作用域的概念。
1. 函數(shù)內(nèi)部的變量,函數(shù)外部不能訪(fǎng)問(wèn)
def func():
variable = 100
print(variable)
print(variable) # name 'variable' is not defined
2. 函數(shù)上層的變量(標(biāo)量)只能讀取,不能再次定義,初始化
def counter1():
n = 0
def compute():
n = n + 1 # n為標(biāo)量(數(shù)值,字符串,浮點(diǎn)數(shù)),Python程序會(huì)因?yàn)椤叭绻麅?nèi)部函數(shù)有引用外部函數(shù)的同名變量或者全局變量,并且對(duì)這個(gè)變量有修改.那么python會(huì)認(rèn)為它是一個(gè)局部變量,又因?yàn)楹瘮?shù)中沒(méi)有n的定義和賦值,所以報(bào)錯(cuò)
# y = n + 1 # 更改為y就沒(méi)事
# return y
return n
return compute
variable = 300
def test_scopt():
print(variable) # 此時(shí)調(diào)用局部變量variable并有沒(méi)綁定到一個(gè)內(nèi)存對(duì)象(沒(méi)有定義和初始化,即沒(méi)有賦值)。本質(zhì)上還是遵循的LEGB法則
variable = 200 #因?yàn)檫@里,前面調(diào)用過(guò)一次,所以variable就變?yōu)榱司植孔兞?/p>
# print(variable) # 寫(xiě)在下面就沒(méi)問(wèn)題,因?yàn)関ariable是新的局部變量,而不是重新被定義,卻沒(méi)有綁定
test_scopt()
Python中的模塊代碼在執(zhí)行之前,并不會(huì)經(jīng)過(guò)預(yù)編譯,但是模塊內(nèi)的函數(shù)體代碼在運(yùn)行前會(huì)經(jīng)過(guò)預(yù)編譯,因此不管變量名的綁定發(fā)生在作用域的那個(gè)位置,都能被編譯器知道。Python雖然是一個(gè)靜態(tài)作用域語(yǔ)言,但變量名查找是動(dòng)態(tài)發(fā)生的,直到在程序運(yùn)行時(shí),才會(huì)發(fā)現(xiàn)作用域方面的問(wèn)題,
3. list,dict等復(fù)合變量里面的值都可以引用更改
def counter():
n = [0]
def compute():
n[0] += 1 # 更改的是n里面的第一個(gè)值,不是更改n
return n[0]
return compute
func = counter()
func() # 1
func() # 2
func() # 3
4. global 聲明全局變量,如果在局部要對(duì)全局變量修改,需要在局部也要先聲明該全局變量
def counter1():
n = 0
def compute():
global n # 如果在局部要對(duì)全局變量修改,需要在局部也要先聲明該全局變量,但此處也會(huì)報(bào)錯(cuò),因?yàn)闆](méi)有全局變量n
n += 1
return n
return compute
# right
def counter1():
global n
n = 0
def compute():
global n
n += 1
return n
return compute
5. nonlocal關(guān)鍵字用來(lái)在函數(shù)或其他作用域中使用外層(非全局)變量
def make_counter():
count = 0
def counter():
nonlocal count # 使用外層非全局變量
count += 1
return count
return counter
作用域的類(lèi)型
在Python中,使用一個(gè)變量時(shí)并不嚴(yán)格要求需要預(yù)先聲明它,但是在真正使用它之前,它必須被綁定到某個(gè)內(nèi)存對(duì)象(被定義、賦值);這種變量名的綁定將在當(dāng)前作用域中引入新的變量,同時(shí)屏蔽外層作用域中的同名變量。
L(local)局部作用域
局部變量:包含在def關(guān)鍵字定義的語(yǔ)句塊中,即在函數(shù)中定義的變量。每當(dāng)函數(shù)被調(diào)用時(shí)都會(huì)創(chuàng)建一個(gè)新的局部作用域。Python中也有遞歸,即自己調(diào)用自己,每次調(diào)用都會(huì)創(chuàng)建一個(gè)新的局部命名空間。在函數(shù)內(nèi)部的變量聲明,除非特別的聲明為全局變量,否則均默認(rèn)為局部變量。有些情況需要在函數(shù)內(nèi)部定義全局變量,這時(shí)可以使用global關(guān)鍵字來(lái)聲明變量的作用域?yàn)槿帧>植孔兞坑蚓拖褚粋€(gè)
棧,僅僅是暫時(shí)的存在,依賴(lài)創(chuàng)建該局部作用域的函數(shù)是否處于活動(dòng)的狀態(tài)。所以,一般建議盡量少定義全局變量,因?yàn)槿肿兞吭谀K文件運(yùn)行的過(guò)程中會(huì)一直存在,占用內(nèi)存空間。
注意:如果需要在函數(shù)內(nèi)部對(duì)全局變量賦值,需要在函數(shù)內(nèi)部通過(guò)global語(yǔ)句聲明該變量為全局變量。
E(enclosing)嵌套作用域
E也包含在def關(guān)鍵字中,E和L是相對(duì)的,E相對(duì)于更上層的函數(shù)而言也是L。與L的區(qū)別在于,對(duì)一個(gè)函數(shù)而言,L是定義在此函數(shù)內(nèi)部的局部作用域,而E是定義在此函數(shù)的上一層父級(jí)函數(shù)的局部作用域。主要是為了實(shí)現(xiàn)Python的閉包,而增加的實(shí)現(xiàn)。
G(global)全局作用域
即在模塊層次中定義的變量,每一個(gè)模塊都是一個(gè)全局作用域。也就是說(shuō),在模塊文件頂層聲明的變量具有全局作用域,從外部開(kāi)來(lái),模塊的全局變量就是一個(gè)模塊對(duì)象的屬性。
注意:全局作用域的作用范圍僅限于單個(gè)模塊文件內(nèi)
B(built-in)內(nèi)置作用域
系統(tǒng)內(nèi)固定模塊里定義的變量,如預(yù)定義在builtin 模塊內(nèi)的變量。
作用域鏈:變量名解析LEGB法則
搜索變量名的優(yōu)先級(jí):局部作用域 > 嵌套作用域 > 全局作用域 > 內(nèi)置作用域
LEGB法則: 當(dāng)在函數(shù)中使用未確定的變量名時(shí),Python會(huì)按照優(yōu)先級(jí)依次搜索4個(gè)作用域,以此來(lái)確定該變量名的意義。首先搜索局部作用域(L),之后是上一層嵌套結(jié)構(gòu)中def或lambda函數(shù)的嵌套作用域(E),之后是全局作用域(G),最后是內(nèi)置作用域(B)。按這個(gè)查找原則,在第一處找到的地方停止。如果沒(méi)有找到,則會(huì)出發(fā)NameError錯(cuò)誤。
example 1
name = "lzl"
def f1():
print(name)
def f2():
name = "eric"
f1()
f2() # 在函數(shù)未執(zhí)行之前,作用域鏈就已經(jīng)形成了,此時(shí)f1()的上一級(jí)應(yīng)該name = 'lzl'
example 2
def scope_test():
def do_local():
spam = "local spam" # 此函數(shù)定義了另外的一個(gè)spam字符串變量,并且生命周期只在此函數(shù)內(nèi)。此處的spam和外層的spam是兩個(gè)變量,如果寫(xiě)出spam = spam + “l(fā)ocal spam” 會(huì)報(bào)錯(cuò)
def do_nonlocal():
nonlocal spam # 使用外層的spam變量 test spam
spam = "nonlocal spam"
def do_global():
global spam
spam = "global spam"
spam = "test spam"
do_local()
print("After local assignmanent:", spam) # test spam
do_nonlocal()
print("After nonlocal assignment:",spam) # nonlocal spam
do_global()
print("After global assignment:",spam) # nonlocal spam ???? 先找是本地變量,找到的本地變量已經(jīng)在do_nonlocal()里面改變了所以輸出的是nonlocal spam
scope_test()
print("In global scope:",spam) # global spam
總結(jié)
以上是生活随笔為你收集整理的python 全局变量使用报错没有定义_Python变量作用域代码解析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: ajax和fetch哪个好,axios和
- 下一篇: 计算机网络运输层的概述,计算机网络_运输