亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

11函數返回值_作用域_enclosing閉包

發布時間:2020-08-06 13:15:11 來源:網絡 閱讀:214 作者:chaijowin 欄目:編程語言

?

?

函數返回值、作用域、enclosing閉包

?

目錄

函數的返回值:... 1

作用域:... 3

enclosing閉包:... 6

默認值的作用域:... 9

可變類型默認值:... 11

函數的銷毀:... 13

?

?

?

函數的返回值:

函數中return語句,在執行過程中只要一到return處會將函數打斷直接返回,而break是退出當前loop循環,returnbreak作用,但比break更狠;

?

總結:

python函數使用return語句返回“返回值”;

所有函數都有返回值,如果沒有return語句,隱式調用return None

return語句并不一定是函數語句塊的最后一條語句;

一個函數可以存在多個return語句,但只有一條可被執行,如果沒有一條return語句被執行到,隱式調用return None

如果有必要,可以顯式調用return None,簡寫為return

如果函數執行了return語句,函數就會返回,當前被執行的return語句之后的其它語句就不會被執行了;

作用:結束函數調用、返回值;

?

返回多個值:

函數不能返回多個值;

return [1,2,3],是指明返回一個列表,是一個列表對象;

return 1,3,5,看似返回多個值,隱式的被python封裝成了一個tuple

配合解構會更加方便,如x,y,z=showlist()x,*_,y=showlist()

?

In [15]: def showplus(x):

??? ...:???? print(x)

??? ...:???? return x+1

??? ...:

In [16]: showplus(5)

5

Out[16]: 6

In [17]: def showplus(x):

??? ...:???? print(x)

??? ...:???? return x+1

??? ...:???? print(x+1)?? #會執行嗎?不會,廢語句

??? ...:????

In [18]: showplus(5)

5

Out[18]: 6

In [20]: def guess(x):

??? ...:???? if x>3:

??? ...:???????? return '>3'

??? ...:???? else:

??? ...:???????? return '<3'

??? ...:????

In [21]: guess(10)?? #多條return語句,return可以寫多個,但只能執行一個return

Out[21]: '>3'

In [22]: def showplus(x):

??? ...:???? print(x)

??? ...:???? return x+1

??? ...:???? return x+2?? #廢語句

??? ...:

In [23]: showplus(5)

5

Out[23]: 6

In [24]: def fn(x):

??? ...:???? for i in range(x):

??? ...:???????? if i>3:

??? ...:???????????? return i?? #執行到return處會將函數打斷直接返回

??? ...:???? else:

??? ...:???????? print('{} is not greater than 3'.format(x))?? #else段隱含有return None,一般都不寫除非明確指定返回None

??? ...:????????

In [25]: fn(5)

Out[25]: 4

In [26]: fn(3)?? #是控制臺輸出,不是函數返回

3 is not greater than 3

?

例:

In [27]: def showlist():

??? ...:???? return [1,3,5]?? #返回一個值[1,3,5]

??? ...:

In [28]: def showlist():

??? ...:???? return 1,3,5?? #返回多個值,封裝,等價于return (1,3,5)

??? ...:

In [29]: x,y,z=showlist()?? #使用解構提取更為方便

In [30]: x,y,z

Out[30]: (1, 3, 5)

?

函數嵌套:

在一個函數中定義了另外一個函數;

函數有可見范圍,這就是作用域的概念(對標識符作控制),函數內定義的在函數外不可見,函數外定義的在函數內可見;

內部函數不能被外部函數直接使用,會拋NameError異常;

?

例:

In [31]: def outer():

??? ...:???? def inner():

??? ...:???????? print('inner')

??? ...:???? print('outer')

??? ...:???? inner()

??? ...:????

?

In [32]: outer()

outer

inner

In [33]: inner()

---------------------------------------------------------------------------

NameError???????????????????????????????? Traceback (most recent call last)

<ipython-input-33-bc10f1654870> in <module>()

----> 1 inner()

NameError: name 'inner' is not defined

?

?

?

作用域:

一個標識符的可見范圍,這就是標識符的作用域,一般常說的是變量的作用域;

?

global全局作用域,在整個程序運行環境中都可見;

local局部作用域,在函數、類,內部可見,局部變量使用范圍不能超過其所在的局部作用域;

?

global總結

x+=1,這種是特殊形式產生的錯誤,原因,先引用后賦值,而python動態語言是賦值才算定義,才能被引用;解決辦法,在這條語句前加x=0之類的賦值語句,或使用global告訴內部作用域去全局作用域中查找變量定義;

內部作用域使用x=5之類的賦值語句會重新定義局部作用域的變量x,但是,一旦這個作用域中使用global聲明為x為全局的,那么x=5相當于在全局作用域的x賦值;

global使用原則,外部作用域變量在內部作用域可見,但也不要在這個內部的局部作用域中直接使用,因為函數的目的就是為了封裝,盡量與外界隔離;如果函數需要使用外部全局變量,請使用函數的形參來傳參解決;一句話,不用global,學習它是為了深入理解變量作用域;

?

變量名解析原則(LEGB):

local,本地作用域,局部作用域的local命名空間,函數調用時創建,調用結束消亡;

enclosingpython2.2引入了嵌套函數,實現了閉包,這個就是嵌套函數的外部函數的命名空間;

global,全局作用域,即一個模塊的命名空間,模塊被import時創建,解釋器退出時消亡;

build-in,內建模塊的命名空間,生命周期從python解釋器啟動時創建到解釋器退出時消亡,如print(open)printopen都是內置的變量;

一個名詞的查找順序就是LEGB,即local-->enclosing-->global-->build-in

11函數返回值_作用域_enclosing閉包

?

例:

In [1]: x=5

In [2]: def fn():

?? ...:???? print(x)

?? ...:????

In [3]: fn()

5

?

例:

In [4]: x=5

In [5]: def fn():

?? ...:???? x+=1?? #x=x+1,如果是y=x+1x=1均正確,而x=x+1x=是在賦值,=右邊又有x,已在用;相當于在fn內部定義一個局部變量x,那么fn內部所有x都是這個局部變量x了,但是這個x還沒有完成賦值,就被右邊拿來作加1操作了;解決:在x+=1前加入x=0或使用global關鍵字定義,使用global的話外層要有x的定義

?? ...:???? print(x)

?? ...:????

In [6]: fn()

---------------------------------------------------------------------------

UnboundLocalError???????????????????????? Traceback (most recent call last)

<ipython-input-6-e1d0f67027b9> in <module>()

----> 1 fn()

<ipython-input-5-9e265d33dd3d> in fn()

????? 1 def fn():

----> 2???? x+=1

????? 3???? print(x)

????? 4

UnboundLocalError: local variable 'x' referenced before assignment

?

例:

In [8]: def fn1():

?? ...:???? x=1?? #local variable,局部作用域,在fn1內,內部高度自治

?? ...:????

In [11]: del x

In [13]: def fn2():

??? ...:???? pritn(x)?? #x不可見

??? ...:????

In [14]: fn2()

---------------------------------------------------------------------------

NameError???????????????????????????????? Traceback (most recent call last)

……

?

例:

In [15]: def outer():

??? ...:???? o=65?? #外層變量作用域在內層作用域可見

??? ...:???? def inner():

??? ...:???????? print('inner {}'.format(o))

??? ...:???????? print(chr(o))

??? ...:???? print('outer {}'.format(o))

??? ...:???? inner()

??? ...:????

In [16]: outer()

outer 65

inner 65

A

In [17]: def outer2():

??? ...:???? o=65

??? ...:???? def inner():

??? ...:???????? o=97?? #賦值即定義,局部作用域,內層作用域inner中定義了o,相當于當前作用域中重新定義了一個新的變量o,但這個o并沒有覆蓋外層作用域outer2中的o

??? ...:???????? print('inner {}'.format(o))

??? ...:???????? print(chr(o))

??? ...:???? print('outer {}'.format(o))

??? ...:???? inner()

??? ...:????

In [18]: outer2()

outer 65

inner 97

a

?

例:

In [26]: x=5

In [27]: def fn():

??? ...:???? global x?? #使用global關鍵字的變量,將fn內的x聲明為使用外部的全局作用域中定義的x;全局作用域中必須有x的定義;如果全局作用域中沒有定義,拋NameError異常,NameError與之前的UnboundLocalError在本質上一樣

??? ...:???? x+=1

??? ...:???? print(x)

??? ...:????

In [28]: fn()

6

In [29]: del x

In [30]: del fn

In [31]: def fn():

??? ...:???? global x

??? ...:???? x+=1

??? ...:???? print(x)

??? ...:????

In [32]: fn()

---------------------------------------------------------------------------

NameError ????????????????????????????????Traceback (most recent call last)

……

NameError: name 'x' is not defined

In [34]: def foo():

??? ...:???? global x

??? ...:???? x=20?? #使用global關鍵字的變量,將foo內的x聲明為使用外部的全局作用域中定義的x;但x=20賦值即定義,x在內部作用域為一個外部作用域的變量賦值,所以x+=2不會報錯;這里x的作用域是全局

??? ...:???? x+=2

??? ...:???? print(x)

??? ...:????

In [35]: foo()

22

In [36]: x

Out[36]: 22

?

?

?

enclosing閉包:

自由變量,未在本地作用域中定義的變量,如定義在內層函數外的外層函數的作用域中的變量;

閉包,是一個概念,出現在函數嵌套中,指內層函數引用到了外層函數的自由變量,很多語言都有這個概念,最常見的js

python3的閉包,還可使用nonlocal關鍵字;

python2的閉包,只能對變量中引用的元素更改(c[0]+=1,c.append(1),c.add(2)),而python3中使用nonlocal能直接用x+=1

使用nonlocal關鍵字,將變量標記為在上級的局部作用域中定義,但不能是全局作用域中定義的;

標識符可以沖突,如int='abc',將把int給覆蓋了;而關鍵字不能沖突,如nonlocal

?

In [37]: def counter():

??? ...:???? c=[0]?? #自由變量

??? ...:???? def inner():

??? ...:???????? c[0]+=1?? #會報錯嗎?不會,與x+=1不一樣,不是對c變量改變,改的是c中的元素,c已在counter中定義了,而且inner中是修改c元素的值,而不是重新定義變量

??? ...:???????? return c[0]

??? ...:???? return inner?? #返回的是標識符,即函數對象,有()才是調用

??? ...:

In [38]: foo=counter()?? #foocallable function可調用對象,即函數對象inner

In [39]: inner()?? #全局內沒有定義過inner

---------------------------------------------------------------------------

NameError???????????????????????????????? Traceback (most recent call last)

<ipython-input-39-bc10f1654870> in <module>()

----> 1 inner()

NameError: name 'inner' is not defined

In [40]: print(foo(),foo())

1 2

In [41]: c=100?? #global variable,此處的ccounter中的c不一樣,inner里引用的是自由變量counter中的c

In [44]: print(foo())

3

?

例:

In [47]: def outer():

??? ...:???? c=5

??? ...:???? def inner():

??? ...:????? ???z=c+1?? #enclosing

??? ...:???????? return z

??? ...:???? return inner

??? ...:

In [48]: def outer():

??? ...:???? c=5

??? ...:???? def inner():

??? ...:???????? c=6?? #不是enclosing

??? ...:???????? return c

??? ...:???? return inner

??? ...:

?

例:

In [49]: def outer():

??? ...:???? count=0

??? ...:???? def inner():

??? ...:???????? global count?? #global僅在inner()和最外層可見,outer中不可見,最外層中若沒有定義count,在調用inner時會報錯

??? ...:???????? count+=1

??? ...:???????? return count

??? ...:???? return inner

??? ...:

In [51]: foo=outer()

In [52]: foo()?? #最外層未定義count

---------------------------------------------------------------------------

NameError???????????????????????????????? Traceback (most recent call last)

……

NameError: name 'count' is not defined

?

例:

In [53]: def outer():

??? ...:???? count=0

??? ...:???? def inner():

??? ...:???????? count+=1

??? ...:???????? return count

??? ...:???? return inner

??? ...:

In [54]: foo=outer()

In [55]: foo()?? #會報錯,使用global能解決,但使用的是全局變量而不是閉包,如果要對普通變量閉包,python3中可用nonlocal

---------------------------------------------------------------------------

……

UnboundLocalError: local variable 'count' referenced before assignment

In [61]: def outer():

??? ...:???? global count

??? ...:???? def inner():

??? ...:???????? count+=1

??? ...:???????? return count

??? ...:???? return inner

??? ...:

?

In [62]: foo=outer()

?

In [63]: foo()

---------------------------------------------------------------------------

……

UnboundLocalError: local variable 'count' referenced before assignment

?

例(閉包,使用nonlocal關鍵字):

In [69]: def outer():

??? ...:???? count=0?? #count是外層函數的局部變量,被內部函數引用

??? ...:???? def inner():

??? ...:???????? nonlocal count?? #內部函數使用nonlocal關鍵字聲明,count變量在上一級作用域中

??? ...:???????? count+=1

??? ...:???????? return count

??? ...:???? return inner

??? ...:

In [70]: foo=outer()

In [71]: foo()

Out[71]: 1

In [72]: foo()

Out[72]: 2

?

例:

In [73]: a=50

In [74]: def outer():

??? ...:???? nonlocal a?? #變量a不能在全局的作用域中

? File "<ipython-input-74-cd05dfa8d327>", line 2

??? nonlocal a

??? ^

SyntaxError: no binding for nonlocal 'a' found

?

例:

In [60]: def outer():

??? ...:???? count=0

??? ...:???? def middle():

??? ...:???????? def inner():

??? ...:???????????? nonlocal count?? #嵌套三層,是閉包

??? ...:???????????? count+=1

??? ...:???????????? return count

??? ...:???????? return inner

??? ...:???? return middle

??? ...:

In [61]: a=outer()

In [62]: b=a()

In [63]: c=b()

In [64]: c

Out[64]: 1

?

默認值的作用域:

函數的缺省值一般用不可變類型;

python把函數的默認值放在了屬性中,這個屬性就伴隨著這個函數對象的整個生命周期,可查看foo.__defaults__屬性;

屬性__defaults__中使用tuple保存所有默認值,該元組中若有引用類型,是引用類型的元素變動,并不是該元組的變化;

屬性__defaults__中使用tuple保存所有默認值,它不會因為在函數體內使用了它而發生改變;

位置參數的默認值在__defaults__里;

關鍵字參數的默認值在__kwdefaults__里;

?

例:

In [1]: def foo(xyz=1):

?? ...:???? print(xyz)

?? ...:????

In [2]: foo()

1

In [3]: foo()

1

In [4]: print(xyz)

……

NameError: name 'xyz' is not defined

In [5]: def foo(xyz=[]):?? #引用類型要注意,xyz在函數調用完就消亡了,此處是因為默認值與棧有關

?? ...:???? xyz.append(1)

?? ...:???? print(xyz)

?? ...:????

In [6]: foo()

[1]

In [7]: foo()?? #因為函數也是對象,python把函數的默認值放在了屬性中,這個屬性就伴隨著這個函數對象的整個生命周期,可查看foo.__defaults__屬性

[1, 1]

In [8]: print(xyz)

……

NameError: name 'xyz' is not defined

In [9]: foo.__defaults__?? #屬性中使用元組保存所有值

Out[9]: ([1, 1],)

?

例:

In [10]: def foo(xyz=[],m=5,n=6):

??? ...:???? xyz.append(100)

??? ...:???? print(xyz)

??? ...:????

In [11]: print(1,foo.__defaults__)

1 ([], 5, 6)

In [12]: print(2,foo(),id(foo))?? #函數地址沒有變,即函數對象沒有變,調用它,它的屬性__defaults__中使用元組保存所有值;xyz默認值是引用類型,引用類型的元素變動,并不是元組的變化

[100]

2 None 140519573187848

In [14]: print(3,foo.__defaults__)

3 ([100], 5, 6)

In [15]: print(4,foo(),id(foo))

[100, 100]

4 None 140519573187848?? #兩次id(foo)有無變化,無,cpythonid取的是foo函數對象的地址

In [17]: print(5,foo.__defaults__)

5 ([100, 100], 5, 6)

?

例(非引用類型例子):

In [19]: def foo(w,u='abc',z=123):

??? ...:???? print(w,u,z)

??? ...:???? u='xyz'

??? ...:???? z=789

??? ...:???? print(w,u,z)

??? ...:????

In [20]: foo.__defaults__

Out[20]: ('abc', 123)

In [21]: foo('magedu')

magedu abc 123

magedu xyz 789

In [22]: foo.__defaults__?? #屬性__defaults__中使用tuple保存所有默認值,它不會因為在函數體內使用了它而發生改變

Out[22]: ('abc', 123)

?

?

?

可變類型默認值:

如果使用默認值,就可能修改這個默認值;

有時候這個特性是好的,有時候這種特性不好,有副作用;

如何做到按需改變?2種方法:

1、使用shadow copy創建一個新的對象,永遠不能改變傳入的參數;

2、通過值的判斷,如if xyz is None:,就可靈活的選擇創建或修改傳入對象,這種方式更靈活,應用更廣泛,很多函數的定義(很多標準庫),都可看到使用None這個不可變的值作為默認參數,可以說這是一種慣用法;

?

例(方1):

In [24]: def foo(xyz=[],u='abc',z=123):

??? ...:???? xyz=xyz[:]

??? ...:???? xyz.append(1)

??? ...:???? print(xyz)

??? ...:???? return xyz

??? ...:

In [25]: foo()

[1]

Out[25]: [1]

In [26]: print(foo.__defaults__)

([], 'abc', 123)

In [27]: foo()

[1]

Out[27]: [1]

In [28]: print(foo.__defaults__)

([], 'abc', 123)

In [29]: foo([10])

[10, 1]

Out[29]: [10, 1]

In [30]: print(foo.__defaults__)

([], 'abc', 123)

In [31]: foo([10,5])

[10, 5, 1]

Out[31]: [10, 5, 1]

In [32]: print(foo.__defaults__)

([], 'abc', 123)

?

例(方2):

In [34]: def foo(xyz=None,u='abc',z=123):?? #常用,使用不可變類型默認值,如果使用缺省值None就創建一個列表,如果傳入一個列表就修改這個列表

??? ...:???? if xyz is None:

??? ...:???????? xyz=[]

??? ...:???? xyz.append(1)

??? ...:???? print(xyz)

??? ...:???? return xyz

??? ...:

In [35]: foo()

[1]

Out[35]: [1]

In [36]: print(foo.__defaults__)

(None, 'abc', 123)

In [37]: foo()

[1]

Out[37]: [1]

In [38]: print(foo.__defaults__)

(None, 'abc', 123)

In [39]: foo([10])

[10, 1]

Out[39]: [10, 1]

In [40]: print(foo.__defaults__)

(None, 'abc', 123)

In [41]: foo([10,5])

[10, 5, 1]

Out[41]: [10, 5, 1]

In [42]: print(foo.__defaults__)

(None, 'abc', 123)

In [43]: a=foo([10])

[10, 1]

In [44]: print(a)

[10, 1]

In [45]: b=foo()

[1]

In [46]: a=foo(b)

[1, 1]

In [47]: print(a)

[1, 1]

In [48]: c=foo(a)

[1, 1, 1]

?

?

?

函數的銷毀:

全局函數的銷毀:

重新定義同名函數;

del語句刪除函數對象;

程序結束時;

?

局部函數銷毀:

重新在上級作用域定義同名函數;

del語句刪除函數對象,引用計數減1

上級作用域銷毀時;

?

例:

In [49]: def foo(xyz=[],u='abc',z=123):

??? ...:???? xyz.append(1)

??? ...:???? return xyz

??? ...:

In [50]: print(foo(),id(foo),foo.__defaults__)

[1] 140519584127992 ([1], 'abc', 123)

In [51]: def foo(xyz=[],u='abc',z=123):?? #重新定義后,覆蓋了之前的foo

??? ...:???? xyz.append(1)

??? ...:???? return xyz

??? ...:

In [52]: print(foo(),id(foo),foo.__defaults__)

[1] 140519572782888 ([1], 'abc', 123)

In [53]: del foo

In [54]: print(foo(),id(foo),foo.__defaults__)

---------------------------------------------------------------------------

NameError???????????????????????????????? Traceback (most recent call last)

<ipython-input-54-d4746b4548a6> in <module>()

----> 1 print(foo(),id(foo),foo.__defaults__)

NameError: name 'foo' is not defined

?

例:

In [55]: def foo(xyz=[],u='abc',z=123):

??? ...:???? xyz.append(1)

??? ...:???? def inner(a=10):

??? ...:???????? pass

??? ...:???? def inner(a=100):

??? ...:???????? print(xyz)

??? ...:?? ??print(inner)

??? ...:???? return inner

??? ...:

In [56]: bar=foo()

<function foo.<locals>.inner at 0x7fcd43383ea0>

In [57]: print(id(foo),id(bar),foo.__defaults__,bar.__defaults__)

140519573186624 140519572782752 ([1], 'abc', 123) (100,)

In [58]: del bar

In [59]: print(id(foo),id(bar),foo.__defaults__,bar.__defaults__)

---------------------------------------------------------------------------

NameError???????????????????????????????? Traceback (most recent call last)

<ipython-input-59-3984e90a440f> in <module>()

----> 1 print(id(foo),id(bar),foo.__defaults__,bar.__defaults__)

NameError: name 'bar' is not defined

?


向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

伽师县| 镇宁| 柳州市| 万安县| 丹东市| 黄大仙区| 青田县| 中卫市| 鄄城县| 玛纳斯县| 同江市| 万山特区| 通城县| 兴安县| 酒泉市| 留坝县| 达日县| 台中市| 岳普湖县| 游戏| 榆林市| 电白县| 阳新县| 淮安市| 西丰县| 鲁甸县| 淮北市| 西畴县| 乐清市| 乐至县| 兴隆县| 绥宁县| 永寿县| 安义县| 遂宁市| 汉沽区| 卫辉市| 安宁市| 乐亭县| 庆元县| 垦利县|