函數對象


Python-12

@(Python)

一、函數對象

  • 函數是第一類對象,意思是函數可以被當做數據處理
  • 函數對象:就是函數不帶括號
  • 函數對象,可以將定義在函數內的函數,通過return返回值,返回到全局中使用,從而打破函數的層級限制
  • Python中一切皆對象

funcfunc()的區別

  • func()是函數的返回值
  • func函數名記錄了值的內存地址(記錄了值的內存地址,相當於連接函數名和值的線),函數名就是函數的內存地址
  • print(func)打印的是func函數名記錄的值的內存地址
  • print(func())打印的是func函數的返回值

Alt text

① 函數名可以被用來引用(賦值給一個變量)

# func是一個函數
y=x
f=func
print(f)   # 就相當於print(func)
f()   # f()就相當於func()調用函數

② 函數名當做參數傳給一個函數

Alt text

③ 函數名可以當做函數的返回值

Alt text

④ 函數名可以當做容器類型的元素

可以把函數的內存地址(或理解為函數名的內存地址),當做元素

Alt text

利用函數名為容器類型的元素,來調用函數

# 取款
def qk():
    print('取款成功')

# 轉賬
def zz():
    print('轉賬成功')
# 支付
def zf():
    print('支付成功')


func_dict={
    '1':qk,
    '2':zz,
    '3':zf,
}

while True:
    msg='''
    1. 取款
    2. 轉賬
    3. 支付
    4. 退出   
    '''
    print(msg)
    func_num=input('輸入數字>>')
    if func_num == '4' : break
    if func_num not in func_dict:
        print('不在范圍')
        continue
    func_dict[func_num]()

二、函數的嵌套

1. 函數的嵌套定義

  • 函數的嵌套是在函數中再定義函數
  • 在函數內中定義的函數,只能在這個函數內使用(一般情況下)
def func1():
    def func2():
        print('函數2')
  • 通過函數嵌套,將一個大功能的小功能嵌套進去,不同的功能匯聚到一起,類似於封裝成一個工具箱
  • 例子:利用函數嵌套和函數對象當做容器元素,來寫出計算圓面積和周長的功能
from math import pi    # 計算圓的公式需要調用
def yuan(banjing,action):
    def mianji():
        return pi * (banjing ** 2)
    def zhouc():
        return pi * banjing * 2
    if action == 'mianji':
        return mianji()    # 這是yun函數的返回值
    elif action == 'zhouc':
        return zhouc()

func1=input('半徑>>')
func1=int(func1)
func2=input('計算類型>>')

print(yuan(func1,func2))   # 也可以使用默認形參固定一個常用的類型

2. 函數的嵌套調用

  • 使用函數嵌套,在調用一個函數時,也調用了其他函數
  • 如果一個功能可以被重復調用,就可以單獨做成一個功能,使用其他函數再調用

Alt text

三、名稱空間與作用域

1. 名稱空間

  • 專門用來存名字的空間(變量名、函數名等的內存地址)
  • 名稱空間,是存放名字和值綁定關系的地方

① 內置名稱空間

  • 內置命名空間:Python解釋器自帶的名字
  • 生命周期:在解釋器啟動時生效,在解釋器關閉時失效

② 全局名稱空間

  • 全局名稱空間:除了內置和局部空間外,其余都是全局名稱空間
  • 全局名稱空間,是在文件執行時產生的(頂頭寫的代碼使用的就是全局名稱空間)
  • 生命周期:在文件執行時生效,在文件執行完畢后失效

③ 局部名稱空間

  • 存放函數調用期間函數體產生的名字,即函數內定義的名字
  • 生命周期:執行文件時,只有被調用了才會臨時生效,在函數執行完畢后失效,自動釋放

內置、全局、局部名稱空間的加載順序

  • ① 內置名稱空間--->② 全局名稱空間--->③ 局部名稱空間

內置、全局、局部名稱空間的查找順序

  • ① 局部名稱空間--->② 全局名稱空間--->③ 內置名稱空間
  • 基於當前位置,然后按順序找

Alt text
Alt text

2. 作用域

  • 作用域就是名稱空間的作用的范圍,是對名稱空間的再分類

① 全局作用域

  • 全局作用域:就是全局作用范圍,包括:內置名稱空間和全局名稱空間
  • 全局有效:內置命名空間和全局命名空間
  • 全局存活:從程序開始存活,一直到程序的結束

② 局部作用域

  • 局部作用域:就是局部作用范圍,包括:局部命名空間
  • 局部有效,臨時存活

  • 作用域關系是在函數定義階段就固定好了,但凡要調用函數就需要去函數的定義階段找作用域關系

Alt text

x=10
def func1():
    print(x)

x=10000000000000000000000
def func2():
    x=11111111111
    func1()

func2()   # 以調用為分隔符,往前找

Alt text

Alt text

x=10
def func1():
    x=777777777777777777  # 先找局部空間,再找全局空間,全局空間有多個找上面最近的
    print(x)

x=10000000000000000000000
def func2():
    x=11111111111
    func1()

func2()   # 以調用為分隔符,往前找

③ 作用域的應用:

  • 打破層級限制,利用return將函數名轉到全局,再調用

Alt text
Alt text

def f1():
    def inner():
        print('from inner')
    return inner

f1()() # f1()得到的是return的值,相當於inner,f1()() == inner()

# 或者

f=f1()
f()   # 相當於f1()()

Alt text

def f1():
    x=1
    def inner():
        print('from inner',x)
    return inner

f=f1()   # 相當於f=inter

def bar():
    x=11111111111111
    f()   # 相當於inter()

bar()
  • 說明:回到定義階段,按照先局部,后全局的順序找,如果局部沒有才找全局,如果有多個全局,就以調用函數為分隔線,往上找最近的

  • 在函數體內,改全局的東西,需要使用global x,比如global xx拿到全局用,同代碼段往下找最后一個
  • 但是盡量不要改全局,盡量做成獨立的功能,對其他無影響
x=1
def foo():
    global x
    x=111

foo()
print(x)
  • nonlocal會往本函數體外層找,往上找最近的,但是還是在大的函數內,找到就改,找不到就報錯
x=1
def f1():
    def f2():
        x=2222222            # 找到的內容
        def f3():
            nonlocal x
            x=111111111111   # 要改成什么
        f3()
        print(x)   # 打印這一層的,看nonlocal是后生效
    f2()

f1()

Alt text

  • 在局部如果想要修改全局的可變類型,不需要借助任何聲明,可以直接修改,比如可以改字典,列表等
  • 在局部如果想要修改全局的不可變類型,需要借助global聲明,聲明為全局的變量就可以直接修改

Alt text


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM