1. 程式人生 > 實用技巧 >Python的基本使用2

Python的基本使用2

1、函式

1.1、定義函式

在Python中,定義一個函式要使用def語句,依次寫出函式名、括號、括號中的引數和冒號:,然後,在縮排塊中編寫函式體,函式的返回值用return語句返回。

def my_abs(x):
    if x >= 0:
        return x
    else:
        return -x

在某個檔案中定義了函式後,可以在另一個檔案中用 " from 檔名 import 方法名 " 的方式來匯入某個方法。注意,匯入時檔名不含檔案字尾 .py。

#在FuncTest.py檔案中定義方法:
def my_abs(x):
    if x >= 0:
        
return x else: return -x #在test.py檔案中引用該方法: from FuncTest import my_abs print(my_abs(100))

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

在Python中,函式可以定義返回多個值,並且最終結果也會返回多個值,但實際上只是返回了一個 tuple。

但是,在語法上,返回一個tuple可以省略括號,而多個變數可以同時接收一個tuple,並且會按位置賦給對應的值,所以,也可以視為返回了多個值。

#匯入math包
import math 

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

#可以看做是返回了多個值
x, y = myMove(100, 100, 60, math.pi / 6)
print(x, y)   #151.96152422706632   70.0 

#但實際上是返回了一個 tuple
r = move(100, 100, 60, math.pi / 6)
print(r)   #(151.96152422706632, 70.0)

1.2、空函式

如果想定義一個什麼事也不做的空函式,可以用pass語句:

def nop():
    pass

pass語句什麼都不做,那有什麼用?實際上pass可以用來作為佔位符,比如現在還沒想好怎麼寫函式的程式碼,就可以先放一個pass,讓程式碼能執行起來。

pass還可以用在其他語句裡,比如下面,缺少了pass,程式碼執行就會有語法錯誤。

if age >= 18:
    pass

1.3、函式的預設引數

我們可以給函式定義預設引數,這樣使用者可以不傳那個預設引數。注意,必須得保證必選引數在前,預設引數在後,否則Python的直譯器會報錯。

def power(x, n=2):
    s = 1
    while n > 0:
        n = n - 1
        s = s * x
    return s

可以定義多個預設引數。呼叫有多個預設引數的函式時,可以按順序提供預設引數,比如呼叫enroll('Bob', 'M', 7)。也可以不按順序提供部分預設引數,此時需要把引數名寫上。比如呼叫enroll('Adam', 'M', city='Tianjin')

def enroll(name, gender, age=6, city='Beijing'):
    print('name:', name)
    print('gender:', gender)
    print('age:', age)
    print('city:', city)

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

否則將可能會出現類似以下預設引數隨著使用過程當中會發生變化的問題:

#先定義一個函式,傳入一個list,新增一個END再返回:
def add_end(L=[]):
    L.append('END')
    return L

#當你正常呼叫時,結果沒問題:
add_end([1, 2, 3])    #[1, 2, 3, 'END']
add_end(['x', 'y', 'z'])    #['x', 'y', 'z', 'END']

#當你使用預設引數呼叫時,一開始結果也是對的:
>>> add_end()
['END']
#但是,再次呼叫add_end()時,結果就不對了:
>>> add_end()
['END', 'END']
>>> add_end()
['END', 'END', 'END']

因為 Python 函式在定義的時候,預設引數L的值就被計算出來了,即[],因為預設引數L也是一個變數,它指向物件[],每次呼叫該函式,如果改變了L的內容,則下次呼叫時,預設引數的內容就變了,不再是函式定義時的[]了。

要避免這個問題,我們可以用None這個不變物件來實現:

#這樣定義,無論怎麼呼叫、呼叫多少次,都不會有問題
def add_end(L=None):
    if L is None:
        L = []
    L.append('END')
    return L

1.4、定義可變引數(*引數名)

在Python函式中,還可以定義可變引數。呼叫該函式時,可以傳入任意個引數,包括0個引數:

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

定義可變引數和定義一個 list 或 tuple 引數相比,僅僅在引數前面加了一個*號。在函式內部,引數numbers接收到的就是一個 tuple。

如果需要將 list 或者 tuple 作為引數去呼叫具有可變引數的函式時,我們可以直接用下面的方式。Python允許你在 list 或 tuple 前面加一個*號,把 list 或 tuple 的元素變成可變引數傳進去:

>>> nums = [1, 2, 3]
>>> calc(*nums)    # *nums表示把nums這個list的所有元素作為可變引數傳進去。
14

1.5、定義關鍵字引數(**引數名)

函式中的關鍵字引數允許你額外傳入0個或任意個含引數名的引數,這些引數會在函式內部自動組裝為一個 dict 。

如下,定義了關鍵字引數 kw:

def person(name, age, **kw):
    print('name:', name, 'age:', age, 'other:', kw)

函式person除了必選引數nameage外,還接受關鍵字引數kw。在呼叫該函式時,可以只傳入必選引數,也可以傳入任意個數的關鍵字引數:

#不傳關鍵字引數
>>> person('Michael', 30)
name: Michael age: 30 other: {}

#可以傳入任意個數的關鍵字引數:
>>> person('Bob', 35, city='Beijing')
name: Bob age: 35 other: {'city': 'Beijing'}

>>> person('Adam', 45, gender='M', job='Engineer')
name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'}

把 dict 作為引數傳遞:

>>> extra = {'city': 'Beijing', 'job': 'Engineer'}
>>> person('Jack', 24, **extra)
name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}

**extra表示把extra這個dict的所有key-value用關鍵字引數傳入到函式的**kw引數,kw將獲得一個dict。注意kw獲得的dict是extra的一份深拷貝,對kw的改動不會影響到函式外的extra

1.6、定義命名關鍵字引數(*, 引數名1, 引數名2)

如果要限制關鍵字引數的名字,我們就可以用命名關鍵字引數。和關鍵字引數比如:**kw不同,命名關鍵字引數需要一個特殊分隔符**後面的引數被視為命名關鍵字引數。

例如,只接收cityjob作為關鍵字引數的函式定義如下:

def person(name, age, *, city, job):
    print(name, age, city, job)

在呼叫定義了命名關鍵字引數的函式時,如果要使用命名關鍵字引數則必須傳入引數名,如果沒有傳入引數名,呼叫將可能報錯。因為 Python 會將其認為是普通的引數,而這些普通的引數中的數量可能跟你傳遞的不一致就會導致報錯。

>>> person('Jack', 24, 'Beijing', 'Engineer')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: person() takes 2 positional arguments but 4 were given

如果在函式定義的引數中已經有了一個可變引數,後面跟著的命名關鍵字引數就不再需要一個特殊分隔符*了。但如果沒有可變引數,就必須加一個*作為特殊分隔符。如果缺少*,Python直譯器將無法識別位置引數和命名關鍵字引數。

def person(name, age, *args, city, job):
    print(name, age, args, city, job)

命名關鍵字引數可以有預設值,從而簡化呼叫:

def person(name, age, *, city='Beijing', job):
    print(name, age, city, job)

#由於命名關鍵字引數city具有預設值,呼叫時,可不傳入city引數:
>>> person('Jack', 24, job='Engineer')
Jack 24 Beijing Engineer

1.7、Python中函式的各種引數的順序

在Python中定義函式,可以用必選引數、預設引數、可變引數、關鍵字引數和命名關鍵字引數,這5種引數都可以組合使用。但是請注意,引數定義的順序必須是:必選引數、預設引數、可變引數、命名關鍵字引數和關鍵字引數。

比如定義一個函式,包含上述若干種引數:

def f1(a, b, c=0, *args, **kw):
    print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)

def f2(a, b, c=0, *, d, **kw):
    print('a =', a, 'b =', b, 'c =', c, 'd =', d, 'kw =', kw)