1. 程式人生 > >Python_函數

Python_函數

span linux -i 組合 imp 默認參數 擴展 cto 接收參數

函數

函數的定義:函數是指將一組語句的集合通過一個名字(函數名)封裝起來,想要執行這個函數,只需調用其函數名即可。

函數的特性:

  • 減少重復代碼;
  • 方便修改,更易擴展;
  • 保持代碼的一致性。

函數名命名規則:

  • 函數名必以下劃線或者字母開頭,可以包含任意字母、數字或下劃線的組合,不能使用任何標點符號;
  • 函數名是區分大小寫的;
  • 函數名字不能是保留字。

語法定義:

def add(a, b):                                        # 函數名
    print(a + b)
add(3,7)                                              #
調用函數

一、函數的參數

形參與實參:

形參:形參變量只有在被調用時才分配內存單元,在調用結束時,即可釋放所分配的內存單元。因此,形參只有在內部有效。函數的調用結果返回主調用函數後則不能再使用此形參變量。

實參:實參可以使常量、變量、表達式、函數等,無論實參是任何類型的量,在進行函數調用時,他們都必須有確定的值,以便把這些值傳送給形參,因此預先用賦值、輸入等辦法使參數獲得確定值。

def add(a, b):                                              # a, b 為形參數
    res = a + b
    
return res c = add(3, 4) # 3, 4 為實參 print(c)

函數參數:

  • 必須參數
  • 關鍵字參數
  • 默認參數
  • 不定長參數

必須參數:必須參數必須以正確的順序傳入參數,調用時的數據必須和聲明時的一樣。

def mu_info(name, age):
    print(Name:%s \nAge:%d % (name, age))

mu_info(wj, 24)

關鍵字參數:傳入參數的時候帶上關鍵字,即使順序不對,依然可以辨識。

def mu_info(name, age):
    
print(Name:%s \nAge: %d % (name, age)) mu_info(age=24, name=wj)

默認參數:形參定義時就確定好的值調用參數的時候可以省略。

必選參數在前,默認參數在後,否則Python解釋器會報錯,

當函數有多個參數時,把變化大的參數放前面,變化小的參數放後面,變化小的參數可以作為默認參數。

def mu_info(name, age, sex=male):
    print(Name:%s \nAge: %d \nsex:%s\n % (name, age, sex))
mu_info(wj, 24)
mu_info(zl, 24)
mu_info(cf, 25, female)

不定長參數:不定常參數可以處理比當初聲明時更多的參數。不定長參數和其他三種參數不同,聲明時不會命名。

*args指的是接受所有無命名參數

def add(*args):
    sum = 0
    for i in args:
        sum = sum + i
    print(sum)

add(1, 2, 3, 4)

**kwargs指的是接受鍵值對的參數保存方式為字典,進行函數內部運算。

def print_info(**kwargs):
    for i in kwargs:
        print(%s:%s % (i, kwargs[i]))

print_info(name=mu, age=18, sex=male, job=Linux, height=180)

不定長參數的位置:*args只能放左邊。**kwargs只能放右邊不能改變,實參也要按照這個位置順序來,不然無法保存。

def print_info(*args, **kwargs):
# def print_info(**kwargs,*args):                                                       # 錯誤示範
    for i in args:
        print(i)
    for o in kwargs:
        print(%s:%s % (o, kwargs[o]))

print_info(mu, 24, sex=male, job=Linux, height=180)
# print_info(sex=‘male‘, ‘mu, 24, job=‘Linux‘, height=180)                              # 錯誤示範
# print_info(sex=‘male‘, job=‘Linux‘, height=180, ‘mu‘, 24)                             # 錯誤示範

不定長參數+默認參數

  如果有默認參數,放左邊。

def print_info(sex=male, *args, **kwargs):
    print(sex)
    print(args)
    print(kwargs)

# print_info()
print_info(mu, 1, 2, 3, job=Linux)                  # sex 沒有打印,因為傳入的參數‘mu’占用了sex的位置,所以單獨打印了‘mu’,如不是把它打印在元組中

  標準順序

def func(name, age=22, *arge, **kwargs)

二、函數的作用域

python中的作用域分4種情況
  L: local,局部作用域,即函數中定義的變量;
  E: enclosing,嵌套的父級函數的局部作用域,即包含此函數的上級函數的局部作用域,但不是全局的;
  G: globa,全局變量就是模塊級別的定義的變量;
  B: built-in,系統固定模塊裏的變量,比如:int,byrearray等。
搜索變量的優先級順序依次是:局部作用域 > 外層作用域 > 當前模塊中的全局 > python內置作用域, 也就是LEGB。

局部作用域不能修改全局作用域的變量,如果想要修改,需要用global聲明。

name = "全局作用域"
def change_name(name):
    print("打印的是那個?:", name)
    name = "局部作用域"
    print("重新賦值後打印的是那個?:" , name)

change_name(name)
print("全局作用域是否發生改變?:", name)
name
= "全局作用域" def change_name(): global name print("打印的是那個?:", name) name = "局部作用域" print("重新賦值後打印的是那個?:" , name) change_name() print("全局作用域是否發生改變?:", name)

內層局部作用域不能修改外層作用域的變量,如果想要修改,需要用nonlocal聲明。

def change_one():
    name = "外層作用域"
    print(name)
    def change_two():
        name = "局部作用域"
        print(name)
    change_two()
    print(name)
change_one()

def change_one():
    name = "外層作用域"
    print(name)
    def change_two():
        nonlocal name
        name = "局部作用域"
        print(name)
    change_two()
    print(name)
change_one()

小結:

1. 變量查找順序: LEGB,局部作用域 > 外層作用域 > 當前模塊中的全局 > python內置作用域
2. 只有模塊、類、及函數才能引入新作用域
3. 對於一個變量,內部作用域先聲明就會覆蓋外部變量,不聲明直接使用,就會使用外部作用域的變量
4. 內部作用域要修改外部作用域變量的值時,全局變量要使用global關鍵字,嵌套作用域變量要使用nonlocal關鍵字。nonlocal是python3新增的關鍵字,有了這個關鍵字,就訥訥個完美的實現閉包了。

三、函數返回值

想要獲取函數的執行結果,可以用return語句將結果返回。

註意:

  函數裏如果沒有return,結束時默認會返回一個None;

  return後可以返回多個對象,如果是多個對象,python會幫我們把多個對象封裝為一個元組,元組中的元組就是各個對象;

  函數在執行過程中只要遇到return語句,就會停止執行並返回結果,so 也可以理解為 return 語句代表著函數的結束。

def f():
    print(ok)
    return
    # return None                                         # 如果不寫,python,默認追加這個
print(f())

四、高階函數

定義:變量可以指向函數,函數的參數能接收變量,那麽一個函數就可以接收另一個函數作為參數,這種函數就稱之為高階函數。

高階函數特點:

  • 函數名可以進行賦值;
  • 函數名可以作為函數參數名還可以作為函數的返回值。

作為函數名:

def f(n):
    return n * n

def test(a, b, func):
    res = func(a) + func(b)
    return res

print(test(3, 2, f))

作為函數的返回值:

def foo():
    def test():
        return 8
    return test                                                     # 其實此時foo() = test

ret = foo()
print(ret)                                                          # 打印的就是還沒有調用的test,也就是test的內存地址,想要調用,再在後邊加()就行,打印出來的就是test的值
print(ret())
print(foo())
print(foo()())

五、遞歸函數

遞歸的特性:

  • 調用自身的函數;
  • 需要有一個明確的結束條件;
  • 每次進入更深一層遞歸時,問題規模相比上次遞歸都應有所減少;
  • 遞歸能處理的,循環都能處理;
  • 遞歸效率不高,遞歸層次過多會導致棧溢出(在計算機中,函數調用是通過棧(stack)這種數據結構實現的,每當進入一個函數調用,棧就會加一層棧幀,每當函數返回,棧就會減一層棧幀。由於棧的大小不是無限的,所以,遞歸調用的次數過多,會導致棧溢出)

遞歸算階乘:

# 正常算階乘
def f(n):
    num = 1
    for i in range(n):
        num = (i + 1) * num
    return num
print(f(5))


# 遞歸引用自己
def fact(n):
    if n == 1:
        return 1
    return n * fact(n - 1)
print(fact(5))

斐波那契數列:

# 正常算法
def f(x):
    a, b = 0, 1
    n = 0
    while n <= x:
        # print(b)
        a, b = b, a + b
        n = n + 1
    return b
print(f(7))


# 引用自己
def fibo(n):
    if n <= 1:
        return n
    return  fibo(n - 1) + fibo(n -2)
print(fibo(5))

六、內置函數

filter:過濾器,需要兩個參數。第一個參數是函數,第二個參數是一個序列,只過濾,不修改。

str = [a, b, c, d]
def fun(n):
    if n != a:
        return n
ret = filter(fun, str)                                        # ret是一個叠代器對象
print(list(ret))

map:可對列表進行修改

str = [a, b, c, d]
def fun(n):
    return n + mu

ret = map(fun, str)                                           # ret是一個叠代器對象
print(list(ret))

reduce:接收參數時,一個函數f,一個列表,傳入reduce的函數必須有兩個參數,reduce對list中的每次參數反復調用函數f,並返回最終結果

from functools import reduce
def f(x, y):
    return x + y
print(reduce(f, range(1,10)))

lambda算法:lambda a, b : a + b

用內置函數算階乘

from functools import reduce
print(reduce(lambda x, y : x * y, range(1,6)))

Python_函數