天天看點

python-函數入門(二)

一、函數對象

什麼是函數?

函數是第一類對象,指的是函數名指向的值(函數)可以被當做資料去使用

1.函數的特性

1.函數可以被引用,即函數可以把值指派給一個變量

def foo():
    print('from foo')

foo()
func=foo    #引用,指派
func()
print(foo)
print(func)      

2.函數可以當做參數傳給另一個函數

def hi():
    return "hi yasoob!"

def doSomethingBeforeHi(func):
    print("I am doing some boring work before executing hi()")
    print(func())

doSomethingBeforeHi(hi)      

3.可以當做一個函數的傳回值

def func(): # func=函數的内位址
    print('from func')

# print(func)

age=10
def bar(x):
    return x

res=bar(age)
print(res)

res=bar(func)
print(res)      

4.可以當做容器類型的元素

容器對象(list、dict、set等)中可以存放任何對象,包括整數、字元串,函數也可以作存放到容器對象中

def func(): # func=函數的内位址
    print('from func')
age=10
l=[age,func,func()]
print(l)      

二、函數嵌套

函數的嵌套又分為兩大類

1.函數的嵌套調用:在調用一個函數的過程中,其内部代碼又調用了其他函數

def max2(x,y):
    if x > y:
        return x
    else:
        return y

def max4(a,b,c,d):
    res1=max2(a,b)
    res2=max2(res1,c)
    res3=max2(res2,d)
    return res3

print(max4(1,2,3,4))      

2.函數的嵌套定義:一個函數内部又定義了另外一個函數

# from math import pi
# # print(pi)
#
# def circle(radius,action=0):
#     """
#     圓形相關運算
#     :param radius: 半徑
#     :param action: 0代表求面積,1代表求周長
#     :return: 面積或者周長
#     """
#     def area(radius):
#         return pi * (radius ** 2)
#
#     def perimiter(radius):
#         return 2 * pi * radius
#
#     if action == 0:
#         res=area(radius)
#     elif action == 1:
#         res=perimiter(radius)
#
#     return res
#
# print(circle(10,0))
# print(circle(10,1))      

三、名稱空間與作用域

1.什麼是名稱空間:

  名稱空間就是用來存放名字與記憶體位址綁定關系的地方(記憶體空間),但凡要查找值一定要通過名字,通路名字必須去查找名稱空間

2.名稱空間的三大類

  内置名稱空間:存放的是python解釋器自帶的名字 例如:len()、man()等

  全局名稱空間:存放的是檔案級别的名字(不是函數内,不是内置的)

x、y、z、b、foo都是全局
m不是
x=1
y=2
if x=1:
    z=3
while Ture:
    b=4
def foo():
    m=3      

  局部名稱空間:在函數内部定義的

  生命周期:

    内置名稱空間:在解釋器啟動時生效,關閉時則失效

    全局名稱空間:在解釋器解釋執行python檔案時生效,檔案執行完畢後則失效

    局部名稱空間:隻在調用函數時臨時産生該函數的局部名稱空間

  加載順序:内置===》全局===》局部

  查找名字的順序:

    基于目前所在位置往上查找,假設目前站在局部,查找順序:局部==》全局==》内置

                 假設目前站在全局,查找順序:全局=》内置

注:名字的查找順序,在函數定義階段就已經被固定死了(即在檢測文法時就已經确定了名字的查找順序),與函數調           用位置無關,無論在任何地方調用函數,都必須回到當初定義函數的位置去确定名字的查找關系

# x=111
# def outer():
#     def inner():
#         print('from inner',x) # x通路的時全局名稱空間中x
#     return inner
#
# f=outer()
# # print(f)
#
# x=222
# f()      

3.作用域

作用域指的是作用的範圍,分為兩種,全局作用域和局部作用域

1.全局作用域:包含的是内置名稱空間與全局名稱空間中的名字

  特點:全局有效,全局存活

2.局部作用域:包含的是局部名稱空間中的名字

  特點:局部有效,臨時存活

補:global  和  nonlocal

#global:在局部聲明一個名字是來自于全局作用域的,可以用來在局部修改全局的不可變類型
# x=1
# def foo():
#     global x
#     x=2
#
# foo()
# print(x)

#nonlocal:聲明一個名字是來自于目前層外一層作用域的,可以用來在局部修改外層函數的不可變類型
# x=0
# def f1():
#     x=111
#     def f2():
#         nonlocal x
#         x=222
#     f2()
#     print(x)
#
# f1()
# print(x)      

四、閉包函數

1.什麼是閉包函數?

指的是定義一個函數内部的函數,該内部函數包含對外層函數作用域名字的引用

需要結合函數對象的概念将閉包函數傳回到全局作用域去使用,進而打破函數的層級限制。

def outter():
    x=111
    def inner():
        print(x)
    return inner

f=outter() #f=outter内的inner

# x=22222
# f()
def func():
    x=3333
    f()

func()      

2.為何要用閉包函數?

閉包函數提供了一種為函數體傳值的解決方案

3.如何使用閉包函數

為函數傳值的方式有兩種,參數和閉包(目前所學)

# 為函數體傳值的方式一:參數
# def func(x,y):
#     print(x+y)
#
# func(1,2)      
# 為函數體傳值的方式二:閉包
# def outter(x,y):
#     # x=1
#     # y=2
#     def func():
#         print(x+y)
#     return func
#
# f=outter(1,2)
# f()      

閉包的概念有的晦澀難以了解,期待接下裡的學習!

    

焚膏油以繼晷,恒兀兀以窮年。