天天看點

【Python基礎】Python 函數使用總結

【Python基礎】Python 函數使用總結

我的施工之路

目前已完成,以下五期Python專題總結:

1​​我的施工計劃​​

2​​數字專題​​

3​​字元串專題​​

4​​清單專題​​

5​​流程控制專題​​

6​​程式設計風格專題​​

今天是Python函數專題,目錄結構:

  • Python 函數專題
  • 基礎部分
  • 1 函數組成
  • 2 引用傳參
  • 3 預設參數與關鍵字參數
  • 4 可變參數
  • 5 内置函數
  • 進階部分
  • 6 偏函數
  • 7 遞歸函數
  • 8 匿名函數
  • 9 高階函數
  • 10 嵌套函數
  • 總結

Python 函數專題

函數是一個接受輸入、進行特定計算并産生輸出的語句集。

我們把一些經常或反複被使用的任務放在一起,建立一個函數,而不是為不同的輸入反複編寫相同的代碼。

Python提供了​

​print​

​​、​

​sorted​

​​、​

​max​

​​、​

​map​

​等内置函數,但我們也可以建立自己的函數,稱為使用者定義函數。

基礎部分

1 函數組成

如下自定義函數:

def foo(nums):
    """ 傳回偶數序列"""
    evens = []
    for num in nums:
        if num%2==0:
            evens.append(num)
    return evens      

可以看到函數主要組成部分:

  • 函數名:​

    ​foo​

  • 函數形參:​

    ​nums​

  • ​:​

    ​​: 函數體的控制字元,作用類似​

    ​Java​

    ​或​

    ​C++​

    ​的一對​

    ​{}​

  • 縮進:一般為4個字元
  • ​"""​

    ​:為函數添加注釋
  • ​return​

    ​: 函數傳回值

以上函數求出清單​

​nums​

​中的所有偶數并傳回,通過它了解Python函數的主要組成部分。

2 引用傳參

定義好一個函數後,使用:函數名+()+實參,調用函數,如下方法:

foo([10,2,5,4])      
【Python基礎】Python 函數使用總結

其中​

​[10,2,5,4]​

​​為實參,它通過​

​by reference​

​​方式傳給形參​

​nums​

​​,即​

​nums​

​​指向清單頭,而不是重新複制一個清單給​

​nums​

​.

再看一個引用的例子:

def myFun(x): 
    x[0] = 20      

如下調用:

lst = [10, 11, 12, 13, 14, 15] 
myFun(lst)      

實參​

​lst​

​​和形參​

​x​

​都指向同一個清單:

【Python基礎】Python 函數使用總結

是以,對​

​x[0]​

​​修改實際就是對實參​

​lst​

​的修改,結果如下:

【Python基礎】Python 函數使用總結

但是,有時在函數内部形參指向改變,是以實參與形參的指向分離,如下例子:

def myFun(x):  
    x = [20, 30, 40]
    x[0] = 0      

調用:

lst = [10, 11, 12, 13, 14, 15] 
myFun(lst)      

​x​

​​ 被傳參後初始指向​

​lst​

​,如下所示:

【Python基礎】Python 函數使用總結

但是,執行​

​x = [20, 30, 40]​

​​後,對象​

​x​

​​重新指向一個新的清單對象​

​[20,30,40]​

​:

【Python基礎】Python 函數使用總結

是以,對于​

​x​

​​内元素的任何修改,都不會同時影響到​

​lst​

​,因為指向已經分離。

3 預設參數與關鍵字參數

Python函數的參數,可以有初始預設值,在調用時如果不指派,則取值為預設值,如下例子:

def foo(length,width,height=1.0):
    return length*width*height      

調用​

​foo​

​​函數,沒有為​

​height​

​​傳參,是以取為預設值​

​1.0​

​:

r = foo(1.2,2.0)
print(r) # 2.4      

使用預設值有一點需要區分,有的朋友會與關鍵字參數混淆,因為它們都是​

​para=value​

​的結構,但是有一個很明顯的不同:預設值是聲明在函數定義時,關鍵字參數是在函數調用時使用的此結構。如下例子:

def foo(length,width,height=1.0): # height是預設參數
    return length*width*height

foo(width=2.0,length=1.2) #确定這種調用後才确定width和length是關鍵字參數      

确定以上調用後,才确定​

​width​

​​和​

​length​

​是關鍵字參數,并且關鍵字參數不必按照形參表的順序調用。

4 可變參數

​Java​

​​和​

​C++​

​在解決同一個函數但參數個數不同時,會使用函數重載的方法。Python使用可變參數的方法,非常靈活。

可變參數是指形參前帶有​

​*​

​的變量,如下所示:

def foo(length,*others):
    s = length
    for para in others:
        s *= para
    return s      

我們可以像下面這樣友善的調用:

foo(1.2,2.0,1.0) # 2.4      
【Python基礎】Python 函數使用總結

如上,帶一個星号的參數被傳參後,實際被解釋為​

​元組對象​

​。我們還可以這樣調用:

foo(1.2) # 1.2      

5 内置函數

總結完函數的參數後,再舉幾個Python内置的常用函數。

pow

大部分朋友應該知道​

​pow​

​是個幂次函數,比如求

pow(2,3)      

除此以外,​

​pow​

​還有第三個參數,使用更高效的算法實作求幂後再求餘數:

pow(2,3,5) # 3      

max,min

max,min用來求解最大最小值,實作​

​relu​

​函數:

def relu(x):
    return max(x,0)      

sorted

sorted函數完成對象排序,它能接收一個指定排序規則的函數,完成定制排序。如下,根據字典值絕對值從小到大排序:

d = {'a':0,'b':-2,'c':1}
dr = sorted(d.items(),key=lambda x:abs(x[1])) 
print(dr) # [('a', 0), ('c', 1), ('b', -2)]      

進階部分

Python有一個專門操作函數的子產品:​

​functools​

​,能實作一些關于函數的特殊操作。

6 偏函數

偏函數固定函數的某些參數後,重新生成一個新的函數。

通常用法,當函數的參數個數太多,需要簡化時,使用​

​partial​

​建立一個新的函數。

假設我們要經常調用​

​int​

​​函數轉換二進制字元,設定參數​

​base​

​為2:

int('1010',base=2)      

為了避免每次都寫一個參數base,我們重新定義一個函數:

def int2(s):
    return int(s,base=2)      

以後每次轉化字元串時,隻需​

​int2('1010​

​)即可,更加簡便。

偏函數也能實作上述功能:

from functools import partial

intp = partial(int,base=2)      

那麼有的朋友會問,偏函數就是個雞肋,重新定義的​

​int2​

​​更加直覺容易了解,這個角度講确實是這樣。但是​

​int2​

​​不能再接收​

​base​

​​參數,但是​

​intp​

​​函數還是能接收​

​base​

​參數,依然保留了原來的參數:

intp('10',base=16) # 16      

可能看到這裡的讀者還是有些迷糊,不太确定怎麼使用偏函數。可以先記住:修改内置函數的預設參數,就像内置函數​

​int​

​預設參數base等于10,使用偏函數調整預設base值為2.

7 遞歸函數

遞歸函數是指調用自身的函數。如下使用遞歸反轉字元串:

def reverseStr(s): 
    if not s:
        return s 
    return reverseStr(s[1:])+s[0]
    
print(reverseStr('nohtyp')) # python      

​reverseStr​

​​函數裡面又調用了函數​

​reverseStr​

​,是以它是遞歸函數。

使用遞歸函數需要注意找到正确的遞歸基,防止陷入無限遞歸。

更多使用遞歸的例子大家可參考此公衆号之前推送。

8 匿名函數

匿名函數是指使用​

​lambda​

​關鍵字建立的函數。它的标準結構如下:

lambda 形參清單: 含有形參清單的表達式      

表達式的計算值即為​

​lambda​

​函數的傳回值。

如下​

​lambda​

​函數:

lambda x,y: x+y      

它等價于下面的​

​f​

​函數:

def f(x,y):
    return x+y      

lambda函數常做為​

​max​

​​,​

​sorted​

​​,​

​map​

​​,​

​filter​

​等函數的key參數。

9 高階函數

可以用來接收另一個函數作為參數的函數叫做高階函數。

如下​

​f​

​​有一個參數​

​g​

​​,而​

​g​

​​又是函數,是以​

​f​

​是高階函數:

def f(g):
    g()      

Python 中經常會遇到高階函數,今天介紹幾個内置的常用的高階函數。

map

map 函數第一個參數為函數,它作用于清單中每個的元素。

如下,清單中的單詞未按照首字母大寫其他字元小寫的規則,使用​

​map​

​​一一​

​capitalize​

​每個元素:

m = map(lambda s: s.capitalize(), ['python','Very','BEAUTIFUL'])
print(list(m))      

結果:

['Python', 'Very', 'Beautiful']      

reduce

reduce 高階函數實作化簡清單,它實作的效果如下:

如下例子,函數​

​f​

​​等于​

​x+y​

​,求得兩數之和,然後再與第三個數相加,依次下去,直到清單尾部,進而得到整個清單的和:

from functools import reduce 

def f(x,y):
    return x+y

r = reduce(f, [1,3,2,4])
print(r) # 10      

以上​

​reduce​

​求解過程等于:

需要注意:​

​reduce​

​​函數要求​

​f​

​必須帶2個參數,隻有這樣才能完成歸約化簡。

10 嵌套函數

嵌套函數是指裡面再嵌套函數的函數。

如下例子,将清單轉化為二叉樹。已知清單​

​nums​

​,

nums = [3,9,20,None,None,15,7],轉化為下面二叉樹:

【Python基礎】Python 函數使用總結

二叉樹定義:

class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None      

建構滿足以上結構的二叉樹,可以觀察到:樹的父節點和左右子節點的關系:

基于以上公式,再使用遞歸建構二叉樹。

遞歸基情況:

if index >= len(nums) or nums[index] is None:
    return None      

遞歸方程:

根據以上分析,得到如下代碼,​

​list_to_binarytree​

​​函數是嵌套函數,它裡面還有一個​

​level​

​子函數:

def list_to_binarytree(nums):
    def level(index):
        if index >= len(nums) or nums[index] is None:
            return None
        
        root = TreeNode(nums[index])
        root.left = level(2 * index + 1)
        root.right = level(2 * index + 2)
        return root

    return level(0)

binary_tree = list_to_binarytree([3,9,20,None,None,15,7])      

通常使用嵌套函數的場景:實作一個功能隻需要編寫2個函數,寫成一個​

​class​

​​好像顯得有些不必要,寫成嵌套後更簡潔,并且某些參數能共享,親和性會更好。不妨體會上面的​

​nums​

​參數。

總結

函數專題主要總結了以下:

  • Python 函數專題
  • 基礎部分
  • 1 函數組成
  • 2 引用傳參
  • 3 預設參數與關鍵字參數
  • 4 可變參數
  • 5 内置函數
  • 進階部分
  • 6 偏函數
  • 7 遞歸函數
  • 8 匿名函數
  • 9 高階函數
  • 10 嵌套函數
  • 總結