python 函數


調用函數
Python內置了很多有用的函數,我們可以直接調用。

要調用一個函數,需要知道函數的名稱和參數,比如求絕對值的函數 abs,它接收一個參數。

可以直接從Python的官方網站查看文檔:
http://docs.python.org/2/library/functions.html#abs
也可以在交互式命令行通過 help(abs) 查看abs函數的幫助信息。

調用 abs 函數:

>>> abs(100)
100
>>> abs(-20)
20
>>> abs(12.34)
12.34
調用函數的時候,如果傳入的參數數量不對,會報TypeError的錯誤,並且Python會明確地告訴你:abs()有且僅有1個參數,但給出了兩個:

>>> abs(1, 2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: abs() takes exactly one argument (2 given)
如果傳入的參數數量是對的,但參數類型不能被函數所接受,也會報TypeError的錯誤,並且給出錯誤信息:str是錯誤的參數類型:

>>> abs('a')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: bad operand type for abs(): 'str'
而比較函數 cmp(x, y) 就需要兩個參數,如果 x<y,返回 -1,如果 x==y,返回 0,如果 x>y,返回 1>>> cmp(1, 2)
-1
>>> cmp(2, 1)
1
>>> cmp(3, 3)
0
Python內置的常用函數還包括數據類型轉換函數,比如   int()函數可以把其他數據類型轉換為整數:

>>> int('123')
123
>>> int(12.34)
12
str()函數把其他類型轉換成 str:

>>> str(123)
'123'
>>> str(1.23)
'1.23'
任務
sum()函數接受一個list作為參數,並返回list所有元素之和。請計算 1*1 + 2*2 + 3*3 + ... + 100*100。

 

 

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

我們以自定義一個求絕對值的 my_abs 函數為例:

def my_abs(x):
    if x >= 0:
        return x
    else:
        return -x
請注意,函數體內部的語句在執行時,一旦執行到return時,函數就執行完畢,並將結果返回。因此,函數內部通過條件判斷和循環可以實現非常復雜的邏輯。

如果沒有return語句,函數執行完畢后也會返回結果,只是結果為 None。

return None可以簡寫為return。

任務
請定義一個 square_of_sum 函數,它接受一個list,返回list中每個元素平方的和。

def square_of_sum(L):
sum=0;
for i in L:
sum+=i*i
return sum

 
         

print square_of_sum([1, 2, 3, 4, 5])
print square_of_sum([-5, 0, 5, 15, 25])

 

 

 

 

返回多值
函數可以返回多個值嗎?答案是肯定的。

比如在游戲中經常需要從一個點移動到另一個點,給出坐標、位移和角度,就可以計算出新的坐標:

# math包提供了sin()和 cos()函數,我們先用import引用它:

import math
def move(x, y, step, angle):
    nx = x + step * math.cos(angle)
    ny = y - step * math.sin(angle)
    return nx, ny
這樣我們就可以同時獲得返回值:

>>> x, y = move(100, 100, 60, math.pi / 6)
>>> print x, y
151.961524227 70.0
但其實這只是一種假象,Python函數返回的仍然是單一值:

>>> r = move(100, 100, 60, math.pi / 6)
>>> print r
(151.96152422706632, 70.0)
用print打印返回結果,原來返回值是一個tuple!

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

任務
一元二次方程的定義是:ax² + bx + c = 0

請編寫一個函數,返回一元二次方程的兩個解。

注意:Python的math包提供了sqrt()函數用於計算平方根


import math

 
         

def quadratic_equation(a, b, c):
tmp=(b*b)-(4*a*c)
tmp=math.sqrt(tmp)
x1=(-b)+tmp;
x2=(-b)-tmp;
x1=x1/(2*a)
x2=x2/(2*a)
return x1,x2

 
         

print quadratic_equation(2, 3, 0)
print quadratic_equation(1, -6, 5)



 

 

遞歸函數
在函數內部,可以調用其他函數。如果一個函數在內部調用自身本身,這個函數就是遞歸函數。

舉個例子,我們來計算階乘 n! = 1 * 2 * 3 * ... * n,用函數 fact(n)表示,可以看出:

fact(n) = n! = 1 * 2 * 3 * ... * (n-1) * n = (n-1)! * n = fact(n-1) * n
所以,fact(n)可以表示為 n * fact(n-1),只有n=1時需要特殊處理。

於是,fact(n)用遞歸的方式寫出來就是:

def fact(n):
    if n==1:
        return 1
    return n * fact(n - 1)
上面就是一個遞歸函數。可以試試:

>>> fact(1)
1
>>> fact(5)
120
>>> fact(100)
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000L
如果我們計算fact(5),可以根據函數定義看到計算過程如下:

===> fact(5)
===> 5 * fact(4)
===> 5 * (4 * fact(3))
===> 5 * (4 * (3 * fact(2)))
===> 5 * (4 * (3 * (2 * fact(1))))
===> 5 * (4 * (3 * (2 * 1)))
===> 5 * (4 * (3 * 2))
===> 5 * (4 * 6)
===> 5 * 24
===> 120
遞歸函數的優點是定義簡單,邏輯清晰。理論上,所有的遞歸函數都可以寫成循環的方式,但循環的邏輯不如遞歸清晰。

使用遞歸函數需要注意防止棧溢出。在計算機中,函數調用是通過棧(stack)這種數據結構實現的,每當進入一個函數調用,棧就會加一層棧幀,每當函數返回,棧就會減一層棧幀。由於棧的大小不是無限的,所以,遞歸調用的次數過多,會導致棧溢出。可以試試計算 fact(10000)。

任務
漢諾塔 (http://baike.baidu.com/view/191666.htm) 的移動也可以看做是遞歸函數。

我們對柱子編號為a, b, c,將所有圓盤從a移到c可以描述為:

如果a只有一個圓盤,可以直接移動到c;

如果a有N個圓盤,可以看成a有1個圓盤(底盤) + (N-1)個圓盤,首先需要把 (N-1) 個圓盤移動到 b,然后,將 a的最后一個圓盤移動到c,再將b的(N-1)個圓盤移動到c。

請編寫一個函數,給定輸入 n, a, b, c,打印出移動的步驟:

move(n, a, b, c)

例如,輸入 move(2, 'A', 'B', 'C'),打印出:

A --> B
A --> C
B --> C

def move(n, a, b, c):
    if n==1:
        print a,"-->",c
    else:
        move(n-1,a,c,b)
        move(1,a,b,c)
        move(n-1,b,a,c)

move(4, 'A', 'B', 'C')

 

 

定義可變參數
如果想讓一個函數能接受任意個參數,我們就可以定義一個可變參數:

def fn(*args):
    print args
可變參數的名字前面有個 * 號,我們可以傳入0個、1個或多個參數給可變參數:

>>> fn()
()
>>> fn('a')
('a',)
>>> fn('a', 'b')
('a', 'b')
>>> fn('a', 'b', 'c')
('a', 'b', 'c')
可變參數也不是很神秘,Python解釋器會把傳入的一組參數組裝成一個tuple傳遞給可變參數,因此,在函數內部,直接把變量 args 看成一個 tuple 就好了。

定義可變參數的目的也是為了簡化調用。假設我們要計算任意個數的平均值,就可以定義一個可變參數:

def average(*args):
    ...
這樣,在調用的時候,可以這樣寫:

>>> average()
0
>>> average(1, 2)
1.5
>>> average(1, 2, 2, 3, 4)
2.4
任務
請編寫接受可變參數的 average() 函數。

def average(*args):
    if len(args)==0:
        return 0.0
    s=0
    cnt=0
    for i in args:
        cnt+=1
        s+=i
    return (s+0.0)/(cnt+0.0)

print average()
print average(1, 2)
print average(1, 2, 2, 3, 4)

 

 

 

定義默認參數
定義函數的時候,還可以有默認參數。

例如Python自帶的 int() 函數,其實就有兩個參數,我們既可以傳一個參數,又可以傳兩個參數:

>>> int('123')
123
>>> int('123', 8)
83
int()函數的第二個參數是轉換進制,如果不傳,默認是十進制 (base=10),如果傳了,就用傳入的參數。

可見,函數的默認參數的作用是簡化調用,你只需要把必須的參數傳進去。但是在需要的時候,又可以傳入額外的參數來覆蓋默認參數值。

我們來定義一個計算 x 的N次方的函數:

def power(x, n):
    s = 1
    while n > 0:
        n = n - 1
        s = s * x
    return s
假設計算平方的次數最多,我們就可以把 n 的默認值設定為 2def power(x, n=2):
    s = 1
    while n > 0:
        n = n - 1
        s = s * x
    return s
這樣一來,計算平方就不需要傳入兩個參數了:

>>> power(5)
25
由於函數的參數按從左到右的順序匹配,所以默認參數只能定義在必需參數的后面:

# OK:
def fn1(a, b=1, c=2):
    pass
# Error:
def fn2(a=1, b):
    pass
任務
請定義一個 greet() 函數,它包含一個默認參數,如果沒有傳入,打印 'Hello, world.',如果傳入,打印 'Hello, xxx.'



def greet(name='world'):
    print 'hello',',',name,'.'

greet()
greet('Bart')

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM