關(guān)于Python函數(shù)對(duì)象的名稱空間和作用域
1.函數(shù)對(duì)象
前面我們學(xué)習(xí)了關(guān)于Python中的變量類型,例如int、str、bool、list等等……,其實(shí)函數(shù)我們可以去理解為一種更加高級(jí)的變量類型,也就是函數(shù)對(duì)象,其實(shí)是一個(gè)更加高級(jí)的變量容器,我們可以去把函數(shù)對(duì)象當(dāng)做一個(gè)變量去使用。
(1)函數(shù)對(duì)象的引用
一個(gè)函數(shù)對(duì)象的形成是先定義一個(gè)函數(shù),然后寫入函數(shù)體,最后把這個(gè)函數(shù)賦值給一個(gè)變量,也就是函數(shù)的對(duì)象,然后我們可以去通過這個(gè)函數(shù)變量來實(shí)現(xiàn)函數(shù)相應(yīng)的功能。(先賦值,再調(diào)用)
示例1:
#定義一個(gè)函數(shù)對(duì)象fun def fun(): print('hello word',end=' ') print('wwww') fun() #直接調(diào)用這個(gè)函數(shù)對(duì)象
這種寫法是最直接的,沒有返回值。
示例2:
def fun(): print('ww') return 123 kun = fun() print(kun,type(kun)) #輸出結(jié)果:ww # 123 <class 'int'>
這個(gè)寫法是定義了一個(gè)kun在變量,作為fun函數(shù)的對(duì)象,我們可以去通過這個(gè)對(duì)象去處理這個(gè)函數(shù)的返回值。
示例3:
def fun(): return 123 kun = fun print(kun,type(kun)) #輸出結(jié)果:<function fun at 0x00000154828AD280> <class 'function'>
這里我沒有加上()所以輸出結(jié)果是fun這個(gè)變量的地址,
示例4:
def fun(): return 123 kun = fun print(kun(),type(kun)) #輸出結(jié)果:123 <class 'function'>
這里先定義一個(gè)kun變量為fun的函數(shù)對(duì)象,下面如果要去調(diào)用這個(gè)函數(shù)的話就必須加上括號(hào),如果沒有括號(hào)那這個(gè)對(duì)象只是函數(shù)的地址。
(2)函數(shù)可以放到序列里面
函數(shù)的返回值是一種變量類型,同時(shí)序列可以儲(chǔ)存變量,所以函數(shù)是可以放到序列里面去
這里就以列表為例子:
def fun(): return '牛馬' kun = fun li=[1,5,kun] print(li) print(li[2]()) #輸出結(jié)果:[1, 5, <function fun at 0x000001BFB1ABD280>] # 牛馬
(3)函數(shù)可以作為參數(shù) , 傳遞給另一個(gè)函數(shù)
示例:
def fun(): return '牛馬' def ff(st): print(f'我是{st}') ff(fun()) #輸出結(jié)果:我是牛馬
(4)函數(shù)可以作為另一個(gè)函數(shù)的返回值
def ff(): print('我愛你') return 520 def fun(): return ff() a=fun() print(a,type(a)) #輸出結(jié)果:我愛你 # 520 <class 'int'>
這里是fun函數(shù)返回值為ff函數(shù),實(shí)際上是經(jīng)歷過了fun函數(shù)的功能,然后再次經(jīng)歷ff函數(shù)的功能,最后返回的是ff函數(shù)的520,故a的結(jié)果是520
2.名稱空間
數(shù)據(jù)的名稱是儲(chǔ)存到棧區(qū),而數(shù)據(jù)的內(nèi)容是儲(chǔ)存到堆區(qū),當(dāng)我們要去使用數(shù)據(jù)的內(nèi)容時(shí),我們可以通過數(shù)據(jù)的名稱來直接去表示數(shù)據(jù)的內(nèi)容,也就是通過棧區(qū)去找到堆區(qū)的東西,然后在堆區(qū)拿出來去使用。棧區(qū)和堆區(qū)是有對(duì)應(yīng)關(guān)系的。
1.內(nèi)建名稱空間
生命周期:會(huì)隨著Python啟動(dòng)而生成,程序關(guān)閉會(huì)摧毀
保存的數(shù)據(jù):內(nèi)置函數(shù)(input,print....)
生成順序:程序里最先生成的
2.全局名稱空間
生命周期:會(huì)隨著Python啟動(dòng)而生成,程序關(guān)閉會(huì)摧毀
保存的數(shù)據(jù):函數(shù)名,變量名
生成順序:在內(nèi)建名稱空間的后面
3.局部名稱空間
生命周期:隨著函數(shù)的調(diào)用而生成,函數(shù)調(diào)用接受后就關(guān)閉
保存的數(shù)據(jù):函數(shù)內(nèi)定義的名字
生成順序:隨著函數(shù)的調(diào)用而生成
所以,我們定義的函數(shù)是屬于局部名稱空間,當(dāng)函數(shù)被調(diào)用完成了之后就會(huì)被銷毀,里面變量?jī)?chǔ)存到的棧堆區(qū)都會(huì)被銷毀
3.作用域
(1)作用域的理解
作用域?qū)嶋H上就是變量的作用范圍,之前我們學(xué)了C語(yǔ)言都知道,有全局變量和局部變量,比如在for循環(huán)里面,里面的變量是一種局部變量,我們?nèi)绻谥骱瘮?shù)外面去定義一個(gè)變量,那就是全局變量。Python也是一樣的道理,變量也是有相應(yīng)的作用域。而變量的作用域是由定義的位置決定的
全局變量與局部變量的名字相同的時(shí)候,實(shí)質(zhì)上是兩個(gè)不同的變量, 其棧堆區(qū)是完全不一樣的!所以我們不可以通過局部來改變?nèi)肿兞?,否則就報(bào)錯(cuò)
示例1:
#定義一個(gè)全局變量a a=15 def fun(): a=999 print('hhh') fun() print(a) #輸出結(jié)果:15
因?yàn)楹瘮?shù)是放到棧堆區(qū),當(dāng)函數(shù)調(diào)用完成了之后返回一個(gè)值,這個(gè)函數(shù)已經(jīng)被銷毀了,那么里面的變量也會(huì)與之銷毀,所以不會(huì)影響到全局變量,故a的值還是15
示例2:
#定義一個(gè)全局變量a a=15 def fun(): a=999 return a print(fun()) print(a) #輸出結(jié)果:999 # 15
這個(gè)函數(shù)調(diào)用完成了之后就返回一個(gè)值,這個(gè)值函數(shù)內(nèi)部的功能的值,但是并沒有對(duì)這個(gè)函數(shù)以外的值進(jìn)行修改,所以a的結(jié)果還是15,而函數(shù)的返回值是999
示例3:
b=15 def fun(): b=b+99 fun() print(b) #輸出結(jié)果:系統(tǒng)報(bào)錯(cuò)
因?yàn)閎是一個(gè)全局變量,而函數(shù)里面的b是一個(gè)重新定義的局部變量,所以我們不可以去直接修改這個(gè)局部變量b,因?yàn)檫@個(gè)b是沒有初始數(shù)值的,而且類型也未定,所以無法進(jìn)行運(yùn)算處理
對(duì)比
b=15 def fun(): b=0 b+=99 print(b) fun() print(b) #輸出結(jié)果:99 15
對(duì)于這個(gè)而言,我給了函數(shù)里面b一個(gè)初始化值,所以可以進(jìn)行運(yùn)算處理,但這個(gè)b與外部全局變量的b是完全不相同,是兩個(gè)不同的變量
(2)作用域的轉(zhuǎn)換
在C語(yǔ)言中我們可以去設(shè)置靜態(tài)變量(static),從而使得這個(gè)變量可以在函數(shù)進(jìn)行修改,同樣Python中可以利用關(guān)鍵字去修改變量的作用域,把局部變量作用到全局變量,或者把全局變量作用降級(jí)為局部
1.global 關(guān)鍵字 (局部變?nèi)?
在函數(shù)中,變量是這個(gè)函數(shù)的局部變量,只僅僅作用到函數(shù)內(nèi)部,我們對(duì)這個(gè)變量進(jìn)行修改是不會(huì)影響外面的變量的,如果把這個(gè)局部變量轉(zhuǎn)換為全局變量的話,那么這變量就可以在函數(shù)里面進(jìn)行修改,而且還可以影響到外部,當(dāng)新定義global的變量名字與之前已有的變量名字出現(xiàn)重復(fù)的話,新的變量?jī)?nèi)容會(huì)把之前的給覆蓋掉,而且新的全局變量也可以在函數(shù)內(nèi)部進(jìn)行修改,從而影響全局。
注意事項(xiàng):這個(gè)關(guān)鍵字是作用到全局變量,這個(gè)全局變量的棧堆區(qū)不會(huì)被銷毀
b=15 def fun(): b=123 fun() print(b) #函數(shù)里面的b與外面的b是不同性質(zhì)的?。?! #輸出結(jié)果:15
對(duì)比
b=15 def fun(): global b b=123 fun() print(b) #輸出結(jié)果:123
重新定義了一個(gè)global后,此時(shí)這個(gè)b已經(jīng)是一個(gè)新的全局變量因?yàn)榍懊嬉呀?jīng)有了一個(gè)全局變量b,所以這個(gè)新的全局變量會(huì)因?yàn)槊窒嗤瑫?huì)把之前的全局變量b給直接覆蓋掉(類似于類型相同且名字相同的文件會(huì)被新的給覆蓋),故輸出結(jié)果是新的全局變量b的結(jié)果:123
2.nonlocal 關(guān)鍵字 (全局變局部)
功能:降權(quán),全局變成局部
前面講到過,已知一個(gè)全局變量,但是我不可以在函數(shù)里面對(duì)這個(gè)全局變量進(jìn)行修改,而且函數(shù)里面的變量都是新的變量,既是跟外面的全局變量名字一模一樣,但是其儲(chǔ)存的棧堆區(qū)是完全不同的,那么當(dāng)我想去通過一個(gè)局部函數(shù)來修改這個(gè)全局變量的話,這時(shí)候我就可以通過nonlocal關(guān)鍵字來進(jìn)行 降維處理 。
注意事項(xiàng):這個(gè)關(guān)鍵字是作用于嵌套函數(shù)的外部變量(相較于內(nèi)部函數(shù),外部函數(shù)是“全局”),這個(gè)變量的棧堆區(qū)會(huì)被銷毀
def fun(): w=99 def fun1(): w=100 fun1() return w print(fun()) #輸出結(jié)果:99
VS
def fun(): w=99 def fun1(): nonlocal w w=100 fun1() return w print(fun()) #輸出結(jié)果:100
這里,可以看出,w=99相對(duì)應(yīng)fun1()是一個(gè)全局變量,而fun1()內(nèi)部的w相對(duì)應(yīng)fun()是一個(gè)局部變量,當(dāng)我用nonlocal關(guān)鍵字去定義了fun()的變量w之后,這個(gè)w變量已經(jīng)是屬于fun1()函數(shù)內(nèi)部的變量,這時(shí)候我們可以去修改這個(gè)w的值,從而去影響外部函數(shù),最后w的返回值也就是被修改后的100
到此這篇關(guān)于關(guān)于Python函數(shù)對(duì)象的名稱空間和作用域的文章就介紹到這了,更多相關(guān)Python函數(shù)作用域和名稱空間內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解Python如何檢查一個(gè)數(shù)字是否是三態(tài)數(shù)
在數(shù)學(xué)中,三態(tài)數(shù)(Triangular?Number)是一種特殊的數(shù)列,它是由自然數(shù)按照一定規(guī)律排列而成的,本文主要介紹了如何使用Python檢查判斷一個(gè)數(shù)字是否是三態(tài)數(shù),需要的可以參考下2024-03-03python polars數(shù)據(jù)科學(xué)庫(kù)對(duì)比Pandas優(yōu)勢(shì)分析
這篇文章主要為大家介紹了python polars數(shù)據(jù)科學(xué)庫(kù)對(duì)比Pandas優(yōu)勢(shì)分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01Python學(xué)習(xí)筆記之列表推導(dǎo)式實(shí)例分析
這篇文章主要介紹了Python學(xué)習(xí)筆記之列表推導(dǎo)式,結(jié)合實(shí)例形式分析Python列表推導(dǎo)式的原理、寫法與相關(guān)使用技巧,需要的朋友可以參考下2019-08-08Python實(shí)現(xiàn)的文本對(duì)比報(bào)告生成工具示例
這篇文章主要介紹了Python實(shí)現(xiàn)的文本對(duì)比報(bào)告生成工具,涉及Python基于difflib模塊實(shí)現(xiàn)對(duì)文本內(nèi)容進(jìn)行對(duì)比的相關(guān)操作技巧,需要的朋友可以參考下2018-05-05詳解python opencv圖像混合算術(shù)運(yùn)算
這篇文章主要介紹了python opencv圖像混合算術(shù)運(yùn)算的相關(guān)知識(shí),本文通過實(shí)例圖文相結(jié)合給大家介紹的非常詳細(xì),需要的朋友可以參考下2021-09-09numpy刪除單行、刪除單列、刪除多列實(shí)現(xiàn)方式
這篇文章主要介紹了numpy刪除單行、刪除單列、刪除多列實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-02-02利用Python操作消息隊(duì)列RabbitMQ的方法教程
RabbitMQ是一個(gè)在AMQP基礎(chǔ)上完整的,可復(fù)用的企業(yè)消息系統(tǒng)。他遵循Mozilla Public License開源協(xié)議。下面這篇文章主要給大家介紹了關(guān)于利用Python操作消息隊(duì)列RabbitMQ的方法教程,需要的朋友可以參考下。2017-07-07python中協(xié)程實(shí)現(xiàn)TCP連接的實(shí)例分析
在本篇文章中我們給大家分享了python中協(xié)程實(shí)現(xiàn)TCP連接的代碼示例內(nèi)容,有需要的朋友們可以跟著學(xué)習(xí)下。2018-10-10python中執(zhí)行shell的兩種方法總結(jié)
這篇文章主要介紹了python中執(zhí)行shell的兩種方法,有兩種方法可以在Python中執(zhí)行SHELL程序,方法一是使用Python的commands包,方法二則是使用subprocess包,這兩個(gè)包均是Python現(xiàn)有的內(nèi)置模塊。需要的朋友可以參考借鑒,下面來一起看看吧。2017-01-01