日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > python >内容正文

python

python之路day10-命名空间和作用域、函数嵌套,作用域链、闭包

發(fā)布時(shí)間:2023/12/6 python 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python之路day10-命名空间和作用域、函数嵌套,作用域链、闭包 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

楔子

假如有一個(gè)函數(shù),實(shí)現(xiàn)返回兩個(gè)數(shù)中的較大值:

def my_max(x,y):m = x if x>y else yreturn m
bigger = my_max(10,20)
print(bigger)

之前是不是我告訴你們要把結(jié)果return回來(lái)你們就照做了?可是你們有沒(méi)有想過(guò),我們?yōu)槭裁匆呀Y(jié)果返回?如果我們不返回m,直接在程序中打印,行不行?

來(lái)看結(jié)果:

>>> def my_max(x,y): ... m = x if x>y else y ... >>> my_max(10,20) >>> print(m) Traceback (most recent call last):File "<stdin>", line 1, in <module> NameError: name 'm' is not defined

報(bào)錯(cuò)了!錯(cuò)誤是“name 'm' is not defined”。變量m沒(méi)有被定義。。。為啥?我明明定義了呀!

在這里我們首先回憶一下python代碼運(yùn)行的時(shí)候遇到函數(shù)是怎么做的。

從python解釋器開(kāi)始執(zhí)行之后,就在內(nèi)存中開(kāi)辟了一個(gè)空間

每當(dāng)遇到一個(gè)變量的時(shí)候,就把變量名和值之間的對(duì)應(yīng)關(guān)系記錄下來(lái)。

但是當(dāng)遇到函數(shù)定義的時(shí)候解釋器只是象征性的將函數(shù)名讀入內(nèi)存,表示知道這個(gè)函數(shù)的存在了,至于函數(shù)內(nèi)部的變量和邏輯解釋器根本不關(guān)心。

等執(zhí)行到函數(shù)調(diào)用的時(shí)候,python解釋器會(huì)再開(kāi)辟一塊內(nèi)存來(lái)存儲(chǔ)這個(gè)函數(shù)里的內(nèi)容,這個(gè)時(shí)候,才關(guān)注函數(shù)里面有哪些變量,而函數(shù)中的變量會(huì)存儲(chǔ)在新開(kāi)辟出來(lái)的內(nèi)存中。函數(shù)中的變量只能在函數(shù)的內(nèi)部使用,并且會(huì)隨著函數(shù)執(zhí)行完畢,這塊內(nèi)存中的所有內(nèi)容也會(huì)被清空。

我們給這個(gè)“存放名字與值的關(guān)系”的空間起了一個(gè)名字——叫做命名空間

代碼在運(yùn)行伊始,創(chuàng)建的存儲(chǔ)“變量名與值的關(guān)系”的空間叫做全局命名空間,在函數(shù)的運(yùn)行中開(kāi)辟的臨時(shí)的空間叫做局部命名空間

命名空間和作用域

命名空間的本質(zhì):存放名字與值的綁定關(guān)系

>>> import this
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

python之禪


>>> import this The Zen of Python, by Tim PetersBeautiful is better than ugly. Explicit is better than implicit. Simple is better than complex. Complex is better than complicated. Flat is better than nested. Sparse is better than dense. Readability counts. Special cases aren't special enough to break the rules. Although practicality beats purity. Errors should never pass silently. Unless explicitly silenced. In the face of ambiguity, refuse the temptation to guess. There should be one-- and preferably only one --obvious way to do it. Although that way may not be obvious at first unless you're Dutch. Now is better than never. Although never is often better than *right* now. If the implementation is hard to explain, it's a bad idea. If the implementation is easy to explain, it may be a good idea. Namespaces are one honking great idea -- let's do more of those!

在python之禪中提到過(guò):命名空間是一種絕妙的理念,讓我們盡情的使用發(fā)揮吧!

?

命名空間一共分為三種:

  全局命名空間

  局部命名空間

  內(nèi)置命名空間

*內(nèi)置命名空間中存放了python解釋器為我們提供的名字:input,print,str,list,tuple...它們都是我們熟悉的,拿過(guò)來(lái)就可以用的方法。

三種命名空間之間的加載與取值順序:

加載順序:內(nèi)置命名空間(程序運(yùn)行前加載)->全局命名空間(程序運(yùn)行中:從上到下加載)->局部命名空間(程序運(yùn)行中:調(diào)用時(shí)才加載)

取值:

  在局部調(diào)用:局部命名空間->全局命名空間->內(nèi)置命名空間

x = 1 def f(x):print(x)print(10)
x = 1 def f(x):print(x)print(10)

  在全局調(diào)用:全局命名空間->內(nèi)置命名空間

x = 1 def f(x):print(x)f(10) print(x)
x = 1 def f(x):print(x)f(10) print(x) print(max)
print(max)

?

?

作用域

作用域就是作用范圍,按照生效范圍可以分為全局作用域和局部作用域。

全局作用域:包含內(nèi)置名稱空間、全局名稱空間,在整個(gè)文件的任意位置都能被引用、全局有效

局部作用域:局部名稱空間,只能在局部范圍內(nèi)生效

globals和locals方法

print(globals()) print(locals())
print(globals()) print(locals()) def func():a = 12b = 20print(locals())print(globals())func()
def func():a = 12b = 20print(locals())print(globals())func()

global關(guān)鍵字

a = 10 def func():global aa = 20print(a) func() print(a)

函數(shù)的嵌套和作用域鏈

函數(shù)的嵌套調(diào)用


def max2(x,y):m = x if x>y else yreturn mdef max4(a,b,c,d):res1 = max2(a,b)res2 = max2(res1,c)res3 = max2(res2,d)return res3# max4(23,-7,31,11) def max2(x,y):m = x if x>y else yreturn mdef max4(a,b,c,d):res1 = max2(a,b)res2 = max2(res1,c)res3 = max2(res2,d)return res3# max4(23,-7,31,11)

  函數(shù)的嵌套定義

def f1():print("in f1")def f2():print("in f2")f2() f1() def f1():def f2():def f3():print("in f3")print("in f2")f3()print("in f1")f2()f1()

?  函數(shù)的作用域鏈

def f1():a = 1def f2():print(a)f2()f1() def f1():a = 1def f2():def f3():print(a)f3()f2()f1() def f1():a = 1def f2():a = 2f2()print('a in f1 : ',a)f1() def f1():a = 1def f2():a = 2f2()print('a in f1 : ',a)f1()

?   nonlocal關(guān)鍵字

1.外部必須有這個(gè)變量
2.在內(nèi)部函數(shù)聲明nonlocal變量之前不能再出現(xiàn)同名變量
3.內(nèi)部修改這個(gè)變量如果想在外部有這個(gè)變量的第一層函數(shù)中生效 def f1():a = 1def f2():nonlocal aa = 2f2()print('a in f1 : ',a)f1() def f1():a = 1def f2():nonlocal aa = 2f2()print('a in f1 : ',a)f1()

函數(shù)名的本質(zhì)

函數(shù)名本質(zhì)上就是函數(shù)的內(nèi)存地址

1.可以被引用


def func():print('in func')f = func print(f) def func():print('in func')f = func print(f)

2.可以被當(dāng)作容器類型的元素

def f1():
print('f1')


def f2():
print('f2')


def f3():
print('f3')

l = [f1,f2,f3]
d = {'f1':f1,'f2':f2,'f3':f3}
#調(diào)用
l[0]()
d['f2']()

函數(shù)被當(dāng)作容易類型的元素

def f1():print('f1')def f2():print('f2')def f3():print('f3')l = [f1,f2,f3] d = {'f1':f1,'f2':f2,'f3':f3} #調(diào)用 l[0]() d['f2']()

3.可以當(dāng)作函數(shù)的參數(shù)和返回值

*不明白?那就記住一句話,就當(dāng)普通變量用

第一類對(duì)象(first-class object)指 1.可在運(yùn)行期創(chuàng)建 2.可用作函數(shù)參數(shù)或返回值 3.可存入變量的實(shí)體。 第一類對(duì)象(first-class object)指 1.可在運(yùn)行期創(chuàng)建 2.可用作函數(shù)參數(shù)或返回值 3.可存入變量的實(shí)體。

閉包

def func():name = 'eva'def inner():print(name)

閉包函數(shù):

內(nèi)部函數(shù)包含對(duì)外部作用域而非全劇作用域名字的引用,該內(nèi)部函數(shù)稱為閉包函數(shù)
#函數(shù)內(nèi)部定義的函數(shù)稱為內(nèi)部函數(shù)

?

由于有了作用域的關(guān)系,我們就不能拿到函數(shù)內(nèi)部的變量和函數(shù)了。如果我們就是想拿怎么辦呢?返回呀!

我們都知道函數(shù)內(nèi)的變量我們要想在函數(shù)外部用,可以直接返回這個(gè)變量,那么如果我們想在函數(shù)外部調(diào)用函數(shù)內(nèi)部的函數(shù)呢?

是不是直接就把這個(gè)函數(shù)的名字返回就好了?

這才是閉包函數(shù)最常用的用法

def func():name = 'eva'def inner():print(name)return innerf = func() f()

判斷閉包函數(shù)的方法__closure__

#輸出的__closure__有cell元素 :是閉包函數(shù) def func():name = 'eva'def inner():print(name)print(inner.__closure__)return innerf = func() f()#輸出的__closure__為None :不是閉包函數(shù) name = 'egon' def func2():def inner():print(name)print(inner.__closure__)return innerf2 = func2() f2() ?閉包嵌套

def wrapper():
money = 1000
def func():
name = 'eva'
def inner():
print(name,money)
return inner
return func

f = wrapper()
i = f()
i()

閉包嵌套

閉包函數(shù)獲取網(wǎng)絡(luò)應(yīng)用 小爬蟲(chóng) from urllib.request import urlopendef index():url = "http://www.xiaohua100.cn/index.html"def get():return urlopen(url).read()return getxiaohua = index() content = xiaohua() print(content)

本章小結(jié)

命名空間:

  一共有三種命名空間從大范圍到小范圍的順序:內(nèi)置命名空間、全局命名空間、局部命名空間

作用域(包括函數(shù)的作用域鏈):

小范圍的可以用大范圍的
但是大范圍的不能用小范圍的
范圍從大到小(圖)

在小范圍內(nèi),如果要用一個(gè)變量,是當(dāng)前這個(gè)小范圍有的,就用自己的
如果在小范圍內(nèi)沒(méi)有,就用上一級(jí)的,上一級(jí)沒(méi)有就用上上一級(jí)的,以此類推。
如果都沒(méi)有,報(bào)錯(cuò)

函數(shù)的嵌套:

  嵌套調(diào)用

  嵌套定義:定義在內(nèi)部的函數(shù)無(wú)法直接在全局被調(diào)用

函數(shù)名的本質(zhì):

  就是一個(gè)變量,保存了函數(shù)所在的內(nèi)存地址

閉包:

  內(nèi)部函數(shù)包含對(duì)外部作用域而非全劇作用域名字的引用,該內(nèi)部函數(shù)稱為閉包函數(shù)



轉(zhuǎn)載于:https://www.cnblogs.com/hanfe1/p/10429690.html

總結(jié)

以上是生活随笔為你收集整理的python之路day10-命名空间和作用域、函数嵌套,作用域链、闭包的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。