定義函數(shù)
def my_abs(x):#求絕對值的my_abs函數(shù)
if x >= 0:
return x
else:
return –x
def nop():#空函數(shù)
pass#占位符
參數(shù)檢查
>>> my_abs(1, 2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: my_abs() takes exactly 1argument (2 given)#參數(shù)個數(shù)不對
>>> my_abs('A')#參數(shù)類型不對,無法檢查
'A'
>>> abs('A')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: bad Operand type for abs():'str'
>>> my_abs('A')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in my_abs
TypeError: bad operand type#錯誤的參數(shù)類型
返回多個值
Python的函數(shù)返回多值其實就是返回一個tuple
import math
def move(x, y, step, angle=0):
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
函數(shù)的參數(shù)
def power(x):#計算x2的函數(shù)
return x * x
>>> power(5)
25
def power(x, n):#計算xn
s = 1
while n > 0:
n = n - 1
s = s * x
return s
def power(x, n=2): #第二個參數(shù)n的默認(rèn)值設(shè)定為2
s= 1
while n > 0:
n = n - 1
s = s * x
return s
默認(rèn)參數(shù)降低了函數(shù)調(diào)用的難度,而一旦需要更復(fù)雜的調(diào)用時,又可以傳遞更多的參數(shù)來實現(xiàn)。無論是簡單調(diào)用還是復(fù)雜調(diào)用,函數(shù)只需要定義一個。
def enroll(name, gender, age=6,city='Beijing'):
print 'name:', name
print 'gender:', gender
print 'age:', age
print 'city:', city
enroll('Bob', 'M', 7)# 與默認(rèn)參數(shù)不符的學(xué)生才需要提供額外的信息
enroll('Adam', 'M', city='Tianjin')
有多個默認(rèn)參數(shù)時,調(diào)用的時候,既可以按順序提供默認(rèn)參數(shù),比如調(diào)用enroll('Bob', 'M', 7),意思是,除了name,gender這兩個參數(shù)外,最后1個參數(shù)應(yīng)用在參數(shù)age上,city參數(shù)由于沒有提供,仍然使用默認(rèn)值。
默認(rèn)參數(shù)的誤區(qū)
def add_end(L=[]):#傳入一個list
L.append('END')#添加一個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()
['END', 'END']
>>> add_end()
['END', 'END', 'END']
Python函數(shù)在定義的時候,默認(rèn)參數(shù)L的值就被計算出來了,即[],因為默認(rèn)參數(shù)L也是一個變量,它指向?qū)ο骩],每次調(diào)用該函數(shù),如果改變了L的內(nèi)容,則下次調(diào)用時,默認(rèn)參數(shù)的內(nèi)容就變了,不再是函數(shù)定義時的[]了。所以,定義默認(rèn)參數(shù)要牢記一點:默認(rèn)參數(shù)必須指向不變對象!要修改上面的例子,我們可以用None這個不變對象來實現(xiàn):
def add_end(L=None):
if L is None:
L = []
L.append('END')
return L
可變參數(shù)
def calc(numbers):#計算a2 + b2 +c2 + ……
sum = 0
for n in numbers:
sum = sum + n * n
return sum#調(diào)用時,要先組裝list或tuple
>>> calc([1, 2, 3])
14
def calc(*numbers):#函數(shù)的參數(shù)改為可變參數(shù)
sum = 0
for n in numbers:
sum = sum + n * n
return sum
>>> calc(1, 2, 3)
14
>>> nums = [1, 2, 3]#已有l(wèi)ist或tuple,調(diào)用可變參數(shù)
>>> calc(*nums)
14
關(guān)鍵字參數(shù)
關(guān)鍵字參數(shù)允許你傳入0個或任意個含參數(shù)名的參數(shù),這些關(guān)鍵字參數(shù)在函數(shù)內(nèi)部自動組裝為一個dict
def person(name, age, **kw):#函數(shù)除必選參數(shù)name和age,還接受關(guān)鍵字參數(shù)kw
print 'name:', name, 'age:', age, 'other:', kw
>>> person('Michael', 30)#調(diào)用函數(shù)時,可以只傳入必選參數(shù)
name: Michael age: 30 other: {}
>>> person('Bob', 35,city='Beijing')#可傳入任意個數(shù)的關(guān)鍵字參數(shù)
name: Bob age: 35 other: {'city':'Beijing'}
>>> kw = {'city': 'Beijing','job': 'Engineer'}#組裝出一個dict
>>> person('Jack', 24, **kw)#把dict轉(zhuǎn)換為關(guān)鍵字參數(shù)傳進去
name: Jack age: 24 other: {'city': 'Beijing','job': 'Engineer'}
參數(shù)組合
def func(a, b, c=0, *args, **kw):#必選參數(shù)、默認(rèn)參數(shù)、可變參數(shù)和關(guān)鍵字參數(shù)
print 'a =', a,'b =', b, 'c =', c, 'args =', args, 'kw =', kw
>>> func(1, 2)# 自動按照參數(shù)位置和參數(shù)名把對應(yīng)的參數(shù)傳進去
a = 1 b = 2 c = 0 args = () kw = {}
>>> func(1, 2, c=3)
a = 1 b = 2 c = 3 args = () kw = {}
>>> func(1, 2, 3, 'a', 'b')
a = 1 b = 2 c = 3 args = ('a', 'b') kw = {}
>>> func(1, 2, 3, 'a', 'b', x=99)
a = 1 b = 2 c = 3 args = ('a', 'b') kw ={'x': 99}
>>> args = (1, 2, 3, 4)#tuple和dict,也可以調(diào)用該函數(shù)
>>> kw = {'x': 99}
>>> func(*args, **kw)
a = 1 b = 2 c = 3 args = (4,) kw = {'x':99}
對于任意函數(shù),都可以通過類似func(*args, **kw)的形式調(diào)用它,無論它的參數(shù)是如何定義的。
遞歸函數(shù)
一個函數(shù)在內(nèi)部調(diào)用自身本身,這個函數(shù)就是遞歸函數(shù)。
fact(n) = n! = 1 x 2 x 3 x ... x (n-1) x n= (n-1)! x n = fact(n-1) x n
def fact(n):#fact(n) = n! = fact(n-1) x n
if n==1:
return 1
return n *fact(n - 1)
使用遞歸函數(shù)需要注意防止棧溢出。在計算機中,函數(shù)調(diào)用是通過棧(stack)這種數(shù)據(jù)結(jié)構(gòu)實現(xiàn)的,每當(dāng)進入一個函數(shù)調(diào)用,棧就會加一層棧幀,每當(dāng)函數(shù)返回,棧就會減一層棧幀。由于棧的大小不是無限的,所以,遞歸調(diào)用的次數(shù)過多,會導(dǎo)致棧溢出。如:
>>> fact(1000)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in fact
...
File "<stdin>", line 4, in fact
RuntimeError: maximum recursion depthexceeded
解決遞歸調(diào)用棧溢出的方法是通過尾遞歸優(yōu)化,在函數(shù)返回的時候,調(diào)用自身本身,并且,return語句不能包含表達(dá)式。這樣,編譯器或者解釋器就可以把尾遞歸做優(yōu)化,使遞歸本身無論調(diào)用多少次,都只占用一個棧幀,不會出現(xiàn)棧溢出的情況.即:
def fact(n):
return fact_iter(1, 1, n)
def fact_iter(product, count, max):
if count > max:
return product
return fact_iter(product * count, count + 1, max)
切片
>>> L = ['Michael', 'Sarah', 'Tracy','Bob', 'Jack']
>>> L[0:3]#取前3個元素, 0開始取,直到索引3為止,但不包括索引3
['Michael', 'Sarah', 'Tracy']
>>> L[1:3]
['Sarah', 'Tracy']
>>> L[-2:]# 倒數(shù)切片
['Bob', 'Jack']
>>> L[-2:-1]
['Bob']
>>> L[10:20]#前11-20個數(shù)
>>> L[:10:2]#前10個數(shù),每兩個取一個
>>> L[::5]#所有數(shù),每5個取一個
>>> 'ABCDEFG'[:3]#字符串'xxx'或Unicode字符串u'xxx'也是一種list,每個元素就是一個字符
'ABC'
迭代
如果給定一個list或tuple,我們可以通過for循環(huán)來遍歷這個list或tuple,這種遍歷我們稱為迭代(Iteration)。
>>> d = {'a': 1, 'b': 2, 'c': 3}
>>> for key in d:3只要是可迭代對象,無論有無下標(biāo),都可以迭代,比如dict
... print key
...
a
c
b
>>> for ch in 'ABC':#字符串也是可迭代
... print ch
...
A
B
C
>>> from collections importIterable
>>> isinstance('abc', Iterable) #str是否可迭代
True
>>> isinstance([1,2,3], Iterable)# list是否可迭代
True
>>> isinstance(123, Iterable) # 整數(shù)是否可迭代
False
>>> for x, y in [(1, 1), (2, 4),(3, 9)]:
... print x, y
...
1 1
2 4
3 9
列表生成式ListComprehensions
>>> range(1, 11)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> L = []#生成[1x1, 2x2,3x3, ..., 10x10]
>>> for x in range(1, 11):
... L.append(x * x)
...
>>> L
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
或:
>>> [x * x for x in range(1, 11)]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
>>> [x * x for x in range(1, 11)if x % 2 == 0]#偶數(shù)的平方
>>> d = {'x': 'A', 'y': 'B', 'z':'C' }#dict的iteritems()可以同時迭代key和value
>>> for k, v in d.iteritems():
... print k, '=', v
...
y = B
x = A
z = C
>>> d = {'x': 'A', 'y': 'B', 'z':'C' }#兩個變量來生成list
>>> [k + '=' + v for k, v ind.iteritems()]
['y=B', 'x=A', 'z=C']
生成器
在Python中,這種一邊循環(huán)一邊計算的機制,稱為生成器(Generator)。
>>> L = [x * x for x inrange(10)]#列表生成式的[]改成(),就創(chuàng)建了一個generator
>>> L
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> g = (x * x for x in range(10))
>>> g
<generator object <genexpr> at0x104feab40>
>>> g = (x * x for x inrange(10))#使用for循環(huán)
>>> for n in g:
... print n
def fib(max):#斐波拉契數(shù)列
n, a, b = 0, 0, 1
while n < max:
print b
a, b = b, a + b
n = n + 1
變成generator的函數(shù),在每次調(diào)用next()的時候執(zhí)行,遇到y(tǒng)ield語句返回,再次執(zhí)行時從上次返回的yield語句處繼續(xù)執(zhí)行。例子,定義一個generator,依次返回數(shù)字1,3,5:
>>> def odd():#odd不是普通函數(shù),而是generator
... print 'step 1'
... yield 1
... print 'step 2'
... yield 3
... print 'step 3'
... yield 5
...
>>> o = odd()
>>> o.next()
step 1
1
>>> o.next()
step 2
3
>>> o.next()
step 3
5
>>> o.next()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration

新聞熱點
疑難解答