1. 函數的嵌套與nonlocal 聲明局部變量
# ### 函數的嵌套
"""
函數和函數之間可以互相嵌套:
嵌套在内層的叫做内函數
喬濤在外層的叫做外函數
"""
def outer():
def inner():
print("我是inner函數 ... ")
inner()
# (1)内部函數可以直接在函數外部調用麼 不行
# inner()
# (2)調用外部函數後,内部函數可以在函數外部調用嗎 不行
# outer()
# inner()
# (3)内部函數可以在函數内部調用嗎 可以
# outer()
# (4)内部函數在函數内部調用時,是否有先後順序 有的 先定義在調用
# 定義三個函數 outer函數中有inner ,inner函數中有smaller, 調用smaller
def outer():
def inner():
def smaller():
print(id)
print("我是smaller函數")
smaller()
inner()
outer()
#找尋變量的調用順序采用LEGB原則(即就近原則)
"""
B —— Builtin(Python);Python内置子產品的命名空間 (内建作用域)
G —— Global(module); 函數外部所在的命名空間 (全局作用域)
E —— Enclosing function locals;外部嵌套函數的作用域(嵌套作用域)
L —— Local(function);目前函數内的作用域 (局部作用域)
依據就近原則,從下往上 從裡向外 依次尋找
"""
函數的嵌套 示例代碼
# ### nonlocal 用來修飾局部變量
"""
nonlocal 符合LEGB原則
(1)用來修改目前作用域上一級的局部變量
(2)如果上一級沒有,在向上一級依次尋找
(3)如果再也找不到了,直接報錯
"""
# (1)用來修改目前作用域上一級的局部變量
def outer():
a = 13
def inner():
nonlocal a
a = 15
print(a)
inner()
print(a)
outer()
# (2)如果上一級沒有,在向上一級依次尋找
# b = 200
def outer():
b = 100
def inner():
b = 200
def smaller():
nonlocal b
b = 101
print(b)
smaller()
print(b)
inner()
print(b)
outer()
# (3)如果再也找不到了,直接報錯
"""
b =200
def outer():
def inner():
def smaller():
# nonlocal 隻修改局部變量
nonlocal b
b +=10
smaller()
print(b)
inner()
outer()
"""
# (4)不通過nonlocal , 是否可以修改局部變量
def outer():
lst = [1,2,3]
def inner():
lst[-1] += 10
inner()
print(lst)
outer()
nonlocal 示例代碼
2. 閉包函數
# ### 閉包函數
"""
生命周期從長到短:
内置空間變量 -> 全局空間變量 -> 局部空間變量
内置空間變量 : 在解釋器退出之後,就會釋放空間
全局空間變量 : 在檔案執行結束之後,就會釋放空間
局部空間變量 : 在調用完函數之後,就會釋放空間
定義: 内函數使用了外函數的局部變量,外函數把内函數傳回出來的過程,叫做閉包,這個内函數叫做閉包函數
"""
# (1) 基本文法
def zouyongling_family():
father = "王健林"
def hobby():
print("先定一個小目标,比如掙他一個億,這是我爸爸%s說的" % (father))
return hobby
func = zouyongling_family() # func = hobby
func()
# 擷取閉包函數使用的變量 __closure__ , cell_contents(了解)
# __closure__ 擷取單元格對象,這個對象中含有延長生命周期的變量值
tup = func.__closure__
print(tup) # (<cell at 0x00000226506595E8: str object at 0x00000226506EC450>,)
print(tup[0]) # <cell at 0x00000226506595E8: str object at 0x00000226506EC450>
# cell_contents 這個屬性 可以擷取單元格對象中的值,如果有證明是一個閉包,如果沒有,就不是一個閉包
print(tup[0].cell_contents)
# (2) 更新閉包函數
"""
特點:内函數使用了外函數的局部變量,該局部變量與内函數發生綁定,延長該變量的生命周期
"""
def huanglexi_family():
jiejie = "馬蓉"
meimei = "馬諾"
money = 1000
def jiejie_hobby():
nonlocal money
money -= 700
print("愛包包,愛手表,愛首飾,家裡的錢花的還剩下%s" % (money))
def meimei_hobby():
nonlocal money
money -= 200
print("甯願在寶馬裡哭,也不願意在自行車上面撒歡,家裡的錢都敗光了,還剩下%s" % (money) )
def big_master():
return (jiejie_hobby,meimei_hobby)
return big_master
func = huanglexi_family()# func = big_master
print(func)
tup = func() # big_master() => tup = (jiejie_hobby,meimei_hobby)
print(tup) # (<function huanglexi_family.<locals>.jiejie_hobby at 0x000001425AE73BF8>, <function huanglexi_family.<locals>.meimei_hobby at 0x000001425AE7C158>)
# 擷取閉包函數
jiejie_hobby = tup[0]
meimei_hobby = tup[1]
# 調用函數
jiejie_hobby()
meimei_hobby()
閉包函數 示例代碼
# ### 閉包的特點:
"""
内函數使用了外函數的局部變量,該變量與内函數發生綁定,延長該變量的生命周期
"""
def outer(val):
def inner(num):
return val + num
return inner
func = outer(10) # func = inner
res = func(5) # val + num = 15
print(res)
"""
代碼解析:
outer(10) val = 10
func = inner
func(5) num = 5
return val + num => return 10 + 5 => 15
print(res) => 15
"""
# ### 閉包的意義
"""
閉包可以優先使用外函數中的變量,并對閉包中的值起到了封裝保護的作用.外部無法通路.
"""
# 記錄滑鼠點選次數操作
# 方法一 : 全局變量的作用範圍太大,容易被串改
total = 0
def click():
global total
total += 1
print(total)
click() # 1
click() # 2
click() # 3
click() # 4
total = 100
click()
# 方法二 :
def myclick():
x = 0
def click():
nonlocal x
x += 1
print(x)
return click
func = myclick()
print(func)
func() # 1
func() # 2
func() # 3
func() # 4
x = 100
func()
閉包的特點 示例代碼
3. locals 與 globals、lambda表達式(匿名函數)
# ### locals 和 globals
"""
-- globals() :傳回字典,存放着全局作用域所有内容
-- locals() :傳回字典,目前作用域所有内容
"""
# (1)locals
"""
在函數外,擷取locals列印之前所有變量内容,形成字典,擷取全局作用域的内容
在函數内,擷取locals調用之前所有變量内容,形成字典,擷取局部作用域的内容
"""
# 在函數外
"""
a = 1
b = 2
res = locals()
c = 3
print(res)
"""
# 在函數内
"""
def func():
a = 1
b = 2
res = locals()
c = 3
print(res)
func()
"""
# (2)globals
"""
在函數外,擷取globals列印之前所有變量内容,形成字典,擷取全局作用域的内容
在函數内,擷取globals調用之前所有變量内容,形成字典,擷取全局作用域的内容
"""
# 在函數外
"""
a = 1
b = 2
res = globals()
c = 3
print(res)
"""
a1 = 1
b1 = 2
# 在函數内
def func():
a = 1
b = 2
res = globals()
c = 3
print(res)
c1 = 3
func()
d1 = 4
# globals 可以動态的建立變量
# 聲明變量
wangwen = "真靓"
# globals 建立一個全局變量 : 傳回的是全局字典,通過在字典中添加鍵值對,來動态建立變量,鍵就是變量名,鍵所對應的值也是這個變量的值
"""
dic = globals()
print(dic)
dic["yangmazi"] = "真聰明"
print(yangmazi)
"""
# globals 建立多個全局變量
"""動态建立p1~p5 5個變量"""
def func():
dic = globals()
print(dic)
for i in range(1,6):
dic[ "p%d" % (i) ] = i
func()
"""
"p%d" % (1) => "p1"
"p%d" % (2) => "p2"
"p%d" % (3) => "p3"
"p%d" % (4) => "p4"
"p%d" % (5) => "p5"
"""
print(p1,p2,p3,p4,p5)
locals和globals 示例代碼
# ### 匿名函數 : lambda表達式
"""
用一句話來表達隻有傳回值的函數
特點: 簡潔 , 高效
文法:
lambda 參數 : 傳回值
"""
# (1)沒有參數的lambda 表達式
def func():
return "我是func函數 ... "
# 改寫
func = lambda : "我是func函數 ... "
res = func()
print(res)
# (2)有參數的lambda 表達式
def func(n):
return type(n)
# 改寫
func = lambda n : type(n)
res = func(4.56)
print(res)
# (3)帶有判斷條件的lambda 表達式
def func(n):
if n % 2 == 0:
return "偶數"
else:
return "奇數"
res = func(3)
print(res)
# 三目運算符
"""
真區間值 if 條件表達式 else 假區間值
如果條件表達式滿足,
就傳回真區間值
否則,就傳回假區間值
"""
def func(n):
return "偶數" if n % 2 == 0 else "奇數"
res = func(3)
print(res)
# 改寫
func = lambda n : "偶數" if n % 2 == 0 else "奇數"
res = func(20)
print(res)
# 比較兩個數的大小,傳回最大值
def func(x,y):
if x>y:
return x
else:
return y
# lambda 改寫
func = lambda x,y : x if x>y else y
res = func(3,2)
print(res)
lambda表達式 示例代碼
day10