把學(xué)過(guò)的知識(shí)記錄下來(lái)柜与。
1.安裝Python 3.6
目前巧勤,Python有兩個(gè)版本,一個(gè)是2.x版弄匕,一個(gè)是3.x版颅悉,這兩個(gè)版本是不兼容的。自行百度安裝3.x迁匠。
2.Python基礎(chǔ)語(yǔ)法
print()會(huì)依次打印每個(gè)字符串剩瓶,遇到逗號(hào)“,”會(huì)輸出一個(gè)空格.
Python的語(yǔ)法比較簡(jiǎn)單,采用縮進(jìn)方式城丧,如下
# 這個(gè)是注釋
a = 100
if a >= 0:
print(a)
else:
print(-a)
以#開(kāi)頭的語(yǔ)句是注釋延曙,注釋是給人看的,可以是任意內(nèi)容亡哄,解釋器會(huì)忽略掉注釋枝缔。其他每一行都是一個(gè)語(yǔ)句,當(dāng)語(yǔ)句以冒號(hào):結(jié)尾時(shí)蚊惯,縮進(jìn)的語(yǔ)句視為代碼塊愿卸。按照約定俗成的管理,應(yīng)該始終堅(jiān)持使用4個(gè)空格的縮進(jìn)截型。Python程序是大小寫(xiě)敏感的趴荸,Tab和4個(gè)空格不一樣哦。
2.1 數(shù)據(jù)類型
整數(shù) Python可以處理任意大小的整數(shù)宦焦,當(dāng)然包括負(fù)整數(shù)
浮點(diǎn)數(shù) 科學(xué)計(jì)數(shù)法表示发钝,把10用e替代,1.23x109就是1.23e9赶诊,或者12.3e8笼平,0.000012可以寫(xiě)成1.2e-5,等等舔痪。
整數(shù)和浮點(diǎn)數(shù)在計(jì)算機(jī)內(nèi)部存儲(chǔ)的方式是不同的寓调,整數(shù)運(yùn)算永遠(yuǎn)是精確的(除法難道也是精確的?是的3搿)夺英,而浮點(diǎn)數(shù)運(yùn)算則可能會(huì)有四舍五入的誤差。
字符串 字符串是以單引號(hào)'或雙引號(hào)"括起來(lái)的任意文本
'I\'m \"OK\"!' #轉(zhuǎn)義字符\來(lái)標(biāo)識(shí) I'm "OK"!
Python還允許用r''表示''內(nèi)部的字符串默認(rèn)不轉(zhuǎn)義
Python允許用'''...'''的格式表示多行內(nèi)容
布爾值 在Python中滋捶,可以直接用True痛悯、False表示布爾值(請(qǐng)注意大小寫(xiě))布爾值可以用and、or和not運(yùn)算重窟。
空值 空值是Python里一個(gè)特殊的值载萌,用None表示。None不能理解為0,因?yàn)?是有意義的扭仁,而None是一個(gè)特殊的空值垮衷。
變量 理解變量在計(jì)算機(jī)內(nèi)存中的表示也非常重要。當(dāng)我們寫(xiě):a = 'ABC'
時(shí)乖坠,Python解釋器干了兩件事情:
- 在內(nèi)存中創(chuàng)建了一個(gè)'ABC'的字符串搀突;
- 在內(nèi)存中創(chuàng)建了一個(gè)名為a的變量,并把它指向'ABC'熊泵。
常量 在Python中仰迁,通常用全部大寫(xiě)的變量名表示常量:
#在Python中,有兩種除法顽分,一種除法是/:
print(10 / 3) #3.3333333333333335
#/除法計(jì)算結(jié)果是浮點(diǎn)數(shù)徐许,即使是兩個(gè)整數(shù)恰好整除,結(jié)果也是浮點(diǎn)數(shù)
print(9 / 3)
#還有一種除法是//怯邪,稱為地板除绊寻,兩個(gè)整數(shù)的除法仍然是整數(shù):
print(10 // 3) #整數(shù)的地板除//永遠(yuǎn)是整數(shù) //除法只取結(jié)果的整數(shù)部分
print(10 % 3) #得到兩個(gè)整數(shù)相除的余數(shù)
#無(wú)論整數(shù)做//除法還是取余數(shù),結(jié)果永遠(yuǎn)是整數(shù)悬秉,所以澄步,整數(shù)運(yùn)算結(jié)果永遠(yuǎn)是精確的。
2.2字符串和編碼
字符編碼 字符串比較特殊的是還有一個(gè)編碼問(wèn)題
因?yàn)橛?jì)算機(jī)只能處理數(shù)字和泌,如果要處理文本村缸,就必須先把文本轉(zhuǎn)換為數(shù)字才能處理。
在最新的Python 3版本中武氓,字符串是以Unicode編碼的梯皿,也就是說(shuō),Python的字符串支持多語(yǔ)言
#對(duì)于單個(gè)字符的編碼
print(ord('A')) #獲取字符的整數(shù)表示
print(chr(65)) #把編碼轉(zhuǎn)換為對(duì)應(yīng)的字符
x = b'ABC' #Python對(duì)bytes類型的數(shù)據(jù)用帶b前綴的單引號(hào)或雙引號(hào)表示
#要注意區(qū)分'ABC'和b'ABC'县恕,前者是str东羹,后者雖然內(nèi)容顯示得和前者一樣,但bytes的每個(gè)字符都只占用一個(gè)字節(jié)
#以Unicode表示的str通過(guò)encode()方法可以編碼為指定的bytes
print('ABC'.encode('ascii')) #純英文的str可以用ASCII編碼為bytes
print('中文'.encode('utf-8')) #含有中文的str可以用UTF-8編碼為bytes
#print('中文'.encode('ascii')) #中文的str無(wú)法用ASCII編碼忠烛,因?yàn)橹形木幋a的范圍超過(guò)了ASCII編碼的范圍
#在bytes中属提,無(wú)法顯示為ASCII字符的字節(jié),用\x##顯示美尸。
#把bytes變?yōu)閟tr冤议,就需要用decode()方法:
print(b'ABC'.decode('ascii'))
print(b'\xe4\xb8\xad\xe6\x96\x87'.decode('utf-8')) #中文
#如果bytes中包含無(wú)法解碼的字節(jié),decode()方法會(huì)報(bào)錯(cuò)
#如果bytes中只有一小部分無(wú)效的字節(jié)师坎,可以傳入errors='ignore'忽略錯(cuò)誤的字節(jié)
print(b'\xe4\xb8\xad\xff'.decode('utf-8', errors='ignore'))#中
print(len(b'ABC')) #len()函數(shù)計(jì)算的是str的字符數(shù)恕酸,如果換成bytes,len()函數(shù)就計(jì)算字節(jié)數(shù)
print(len('中文'.encode('utf-8')))
由于Python源代碼也是一個(gè)文本文件胯陋,所以蕊温,當(dāng)你的源代碼中包含中文的時(shí)候袱箱,在保存源代碼時(shí),就需要?jiǎng)?wù)必指定保存為UTF-8編碼寿弱。
當(dāng)Python解釋器讀取源代碼時(shí)犯眠,為了讓它按UTF-8編碼讀取,我們通常在文件開(kāi)頭寫(xiě)上這兩行:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
第一行注釋是為了告訴Linux/OS X系統(tǒng)症革,這是一個(gè)Python可執(zhí)行程序,Windows系統(tǒng)會(huì)忽略這個(gè)注釋鸯旁;
第二行注釋是為了告訴Python解釋器噪矛,按照UTF-8編碼讀取源代碼,否則铺罢,你在源代碼中寫(xiě)的中文輸出可能會(huì)有亂碼艇挨。
格式化
在Python中,采用的格式化方式和C語(yǔ)言是一致的韭赘,用%實(shí)現(xiàn)缩滨,舉例如下
#%運(yùn)算符就是用來(lái)格式化字符串的
#%s表示用字符串替換,%d表示用整數(shù)替換,%x表示用16進(jìn)制整數(shù)替換,%f表示用浮點(diǎn)數(shù)替換
#有幾個(gè)%?占位符,后面就跟幾個(gè)變量或者值泉瞻,順序要對(duì)應(yīng)好,如果只有一個(gè)%?脉漏,括號(hào)可以省略。
print('Hello, %s' % 'world')
print('Hi, %s, you have $%d.' % ('Michael', 1000000))
#%s永遠(yuǎn)起作用袖牙,它會(huì)把任何數(shù)據(jù)類型轉(zhuǎn)換為字符串
#用%%來(lái)表示一個(gè)普通%
format() 它會(huì)用傳入的參數(shù)依次替換字符串內(nèi)的占位符{0}侧巨、{1}……,
>>> 'Hello, {0}, 成績(jī)提升了 {1:.1f}%'.format('小明', 17.125)
'Hello, 小明, 成績(jī)提升了 17.1%'
2.3使用list和tuple
list列表
# Python內(nèi)置的一種數(shù)據(jù)類型是列表:list 是一種有序的集合鞭达,可以隨時(shí)添加和刪除其中的元素, 類似js數(shù)組
classmates = ['Michael', 123,['asp', 'php'], True] #用len()函數(shù)可以獲得list元素的個(gè)數(shù)
#要確保索引不要越界司忱,記得最后一個(gè)元素的索引是len(classmates) - 1
print(classmates[-2])#還可以用-1做索引,直接獲取最后一個(gè)元素 以此類推
classmates.append('Adam')#往list中追加元素到末尾
classmates.insert(1, 'Jack') #把元素插入到指定的位置
classmates.pop() #刪除list末尾的元素
classmates.pop(1) #刪除指定位置的元素畴蹭,用pop(i)方法坦仍,其中i是索引位置
classmates[1] = 'Sarah' #把某個(gè)元素替換成別的元素,可以直接賦值給對(duì)應(yīng)的索引位置
#如果一個(gè)list中一個(gè)元素也沒(méi)有叨襟,就是一個(gè)空的list繁扎,它的長(zhǎng)度為0
tuple 元組 tuple和list非常類似,但是tuple一旦初始化就不能修改.
classmates = ('Michael', 'Bob', 'Tracy')
#現(xiàn)在芹啥,classmates這個(gè)tuple不能變了锻离,它也沒(méi)有append(),insert()這樣的方法墓怀。
#其他獲取元素的方法和list是一樣的汽纠,你可以正常地使用classmates[0],classmates[-1]傀履,但不能賦值成另外的元素虱朵。
#不可變的tuple有什么意義莉炉?因?yàn)閠uple不可變,所以代碼更安全碴犬。如果可能絮宁,能用tuple代替list就盡量用tuple。
#tuple的陷阱:當(dāng)你定義一個(gè)tuple時(shí)服协,在定義的時(shí)候绍昂,tuple的元素就必須被確定下來(lái),比如:
t=(1, 2)
#如果要定義一個(gè)空的tuple偿荷,可以寫(xiě)成()
t = ()
#要定義一個(gè)只有1個(gè)元素的tuple窘游,必須加一個(gè)逗號(hào),來(lái)消除歧義:
t = (1,)
print(t)
#Python在顯示只有1個(gè)元素的tuple時(shí),也會(huì)加一個(gè)逗號(hào),以免你誤解成數(shù)學(xué)計(jì)算意義上的括號(hào)跳纳。
2.4條件判斷
#if語(yǔ)句的完整形式就是:
if <條件判斷1>:
<執(zhí)行1>
elif <條件判斷2>:
<執(zhí)行2>
elif <條件判斷3>:
<執(zhí)行3>
else:
<執(zhí)行4>
#if語(yǔ)句執(zhí)行有個(gè)特點(diǎn)忍饰,它是從上往下判斷,如果在某個(gè)判斷上是True寺庄,把該判斷對(duì)應(yīng)的語(yǔ)句執(zhí)行后艾蓝,就忽略掉剩下的elif和else
age = 3
if age >= 18:#注意不要少寫(xiě)了冒號(hào):
print('adult')
elif age >= 6:
print('teenager')
else:
print('kid')
2.5循環(huán)
#Python的循環(huán)有兩種,一種是for...in循環(huán)斗塘,依次把list或tuple中的每個(gè)元素迭代出來(lái)
names = ['Michael', 'Bob', 'Tracy']
for name in names:
print(name)
#執(zhí)行這段代碼赢织,會(huì)依次打印names的每一個(gè)元素:
sum = 0
for x in range(101):#range(101)就可以生成0-100的整數(shù)序列
sum = sum + x
print(sum)
#第二種循環(huán)是while循環(huán),只要條件滿足逛拱,就不斷循環(huán)敌厘,條件不滿足時(shí)退出循環(huán)
sum = 0
n = 99
while n > 0:
sum = sum + n
n = n - 2
if n > 10: # 當(dāng)n = 11時(shí),條件滿足朽合,執(zhí)行break語(yǔ)句
break # break語(yǔ)句會(huì)結(jié)束當(dāng)前循環(huán)
print(n)
#在循環(huán)過(guò)程中俱两,也可以通過(guò)continue語(yǔ)句,跳過(guò)當(dāng)前的這次循環(huán)曹步,直接開(kāi)始下一次循環(huán)宪彩。
if n % 2 == 0: # 如果n是偶數(shù),執(zhí)行continue語(yǔ)句
continue # continue語(yǔ)句會(huì)直接繼續(xù)下一輪循環(huán)讲婚,后續(xù)的print()語(yǔ)句不會(huì)執(zhí)行
print(sum)
2.6使用dict和set
dict字典 Python內(nèi)置了字典:dict的支持尿孔,dict全稱dictionary固耘,在其他語(yǔ)言中也稱為map锨亏,使用鍵-值(key-value)存儲(chǔ),具有極快的查找速度绘闷。
d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}
d['Adam'] = 67 #賦值
d['Adam'] #獲取 如果key不存在物赶,dict就會(huì)報(bào)錯(cuò):
#多次對(duì)一個(gè)key放入value白指,后面的值會(huì)把前面的值沖掉
#要避免key不存在的錯(cuò)誤,有兩種辦法酵紫,一是通過(guò)in判斷key是否存在:
print('Adam' in d) #True/False
print(d.get('Thomas')) #如果key不存在告嘲,返回None
print(d.get('Thomas', -1)) #不存在 返回傳入的默認(rèn)值
#要?jiǎng)h除一個(gè)key错维,用pop(key)方法,對(duì)應(yīng)的value也會(huì)從dict中刪除
d.pop('Thomas')
#請(qǐng)務(wù)必注意橄唬,dict內(nèi)部存放的順序和key放入的順序是沒(méi)有關(guān)系的
和list比較赋焕,dict有以下幾個(gè)特點(diǎn):
查找和插入的速度極快,不會(huì)隨著key的增加而變慢仰楚;
需要占用大量的內(nèi)存隆判,內(nèi)存浪費(fèi)多。
而list相反:
查找和插入的時(shí)間隨著元素的增加而增加缸血;
占用空間小蜜氨,浪費(fèi)內(nèi)存很少。
所以捎泻,dict是用空間來(lái)?yè)Q取時(shí)間的一種方法。
需要牢記的第一條就是dict的key必須是不可變對(duì)象埋哟。
這個(gè)通過(guò)key計(jì)算位置的算法稱為哈希算法(Hash)笆豁。
要保證hash的正確性,作為key的對(duì)象就不能變赤赊。
在Python中闯狱,字符串、整數(shù)等都是不可變的抛计,因此哄孤,可以放心地作為key。而list是可變的吹截,就不能作為key
set set和dict類似瘦陈,也是一組key的集合,但不存儲(chǔ)value波俄。由于key不能重復(fù)晨逝,所以,在set中懦铺,沒(méi)有重復(fù)的key捉貌。
#要?jiǎng)?chuàng)建一個(gè)set,需要提供一個(gè)list作為輸入集合:重復(fù)元素在set中自動(dòng)被過(guò)濾:
s = set([1, 2, 3])
#通過(guò)add(key)方法可以添加元素到set中冬念,可以重復(fù)添加趁窃,但不會(huì)有效果:
s.add(4)
#通過(guò)remove(key)方法可以刪除元素:
s.remove(4)
#set可以看成數(shù)學(xué)意義上的無(wú)序和無(wú)重復(fù)元素的集合,因此急前,兩個(gè)set可以做數(shù)學(xué)意義上的交集醒陆、并集等操作:
s1 = set([1, 2, 3])
s2 = set([2, 3, 4])
print(s1 & s2) #{2, 3}
print(s1 | s2) #{1, 2, 3, 4}
#set和dict的唯一區(qū)別僅在于沒(méi)有存儲(chǔ)對(duì)應(yīng)的value
#所以,對(duì)于不變對(duì)象來(lái)說(shuō)叔汁,調(diào)用對(duì)象自身的任意方法统求,也不會(huì)改變?cè)搶?duì)象自身的內(nèi)容检碗。相反,這些方法會(huì)創(chuàng)建新的對(duì)象并返回
#使用key-value存儲(chǔ)結(jié)構(gòu)的dict在Python中非常有用码邻,選擇不可變對(duì)象作為key很重要折剃,最常用的key是字符串
3.函數(shù)
調(diào)用函數(shù)
# 內(nèi)置函數(shù) http://docs.python.org/3/library/functions.html#abs
print(abs(-2.1)) #求絕對(duì)值的函數(shù)
#調(diào)用函數(shù)的時(shí)候,如果傳入的參數(shù)數(shù)量不對(duì)像屋,會(huì)報(bào)TypeError的錯(cuò)誤
#如果傳入的參數(shù)數(shù)量是對(duì)的怕犁,但參數(shù)類型不能被函數(shù)所接受,也會(huì)報(bào)TypeError的錯(cuò)誤
print(max(2, 3, 1, -5)) #max函數(shù)可以接收任意多個(gè)參數(shù)己莺,并返回最大的那個(gè)
#數(shù)據(jù)類型轉(zhuǎn)換
int('123') #int()函數(shù)可以把其他數(shù)據(jù)類型轉(zhuǎn)換為整數(shù)
float('12.34') #12.34
str(1.23) #'1.23'
bool(1) #True
bool('') # False
print(hex(23)=='0x17') #函數(shù)把一個(gè)整數(shù)轉(zhuǎn)換成十六進(jìn)制表示的字符串
#函數(shù)名其實(shí)就是指向一個(gè)函數(shù)對(duì)象的引用奏甫,完全可以把函數(shù)名賦給一個(gè)變量,相當(dāng)于給這個(gè)函數(shù)起了一個(gè)“別名”
a = abs # 變量a指向abs函數(shù)
a(-1) # 所以也可以通過(guò)a調(diào)用abs函數(shù)
定義函數(shù)
#定義一個(gè)函數(shù)要使用def語(yǔ)句凌受,依次寫(xiě)出函數(shù)名阵子、括號(hào)、括號(hào)中的參數(shù)和冒號(hào):胜蛉,
# 然后挠进,在縮進(jìn)塊中編寫(xiě)函數(shù)體,函數(shù)的返回值用return語(yǔ)句返回誊册。
def my_abs(x):
if x >= 0:
return x
else:
return -x
print(my_abs(-99))
#函數(shù)體內(nèi)部的語(yǔ)句在執(zhí)行時(shí)领突,一旦執(zhí)行到return時(shí),函數(shù)就執(zhí)行完畢
#如果沒(méi)有return語(yǔ)句案怯,函數(shù)執(zhí)行完畢后也會(huì)返回結(jié)果君旦,只是結(jié)果為None。return None可以簡(jiǎn)寫(xiě)為return嘲碱。
#函數(shù)執(zhí)行完畢也沒(méi)有return語(yǔ)句時(shí)金砍,自動(dòng)return None。
# from xxxx import my_abs來(lái)導(dǎo)入my_abs()函數(shù)悍汛,注意 xxxx 是文件名(不含.py擴(kuò)展名 )
#空函數(shù) 如果想定義一個(gè)什么事也不做的空函數(shù)捞魁,可以用pass語(yǔ)句:
def nop():
pass
#pass語(yǔ)句什么都不做,那有什么用离咐?實(shí)際上pass可以用來(lái)作為占位符谱俭,比如現(xiàn)在還沒(méi)想好怎么寫(xiě)函數(shù)的代碼,就可以先放一個(gè)pass宵蛀,讓代碼能運(yùn)行起來(lái)昆著。
#pass還可以用在其他語(yǔ)句里,比如:
if age >= 18:
pass
#缺少了pass术陶,代碼運(yùn)行就會(huì)有語(yǔ)法錯(cuò)誤凑懂。
#讓我們修改一下my_abs的定義,對(duì)參數(shù)類型做檢查梧宫,只允許整數(shù)和浮點(diǎn)數(shù)類型的參數(shù)接谨。
#數(shù)據(jù)類型檢查可以用內(nèi)置函數(shù)isinstance()實(shí)現(xiàn):
def my_abs(x):
if not isinstance(x, (int, float)):
raise TypeError('bad operand type')
if x >= 0:
return x
else:
return -x
#函數(shù)可以返回多個(gè)值嗎摆碉?答案是肯定的。
import math
def move(x, y, step, angle=0):
nx = x + step * math.cos(angle)
ny = y - step * math.sin(angle)
return nx, ny
#然后脓豪,我們就可以同時(shí)獲得返回值:
x, y = move(100, 100, 60, math.pi / 6)
#但其實(shí)這只是一種假象巷帝,Python函數(shù)返回的仍然是單一值:
r = move(100, 100, 60, math.pi / 6)
print(r) #(151.96152422706632, 70.0)
#原來(lái)返回值是一個(gè)tuple!但是扫夜,在語(yǔ)法上楞泼,返回一個(gè)tuple可以省略括號(hào),而多個(gè)變量可以同時(shí)接收一個(gè)tuple笤闯,按位置賦給對(duì)應(yīng)的值堕阔,
# 所以,Python的函數(shù)返回多值其實(shí)就是返回一個(gè)tuple颗味,但寫(xiě)起來(lái)更方便超陆。
函數(shù)的參數(shù)
# Python的函數(shù)定義非常簡(jiǎn)單,除了正常定義的必選參數(shù)外浦马,還可以使用默認(rèn)參數(shù)侥猬、可變參數(shù)和關(guān)鍵字參數(shù),
# 使得函數(shù)定義出來(lái)的接口捐韩,不但能處理復(fù)雜的參數(shù),還可以簡(jiǎn)化調(diào)用者的代碼鹃锈。
def power(x, n=2):#默認(rèn)參數(shù)
s = 1
while n > 0:
n = n - 1
s = s * x
return s
默認(rèn)參數(shù)可以簡(jiǎn)化函數(shù)的調(diào)用荤胁。設(shè)置默認(rèn)參數(shù)時(shí),有幾點(diǎn)要注意:
一是必選參數(shù)在前屎债,默認(rèn)參數(shù)在后仅政,
二是如何設(shè)置默認(rèn)參數(shù)。
當(dāng)函數(shù)有多個(gè)參數(shù)時(shí)盆驹,把變化大的參數(shù)放前面圆丹,變化小的參數(shù)放后面。變化小的參數(shù)就可以作為默認(rèn)參數(shù)躯喇。
使用默認(rèn)參數(shù)有什么好處辫封?最大的好處是能降低調(diào)用函數(shù)的難度。
當(dāng)不按順序提供部分默認(rèn)參數(shù)時(shí)廉丽,需要把參數(shù)名寫(xiě)上倦微。比如調(diào)用enroll('Adam', 'M', city='Tianjin')
#默認(rèn)參數(shù)有個(gè)最大的坑,演示如下:
def add_end(L=[]):
L.append('END')
return L
print(add_end()) # ['END']
print(add_end()) # ['END', 'END']
#很多初學(xué)者很疑惑正压,默認(rèn)參數(shù)是[]欣福,但是函數(shù)似乎每次都“記住了”上次添加了'END'后的list。
#定義默認(rèn)參數(shù)要牢記一點(diǎn):默認(rèn)參數(shù)必須指向不變對(duì)象焦履!
def add_end(L=None):
if L is None:
L = []
L.append('END')
return L
#現(xiàn)在拓劝,無(wú)論調(diào)用多少次雏逾,都不會(huì)有問(wèn)題:
#為什么要設(shè)計(jì)str、None這樣的不變對(duì)象呢郑临?因?yàn)椴蛔儗?duì)象一旦創(chuàng)建栖博,對(duì)象內(nèi)部的數(shù)據(jù)就不能修改。
#此外牧抵,由于對(duì)象不變笛匙,多任務(wù)環(huán)境下同時(shí)讀取對(duì)象不需要加鎖,同時(shí)讀一點(diǎn)問(wèn)題都沒(méi)有犀变。
可變參數(shù) 允許你傳入0個(gè)或任意個(gè)參數(shù)
def calc(*numbers): #可變參數(shù)
sum = 0
for n in numbers:
sum = sum + n * n
return sum
#如果已經(jīng)有一個(gè)list或者tuple妹孙,要調(diào)用一個(gè)可變參數(shù)怎么辦?可以這樣做:
#Python允許你在list或tuple前面加一個(gè)*號(hào)获枝,把list或tuple的元素變成可變參數(shù)傳進(jìn)去
nums = [1, 2, 3]
calc(*nums)
# *nums表示把nums這個(gè)list的所有元素作為可變參數(shù)傳進(jìn)去蠢正。這種寫(xiě)法相當(dāng)有用,而且很常見(jiàn)省店。
關(guān)鍵字參數(shù)
#可變參數(shù)在函數(shù)調(diào)用時(shí)自動(dòng)組裝為一個(gè)tuple嚣崭。而關(guān)鍵字參數(shù)允許你傳入0個(gè)或任意個(gè)含參數(shù)名的參數(shù),
#這些關(guān)鍵字參數(shù)在函數(shù)內(nèi)部自動(dòng)組裝為一個(gè)dict懦傍。請(qǐng)看示例:
def person(name, age, **kw):
print('name:', name, 'age:', age, 'other:', 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'}
#和可變參數(shù)類似雹舀,也可以先組裝出一個(gè)dict,然后粗俱,把該dict轉(zhuǎn)換為關(guān)鍵字參數(shù)傳進(jìn)去
extra = {'city': 'Beijing', 'job': 'Engineer'}
person('Jack', 24, **extra) #name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}
# **extra表示把extra這個(gè)dict的所有key-value用關(guān)鍵字參數(shù)傳入到函數(shù)的**kw參數(shù)说榆,kw將獲得一個(gè)dict,
# 注意kw獲得的dict是extra的一份拷貝寸认,對(duì)kw的改動(dòng)不會(huì)影響到函數(shù)外的extra签财。
命名關(guān)鍵字參數(shù)
#仍以person()函數(shù)為例,我們希望檢查是否有city和job參數(shù):
def person(name, age, **kw):
if 'city' in kw:
# 有city參數(shù)
pass
if 'job' in kw:
# 有job參數(shù)
pass
print('name:', name, 'age:', age, 'other:', kw)
person('Jack', 24, city='Beijing', addr='Chaoyang', zipcode=123456)
#如果要限制關(guān)鍵字參數(shù)的名字偏塞,就可以用命名關(guān)鍵字參數(shù)唱蒸,例如,只接收city和job作為關(guān)鍵字參數(shù)灸叼。
# 這種方式定義的函數(shù)如下:
def person(name, age, *, city, job):
print(name, age, city, job)
#和關(guān)鍵字參數(shù)**kw不同神汹,命名關(guān)鍵字參數(shù)需要一個(gè)特殊分隔符*,*后面的參數(shù)被視為命名關(guān)鍵字參數(shù)怜姿。
person('Jack', 24, city='Beijing', job='Engineer') #Jack 24 Beijing Engineer
#如果函數(shù)定義中已經(jīng)有了一個(gè)可變參數(shù)慎冤,后面跟著的命名關(guān)鍵字參數(shù)就不再需要一個(gè)特殊分隔符*了:
def person(name, age, *args, city, job):
print(name, age, args, city, job)
#命名關(guān)鍵字參數(shù)必須傳入?yún)?shù)名,這和位置參數(shù)不同沧卢。如果沒(méi)有傳入?yún)?shù)名蚁堤,調(diào)用將報(bào)錯(cuò):
def person(name, age, *, city='Beijing', job):
print(name, age, city, job)
#由于命名關(guān)鍵字參數(shù)city具有默認(rèn)值,調(diào)用時(shí),可不傳入city參數(shù):
person('Jack', 24, job='Engineer') #Jack 24 Beijing Engineer
#使用命名關(guān)鍵字參數(shù)時(shí)披诗,要特別注意撬即,如果沒(méi)有可變參數(shù),就必須加一個(gè)*作為特殊分隔符呈队。
#如果缺少*剥槐,Python解釋器將無(wú)法識(shí)別位置參數(shù)和命名關(guān)鍵字參數(shù):
參數(shù)組合
在Python中定義函數(shù),可以用必選參數(shù)宪摧、默認(rèn)參數(shù)粒竖、可變參數(shù)、關(guān)鍵字參數(shù)和命名關(guān)鍵字參數(shù)几于,這5種參數(shù)都可以組合使用蕊苗。
但是請(qǐng)注意,參數(shù)定義的順序必須是:必選參數(shù)沿彭、默認(rèn)參數(shù)朽砰、可變參數(shù)、命名關(guān)鍵字參數(shù)和關(guān)鍵字參數(shù)喉刘。
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)
f1(1, 2) #a = 1 b = 2 c = 0 args = () kw = {}
f1(1, 2, c=3) #a = 1 b = 2 c = 3 args = () kw = {}
f1(1, 2, 3, 'a', 'b') #a = 1 b = 2 c = 3 args = ('a', 'b') kw = {}
f1(1, 2, 3, 'a', 'b', x=99)#a = 1 b = 2 c = 3 args = ('a', 'b') kw = {'x': 99}
f2(1, 2, d=99, ext=None) #a = 1 b = 2 c = 0 d = 99 kw = {'ext': None}
#最神奇的是通過(guò)一個(gè)tuple和dict瞧柔,你也可以調(diào)用上述函數(shù):
args = (1, 2, 3, 4)
kw = {'d': 99, 'x': '#'}
f1(*args, **kw) #a = 1 b = 2 c = 3 args = (4,) kw = {'d': 99, 'x': '#'}
#對(duì)于任意函數(shù),都可以通過(guò)類似func(*args, **kw)的形式調(diào)用它睦裳,無(wú)論它的參數(shù)是如何定義的造锅。
默認(rèn)參數(shù)一定要用不可變對(duì)象,如果是可變對(duì)象廉邑,程序運(yùn)行時(shí)會(huì)有邏輯錯(cuò)誤备绽!
要注意定義可變參數(shù)和關(guān)鍵字參數(shù)的語(yǔ)法:
*args是可變參數(shù),args接收的是一個(gè)tuple鬓催;
**kw是關(guān)鍵字參數(shù),kw接收的是一個(gè)dict恨锚。
可變參數(shù)既可以直接傳入:func(1, 2, 3)宇驾,又可以先組裝list或tuple,再通過(guò)args傳入:func((1, 2, 3))猴伶;
關(guān)鍵字參數(shù)既可以直接傳入:func(a=1, b=2)课舍,又可以先組裝dict,再通過(guò)kw傳入:func({'a': 1, 'b': 2})他挎。
使用args和kw是Python的習(xí)慣寫(xiě)法筝尾,當(dāng)然也可以用其他參數(shù)名,但最好使用習(xí)慣用法办桨。
命名的關(guān)鍵字參數(shù)是為了限制調(diào)用者可以傳入的參數(shù)名筹淫,同時(shí)可以提供默認(rèn)值。
定義命名的關(guān)鍵字參數(shù)在沒(méi)有可變參數(shù)的情況下不要忘了寫(xiě)分隔符呢撞,否則定義的將是位置參數(shù)损姜。
遞歸函數(shù)
在函數(shù)內(nèi)部饰剥,可以調(diào)用其他函數(shù)。如果一個(gè)函數(shù)在內(nèi)部調(diào)用自身本身摧阅,這個(gè)函數(shù)就是遞歸函數(shù)汰蓉。
def fact(n):
if n==1:
return 1
return n * fact(n - 1)
遞歸函數(shù)的優(yōu)點(diǎn)是定義簡(jiǎn)單,邏輯清晰棒卷。理論上顾孽,所有的遞歸函數(shù)都可以寫(xiě)成循環(huán)的方式,但循環(huán)的邏輯不如遞歸清晰比规。