注意事項:
函數定義語法:
def 函數名([參數列表]):
'''注釋'''
函數體
函數形參不需要聲明類型,也不需要指定函數返回值類型
即使該函數不需要接收任何參數,也必須保留一對空的圓括號
括號後面的冒號必不可少
函數體相對於def關鍵字必須保持一定的空格縮進 Python允許嵌套定義函數
對於絕大多數情況下,在函數內部直接修改形參的值不會影響實參,而是創建一個新變量。例如:
>>> def addOne(a):
print(id(a), ':', a)
a += 1
print(id(a), ':', a)
>>> v = 3
>>> id(v)
1599055008
>>> addOne(v)
1599055008 : 3
1599055040 : 4
>>> v
3
>>> id(v)
1599055008
在有些情況下,可以通過特殊的方式在函數內部修改實參的值。
>>> def modify(v): # 使用下標修改列表元素值
v[0] = v[0]+1
>>> a = [2]
>>> modify(a)
>>> a
[3]
>>> def modify(v, item): # 使用列表的方法為列表增加元素
v.append(item)
>>> a = [2]
>>> modify(a,3)
>>> a
[2, 3]
也就是說,如果傳遞給函數的實參是可變序列,並且在函數內部使用下標或可變序列自身的原地操作方法增加、刪除元素或修改元素時,實參也得到相應的修改。
>>> def modify(d): #修改字典元素值或為字典增加元素
d['age'] = 38
>>> a = {'name':'Dong', 'age':37, 'sex':'Male'}
>>> a
{'age': 37, 'name': 'Dong', 'sex': 'Male'}
>>> modify(a)
>>> a
{'age': 38, 'name': 'Dong', 'sex': 'Male'}
調用帶有默認值參數的函數時,可以不對默認值參數進行賦值,也可以為其賦值,具有很大的靈活性。
>>> def say(message, times=1 ):
print(message*times)
>>> say('hello')
hello
>>> say('hello',3)
hello hello hello
>>> say('hi',7)
hi hi hi hi hi hi hi
下面的函數使用指定分隔符將列表中所有字符串元素連接成一個字符串。
>>> def join(lst, sep=None):
return (sep or ' ').join(lst)
>>> aList = ['a', 'b', 'c']
>>> join(aList)
'a b c'
>>> join(aList, ',')
'a,b,c'
注意:默認值參數必須出現在函數參數列表的最右端,任何一個默認值參數右邊不能有非默認值參數。
默認值參數只在函數定義時被解釋一次 可以使用“函數名.__defaults__”查看所有默認參數的當前值
>>> i = 3
>>> def f(n=i): # 參數n的值僅取決於i的當前值
print(n)
>>> f()
3
>>> i = 5 # 函數定義後修改i的值不影響參數n的默認值
>>> f()
3
>>> f.__defaults__ # 查看函數所有默認值參數的當前值
(3,)
通過關鍵參數,實參順序可以和形參順序不一致,但不影響傳遞結果,避免了用戶需要牢記位置參數順序的麻煩。
>>> def demo(a,b,c=5):
print(a,b,c)
>>> demo(3,7)
3 7 5
>>> demo(a=7,b=3,c=6)
7 3 6
>>> demo(c=8,a=9,b=0)
9 0 8
可變長度參數主要有兩種形式:在參數名前加1個星號*或2個星號**。
*parameter用來接收多個位置實參並將其放在元組中。
**parameter接收多個關鍵參數並存放到字典中。
*parameter的用法
>>> def demo(*p):
print(p)
>>> demo(1,2,3)
(1, 2, 3)
>>> demo(1,2)
(1, 2)
>>> demo(1,2,3,4,5,6,7)
(1, 2, 3, 4, 5, 6, 7)
**parameter的用法
>>> def demo(**p):
for item in p.items():
print(item)
>>> demo(x=1,y=2,z=3)
('x', 1)
('y', 2)
('z', 3)
傳遞參數時,可以通過在實參序列前加一個星號將其解包,然後傳遞給多個單變量形參。
>>> def demo(a, b, c):
print(a+b+c)
>>> seq = [1, 2, 3]
>>> demo(*seq)
6
>>> tup = (1, 2, 3)
>>> demo(*tup)
6
>>> dic = {1:'a', 2:'b', 3:'c'}
>>> demo(*dic)
6
>>> Set = {1, 2, 3}
>>> demo(*Set)
6
>>> demo(*dic.values())
abc
如果函數實參是字典,可以在前面加兩個星號進行解包,等價於關鍵參數。
>>> def demo(a, b, c):
print(a+b+c)
>>> dic = {'a':1, 'b':2, 'c':3}
>>> demo(**dic)
6
>>> demo(a=1, b=2, c=3)
6
>>> demo(*dic.values())
6
return語句用來從一個函數中返回一個值,同時結束函數。
對於以下情況,Python將認為該函數以return None結束,返回空值:
函數沒有return語句;
函數有return語句但是沒有執行到;
函數有return也執行到了,但是沒有返回任何值。
變量起作用的代碼范圍稱為變量的作用域,不同作用域內變量名可以相同,互不影響。
在函數內部定義的普通變量只在函數內部起作用,稱為局部變量。當函數執行結束後,局部變量自動刪除,不再可以使用。
局部變量的引用比全局變量速度快。
全局變量會增加函數之間的隱式耦合。
全局變量可以通過關鍵字global來定義。這分為兩種情況:
一個變量已在函數外定義,如果在函數內需要為這個變量賦值,並要將這個賦值結果反映到函數外,可以在函數內使用global將其聲明為全局變量。
如果一個變量在函數外沒有定義,在函數內部也可以直接將一個變量定義為全局變量,該函數執行後,將增加一個新的全局變量。
注意:
在某個作用域內任意位置只要有為變量賦值的操作,該變量在這個作用域內就是局部變量,除非使用global進行了聲明。
如果局部變量與全局變量具有相同的名字,那麼該局部變量會在自己的作用域內隱藏同名的全局變量。
lambda表達式可以用來聲明匿名函數(也可以定義具名函數),也就是沒有函數名字的臨時使用的小函數,尤其適合需要一個函數作為另一個函數參數的場合。
>>> L = [(lambda x: x**2), #匿名函數
(lambda x: x**3),
(lambda x: x**4)]
>>> print(L[0](2),L[1](2),L[2](2)) #調用lambda表達式
4 8 16
>>> D = {'f1':(lambda:2+3), 'f2':(lambda:2*3), 'f3':(lambda:2**3)}
>>> print(D['f1'](), D['f2'](), D['f3']())
5 6 8
>>> L = [1,2,3,4,5]
>>> print(list(map(lambda x: x+10, L))) #lambda表達式作為函數參數
[11, 12, 13, 14, 15]
>>> L
[1, 2, 3, 4, 5]
>>> import random
>>> x = [[random.randint(1,10) for j in range(5)] for i in range(5)]
#包含5個子列表的列表
#每個子列表中包含5個1到10之間的隨機數
>>> for item in x:
print(item)
[5, 6, 8, 7, 4]
[1, 5, 3, 9, 4]
[9, 6, 10, 7, 6]
[8, 2, 7, 1, 6]
[1, 7, 5, 3, 5]
python sorted()函數的key參數_葬愛家族小阿傑的博客-CSDN博客_python中sorted函數的key是什麼
>>> from random import sample #sample()函數選擇多個不重復的隨機元素
>>> data = [sample(range(100), 10) for i in range(5)]
>>> for row in data:
print(row)
[72, 47, 87, 27, 75, 14, 0, 67, 16, 52]
[28, 93, 74, 15, 52, 77, 87, 50, 79, 43]
[32, 31, 25, 67, 63, 84, 27, 53, 79, 93]
[22, 3, 56, 91, 75, 83, 51, 89, 14, 45]
[90, 46, 29, 56, 72, 38, 88, 69, 50, 11]
>>> for row in sorted(data):
print(row)
[22, 3, 56, 91, 75, 83, 51, 89, 14, 45]
[28, 93, 74, 15, 52, 77, 87, 50, 79, 43]
[32, 31, 25, 67, 63, 84, 27, 53, 79, 93]
[72, 47, 87, 27, 75, 14, 0, 67, 16, 52]
[90, 46, 29, 56, 72, 38, 88, 69, 50, 11]
>>> from functools import reduce
>>> reduce(lambda x,y:x*y, data[0]) #第一行所有數字相乘
0
>>> reduce(lambda x,y:x*y, data[1]) #第二行所有數字相乘
171018396981432000
>>> list(map(lambda row:row[0], data)) #獲取每行第一個元素
[72, 28, 32, 22, 90]
>>> list(map(lambda row:row[data.index(row)], data))
#獲取對角線上的元素
[72, 93, 25, 91, 72]
>>> max(data, key=lambda row:row[-1]) #最後一個元素最大的行
[32, 31, 25, 67, 63, 84, 27, 53, 79, 93]
python中的map函數_菜鳥更要努力呀的博客-CSDN博客_python中的map
內置函數map()可以將一個函數作用到一個或多個序列或迭代器對象上,返回可迭代的map對象。
>>> list(map(str,range(5)))
['0', '1', '2', '3', '4']
>>> def add5(v):
return v+5
>>> list(map(add5,range(10)))
[5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
>>> def add(x, y):return x+y
>>> list(map(add, range(5), range(5)))
[0, 2, 4, 6, 8]
標准庫functools中的reduce()函數可以將一個接受2個參數的函數以迭代的方式從左到右依次作用到一個序列或迭代器對象的所有元素上。
>>> from functools import reduce
>>> seq=[1,2,3,4,5,6,7,8,9]
>>> reduce(lambda x,y:x+y, seq)
45
>>> def add(x, y):
return x + y
>>> reduce(add,range(10))
45
>>> reduce(add,map(str,range(10)))
'0123456789'
內置函數filter將一個函數作用到一個序列上,返回該序列中使得該函數返回值為True的那些元素組成的filter對象。
>>> seq=['foo','x41','?!','***']
>>> def func(x):
return x.isalnum()
>>> list(filter(func,seq))
['foo', 'x41']
>>> seq
['foo', 'x41', '?!', '***']
>>> [x for x in seq if x.isalnum()]
['foo', 'x41']
>>> list(filter(lambda x:x.isalnum(),seq))
['foo', 'x41']
包含yield語句的函數可以用來創建生成器對象,這樣的函數也稱生成器函數。
每次執行到yield語句會返回一個值然後暫停或掛起後面代碼的執行,下次通過生成器對象的__next__()方法、內置函數next()、for循環遍歷生成器對象元素或其他方式顯式“索要”數據時恢復執行。
生成器對象具有惰性求值的特點,適合大數據處理。