天天看點

day10-Python運維開發基礎(函數嵌套、nonlocal聲明局部變量、閉包、locals/globals、lambda表達式)

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