筆記:Python函式

假裝鎮定發表於2018-10-01
  1. 呼叫函式
    Python內建了很多可以直接呼叫的函式
    呼叫一個函式,需要知道函式的名稱和引數。
Python官方網站提供的文件
 https://docs.python.org/3/library/functions.html
如:
 1)abs() 求絕對值
 2)max() 獲取最大值
 	接收任意多個引數,並返回最大那個
 Python內建的常用函式還包括資料型別轉換函式
  如:str()函式可以把其他資料型別轉換為字串
  >>>str(500)
  '500'

函式名其實就是指向一個函式物件的引用,完全可以把函式名賦給一個變數,相當於給這個函式起了一個別名:

#變數w指向max函式
>>>w = max
#因此,也可以通過w呼叫max函式
>>>w(1,5,10,55)
55

在這裡插入圖片描述

  1. 定義函式
    在Python中,定義一個函式要使用def 語句,依次寫出函式名、括號、括號中的引數和冒號: ,然後,在縮排塊中編寫函式體,函式的返回值用return 語句返回
自定義一個求最大數的`w_max`函式:
def w_max(a, b):
	if a > b:
		return a
	else:
		return b

儲存該自定義函式至:py1.py
命令列模式切換到該檔案的當前目錄下啟動Python直譯器,用
from py1 import w_max 來匯入w_max函式,#py1位檔名

在這裡插入圖片描述
空函式
如果想定義一個無任何操作的空函式,可以用pass語句

def empty_function():
	pass

pass可以用來作為佔位符,比如現在還沒有想好怎麼寫函式的程式碼,就可以先放一個pass,讓程式碼能執行起來,如:

if 1 > 0:
	pass
缺少pass,程式碼執行就會有語法錯誤

引數檢查
呼叫函式時,如果引數個數不對,Python直譯器會自動檢查出來,並丟擲TypeError
但如果是引數型別不對,Python直譯器就無法幫我們檢查

返回多個值
函式可以返回多個值,如:遊戲中經常需要從一個點移動到另一個點,給出座標、位移和角度,就可以計算出新的新的座標

import math

def move(x, y, step, angle=0):
    nx = x + step * math.cos(angle)
    ny = y - step * math.sin(angle)
    return nx, ny

import math語句表示匯入math包,並允許後續程式碼引用math包裡的sin、cos等函式
然後,我們就可以同時獲得返回值:

>>> x, y = move(100, 100, 60, math.pi / 6)
>>> print(x, y)
151.96152422706632 70.0

但其實這只是一種假象,Python函式返回的仍然是單一值:

>>> r = move(100, 100, 60, math.pi / 6)
>>> print(r)
(151.96152422706632, 70.0)

原來返回值是一個tuple!但是,在語法上,返回一個tuple可以省略括號,而多個變數可以同時接收一個tuple,按位置賦給對應的值,所以,Python的函式返回多值其實就是返回一個tuple,但寫起來更方便。

總結

定義函式時,需要確定函式名和引數個數;
如果有必要,可以先對引數的資料型別做檢查;
函式體內部可以用return隨時返回函式結果;
函式執行完畢也沒有return語句時,自動return None。
函式可以同時返回多個值,但其實就是一個tuple。
  1. 函式的引數
    定義函式的時候,我們把引數的名字和位置確定下來,函式的介面定義就完成了。對於函式的呼叫者來說,只需要知道如何傳遞正確的引數,以及函式將返回什麼樣的值就夠了,函式內部的複雜邏輯被封裝起來,呼叫者無需瞭解。
    Python的函式定義非常簡單,但靈活度卻非常大。除了正常定義的必選引數外,還可以使用預設引數、可變引數和關鍵字引數,使得函式定義出來的介面,不但能處理複雜的引數,還可以簡化呼叫者的程式碼。
位置引數

fun1(x, y)函式有兩個引數:xy,這兩個引數都是位置引數,呼叫函式時,傳入的兩個值按照位置順序依次賦給引數xy

預設引數

定義函式:求x的n次方

def w_power(x, y = 2):

當我們呼叫w_power(3)時,相當於呼叫w_power(3, 2)

  • 定義預設引數要牢記一點:預設引數必須指向不變物件!
可變引數

要定義出這個函式,我們必須確定輸入的引數。由於引數個數不確定,我們首先想到可以把a,b,c……作為一個list或tuple傳進來,這樣,函式可以定義如下

def calc(numbers):
    sum = 0
    for n in numbers:
        sum = sum + n * n
    return sum

但是呼叫的時候,需要先組裝出一個list或tuple:

>>> calc([1, 2, 3])
14
>>> calc((1, 3, 5, 7))
84

如果利用可變引數,呼叫函式的方式可以簡化成這樣:

>>> calc(1, 2, 3)
14
>>> calc(1, 3, 5, 7)
84

如果利用可變引數,呼叫函式的方式可以簡化成這樣:

>>> calc(1, 2, 3)
14
>>> calc(1, 3, 5, 7)
84

所以,我們把函式的引數改為可變引數:

def calc(*numbers):
    sum = 0
    for n in numbers:
        sum = sum + n * n
    return sum
  • Python允許你在list或tuple前面加一個*號,把list或tuple的元素變成可變引數傳進去:
>>> nums = [1, 2, 3]
>>> calc(*nums)
14

*nums表示把nums這個list的所有元素作為可變引數傳進去。這種寫法相當有用,而且很常見。

  1. 遞迴函式
    在函式內部,可以呼叫其他函式。如果一個函式在內部呼叫自身本身,這個函式就是遞迴函式。
    階乘為例:n! = 1 x 2 x 3 x ... x n,用函式fact(n)表示fact(n) = n! = 1 x 2 x 3 x ... x (n-1) x n = (n-1)! x n = fact(n-1) x n所以,fact(n)可以表示為n x fact(n-1),只有n=1時需要特殊處理

fact(n)用遞迴的方式寫出來就是

def fact(n):
    if n==1:
        return 1
    return n * fact(n - 1)
  • 總結
使用遞迴函式的優點是邏輯簡單清晰,缺點是過深的呼叫會導致棧溢位。
針對尾遞迴優化的語言可以通過尾遞迴防止棧溢位。尾遞迴事實上和迴圈是等價的,沒有迴圈語句的程式語言只能通過尾遞迴實現迴圈。
Python標準的直譯器沒有針對尾遞迴做優化,任何遞迴函式都存在棧溢位的問題。

相關文章