1. 程式人生 > >python函數基礎

python函數基礎

函數 def 閉包函數

一、為什麽要有函數?沒有函數有什麽問題?

1、組織結構不清晰,可讀性差

2、代碼冗余

3、可擴展性差

二、函數的分類:

1、內置函數:python解釋器已經為我們定義好了的函數即內置函數,我們可以拿來就用而無需事先定義

2、自定義函數:我們自己根據需求,事先定制好我們自己的函數來實現某種功能,如果遇到相同的情景可以直接調用

三、定義函數的三種形式

第一種:無參函數 (應用場景僅僅只是執行一些操作)

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

第二種:有參函數 (需要根據外部傳進來的參數,才能執行相應的邏輯)

有參函數分為形參和實參

形參包含:

1、位置形參:必選參數

def foo(name,age,sex):
    print(name)
    print(age)
    print(sex)

2、默認函數:形參在定義時就已經為其賦值

實參包含:

1、關鍵字實參:按照key=value的形式定義的實參

2、位置實參:按照位置給形參傳值

foo('jim',18,'male')

還有一種是可變長參數:可變長參數指的是實參的個數多了,實參無非位置實參和關鍵字實參兩種

形參處理按照位置定義的實參溢出的情況:*

def foo(x,y,*args):          #*把位置實參多余的賦值給args, args=(3, 4, 5)
    print(x)
    print(y)
    print(args)
foo(1,2,3,4,5)


形參處理按照關鍵字定義的實參溢出的情況:**

def foo(x,y,**awargs):          #**把位置實參多余的賦值給awargs, awargs={'z': 3, 'e': 4}
    print(x)
    print(y)
    print(awargs)
foo(x=1,y=2,z=3,e=4)

最後是命名關鍵字參數:*後定義的參數,必須被傳值(有默認值的除外),且必須按照關鍵字實參的形式傳遞

def foo(x,y,*args,a=1,**kwargs):
    print(x, y)           #處理傳的參數後結果是1 2
    print(args)           #處理傳的參數後結果是(3, 4, 5)
    print(a)               #處理傳的參數後結果是1
    print(kwargs)         #處理傳的參數後結果是{'c': 4, 'd': 5}
foo(1,2,3,4,5,c=4,d=5)

第三種:空函數 (設計代碼結構)

四、函數調用

1、函數的返回值

return的返回值沒有類型限制

1. 沒有return:返回None,等同於return None

2. return 一個值:返回該值

3. return 多個值:返回的多個值以元組的形式

2、函數調用的三種形式

1、語句形式

2、表達式形式

3、當做另外一個函數的參數

def foo(x,y):
    if x>=y:
        return x
    else:
        return y
foo(1,2)                    #語句形式
res=foo(1,2)*10       #表達式形式,取到的結果在表達式裏做運算
res2=foo(foo(1,2),3) #函數調用可以當做另外一個函數的參數
print(res2)


五、名稱空間與作用域

1、名稱空間的加載順序

#1、python解釋器先啟動,因而首先加載的是:內置名稱空間

#2、執行*.py文件,然後以文件為基礎,加載全局名稱空間

#3、在執行文件的過程中如果調用函數,則臨時產生局部名稱空間

2、名稱空間的查找順序

局部名稱空間--->全局名稱空間--->內置名稱空間

3、作用域

作用域關系是在函數定義階段就已經固定的,與函數的調用位置無關

x=1
def num():
    x=2
    print(x)                    #x的值為2
    x=3
num()


六、閉包函數

1、閉包函數: 內部函數包含對外部作用域而非全局作用域的引用

2、閉包函數的意義

返回的函數對象,不僅僅是一個函數對象,在該函數外還包裹了一層作用域,這使得,該函數無論在何處調用,優先使用自己外層包裹的作用域

import requests
def outter(url):
    # url = 'https://www.baidu.com'
    def get():
        response=requests.get(url)
        if response.status_code == 200:                #取狀態碼是200的
            print(len(response.text))
    return get
baidu=outter('https://www.baidu.com')
baidu()


七、裝飾器

1、遵循的原則

開放封閉原則:對修改封閉,對擴展開放

1、不修改被裝飾對象的源代碼

2、不修改被裝飾對象的調用方式

2、模擬打開網頁的時間

import time
def index():
    time.sleep(3)
    print('hello')
def inner():
    start=time.time()                           #開始的時間
    index()
    stop=time.time()                          #網頁打開後的時間
    print(stop-start)
inner()


上面的實現了我們的需要,但是inner函數包含index函數,只能統計index的執行時間,不利於代碼的重用,所以要改進一下

import time
def index():
    time.sleep(3)
    print('hello')
def timmer(func):
    def inner():
        start=time.time()
        func()
        stop=time.time()
        print(stop-start)
    return inner
index=timmer(index)    #index不是以前的index,是重新更名的,這樣對用戶調用index函數時,操作不會改變
index()

最後版本

import time
def timmer(func):
    def wrapper(*args,**kwargs):
        start_time=time.time()
        res=func(*args,**kwargs)
        stop_time=time.time()
        print('run time is %s' %(stop_time-start_time))
        return res
    return wrapper
@timmer
def foo():
    time.sleep(1)
    print('from foo')
foo()

執行流程:程序執行時,空過函數定義階段,執行@timmer,跳到timmer函數,執行到return wrapper------> @timmer------->foo()----->執行wrapper函數--->執行foo()




python函數基礎