第3天踪旷,Python字符編碼/文件操作/函數(shù)

一、字符編碼

1缚柳、字符編碼發(fā)展史

  • 階段一:現(xiàn)代計算機起源于美國埃脏,最早誕生的也是基于英文考慮的ASCII碼;

    ASCII:一個bytes代表一個字符(英文字符/鍵盤上的所有其他字符)秋忙,1bytes = 8bit彩掐,8個bit位可以產(chǎn)生2**8 = 256種變化,即可以表示256個字符灰追。

  • 階段二:為了滿足中文堵幽,中國人定制了GBK編碼

    GBK:2bytes表示一個字符狗超;
    其他國家也紛紛定制自己的編碼,如日本把日文編到shift_JIS里朴下,韓國把韓文編到Euc-kr里

  • 階段三:各國都有各自的編碼標準努咐,就會不可避免地出現(xiàn)沖突,結果就是在多語言混合的文本中殴胧,顯示出來就會亂碼渗稍。

    • 于是產(chǎn)生了unicode,統(tǒng)一用2bytes代表一個字符团滥,2bytes = 16bit 竿屹,16個bit位可以產(chǎn)生2**16 = 65536種變化,可以表示65536個字符灸姊,然后將全世界各國的文字符號全都包含在內拱燃,因而兼容萬國文字語言。
    • 但對于英文文本來說力惯,這種編碼方式就會多出一倍的存儲空間碗誉,為了解決這個問題,于是又產(chǎn)生了UTF-8父晶,它是對unicode的壓縮優(yōu)化哮缺,英文字符只占用1bytes,中文字符占用3bytes诱建。
  • 注意:需要強調一點蝴蜓;

  • unicode:簡單粗暴,所有字符都占2bytes俺猿,優(yōu)點是字符 ---> 二進制表示 轉換速度快茎匠,缺點是占用空間大
  • utf-8:精準,對不同的字符用不同的長度表示押袍,優(yōu)點是節(jié)省空間诵冒,缺點是:字符 ---> 二進制表示 轉換速度慢,因為每次都需要計算出字符需要多長的bytes才能夠準確表示
  • 內存中使用的編碼是unicode谊惭,用空間換時間(程序都需要加載到內存中才能運行汽馋,因為內存應該是盡可能保證快)
  • 硬盤中或者網(wǎng)絡傳輸用utf-8,網(wǎng)絡 I/O 或磁盤 I/O 遠大于utf-8的轉換延遲圈盔,而且 I/O 應該是飛可能地節(jié)省帶寬豹芯,保證數(shù)據(jù)傳輸?shù)姆€(wěn)定性。

注:所有程序驱敲,最終都要加載到內存铁蹈,程序保存到硬盤,不同的國家用不同的編碼格式众眨,但是到內存中我們?yōu)榱思嫒萑f國(計算機可以運行任何國家的程序原因在于此)握牧,統(tǒng)一且固定使用unicode容诬,這就是為何內存固定用unicode的原因,你可能會說兼容萬國我可以用utf-8啊沿腰,可以览徒,完全可以正常工作,之所以不用肯定是unicode比utf-8更高效八塘(uicode固定用2個字節(jié)編碼习蓬,utf-8則需要計算),但是unicode更浪費空間措嵌,沒錯友雳,這就是用空間換時間的一種做法,而存放到硬盤铅匹,或者網(wǎng)絡傳輸,都需要把unicode轉成utf-8饺藤,因為數(shù)據(jù)的傳輸包斑,追求的是穩(wěn)定,高效涕俗,數(shù)據(jù)量越小數(shù)據(jù)傳輸就越靠譜罗丰,于是都轉成utf-8格式的,而不是unicode再姑。

2萌抵、字符編碼的使用

無論是何種編輯器,要防止文件出現(xiàn)亂碼(請一定注意元镀,存放一段代碼的文件也僅僅只是一個普通文件而已,此處指的是文件沒有執(zhí)行前讨永,我們打開文件時出現(xiàn)的亂碼)

核心法則就是遇革,文件以什么編碼保存的卿闹,就以什么編碼方式打開

Paste_Image.png

2.1 程序的執(zhí)行

python test.py (執(zhí)行程序萝快,一定是先將文件內容加載到內存中)

步驟一:啟動python解釋器
步驟二:python解釋器此時就是一個文本編輯器,負責打開文件test.py揪漩,即從硬盤中讀取test.py的內容到內存中旋恼。

此時氢拥,python解釋器會讀取test.py的第一行內容,# -*-coding:utf-8 -*-囚痴,來決定以什么編碼格式來讀入內存审葬,這一行就是來設定python解釋器這個軟件的編碼使用的編碼格式涣觉,這個編碼可以用sys.getdefaultencoding()查看官册,如果不在python文件指定頭信息#-*-coding:utf-8-*-,那就使用默認的python2中默認使用ascii,python3中默認使用utf-8鸦难。

錯誤:

錯誤

正確:

正確

步驟三:讀取已經(jīng)加載到內存的代碼(unicode編碼的二進制),然后執(zhí)行拴事,執(zhí)行過程中可能會開辟新的內存空間圣蝎,比如 name = Alex

  • 內存的編碼使用unicode捅彻,不代表內存中全都是unicode編碼的二進制步淹;
  • 在程序執(zhí)行之前谤绳,內存中確實都是unicode編碼的二進制弃锐,比如從文件中讀取了一行name = Alex扇住,其中“name”挎塌、“=”榴都、引號嘴高,地位都一樣,都是普通字符而已春瞬,都是 unicode編碼的二進制形式存放在內存中的宽气;
  • 但是程序在執(zhí)行過程中抹竹,會申請內存(與程序代碼所存在的內存是兩個空間),可以存放任意編碼格式的數(shù)據(jù)钞楼,比如name = Alex會被python解釋器識別為字符串询件,會申請內存空間來存放“Hello”宛琅,然后讓“name”指向該內存地址嘿辟,此時新申請的該內存地址保存的也是unicode編碼的“Alex”,如果代碼換成name = "Alex".encode('utf-8'),那么新申請的內存空間里存放的就是utf-8編碼的字符串“Alex”了红伦。

針對python3 如下圖:

Paste_Image.png

瀏覽網(wǎng)頁的時候昙读,服務器會把動態(tài)生成的unicode內容轉換為utf-8再傳輸?shù)綖g覽器:

Paste_Image.png

如果服務器端encode的編碼格式是utf-8,客戶端內存中收到的也是utf-8編碼的二進制只嚣。

2.2册舞、Python2與Python3的區(qū)別

在Python2中有兩種字符串類型:str 和 unicode

str類型:當Python解釋器執(zhí)行到產(chǎn)生字符串的代碼時(例如:s = "林")环础,會申請新的內存地址剩拢,然后將“林” encode成文件開頭指定的編碼格式徐伐,這已經(jīng)是encode之后的結果办素,所以 s 只能decode性穿,所以很重要的一點是:在Python2中需曾,str 就是編碼后的結果bytes,str = bytes商源,所以在Python2中牡彻,unicode字符編碼結果就 str/bytes 庄吼。

#coding:utf-8
s='林' #在執(zhí)行時,'林'會被以conding:utf-8的形式保存到新的內存空間中

print repr(s) #'\xe6\x9e\x97' 三個Bytes,證明確實是utf-8
print type(s) #<type 'str'>

s.decode('utf-8')
# s.encode('utf-8') #報錯霸褒,s為編碼后的結果bytes废菱,所以只能decode

unicode類型:當Python解釋器執(zhí)行到產(chǎn)生字符串的代碼時(例如:s = u"林"),會申請新的內存地址,然后將”林“以unicode的格式存放到新的內存空間衰倦,所以 s 只能encode樊零,不能decode 驻襟。

s=u'林'
print repr(s) #u'\u6797'
print type(s) #<type 'unicode'>


# s.decode('utf-8') #報錯沉衣,s為unicode豌习,所以只能encode
s.encode('utf-8')

打印到終端:對于print需要特別說明的是:當程序執(zhí)行時肥隆,比如name = '蔡' 栋艳,print(name) #這一步是將name指向的那塊新的內存空間(非代碼所在的內存空間)中的內容嘱巾,打印到終端,而終端仍然是運行于內存中的篙螟,所以這打印可以理解為從一塊內存打印到另一塊內存遍略,unicode --> unicode 绪杏。

對于unicode格式的數(shù)據(jù)來說蕾久,無論怎么打印,都不會亂碼障簿。

Python3中的字符串與Python2中的 u"字符串” 一樣站故,都是unicode西篓,所以無論如何打印都不會亂碼岂津。

在pycharm中寸爆,

Paste_Image.png

在windows終端

Paste_Image.png

但是在python2中存在另外一種非unicode的字符串赁豆,此時魔种,print x节预,會按照終端的編碼執(zhí)行x.decode('終端編碼')安拟,變成unicode后糠赦,再打印拙泽,此時終端編碼若與文件開頭指定的編碼不一致顾瞻,亂碼就產(chǎn)生了

在pycharm中(終端編碼為utf-8荷荤,文件編碼為utf-8梅猿,不會亂碼)

Paste_Image.png

在windows終端(終端編碼為gbk袱蚓,文件編碼為utf-8喇潘,亂碼產(chǎn)生)

Paste_Image.png

驗證:
分別驗證在pycharm(默認是utf-8)中和cmd(默認是gbk)下述的打印結果:

#coding:utf-8
s=u'林' #當程序執(zhí)行時颖低,'林'會被以unicode形式保存新的內存空間中


#s指向的是unicode忱屑,因而可以編碼成任意格式莺戒,都不會報encode錯誤
s1=s.encode('utf-8')
s2=s.encode('gbk')
print s1 #打印正常否从铲?#在pycharm打印正名段,cmd中打印會亂碼
print s2 #打印正常否伸辟,正好與上面相反


print repr(s) #u'\u6797'
print repr(s1) #'\xe6\x9e\x97' 編碼一個漢字utf-8用3Bytes
print repr(s2) #'\xc1\xd6' 編碼一個漢字gbk用2Bytes

print type(s) #<type 'unicode'>
print type(s1) #<type 'str'>
print type(s2) #<type 'str'>

2.3信夫、在Python3中也有兩種字符串類型str 和 bytes

str 是 unicode

#coding:utf-8
s='林' #當程序執(zhí)行時忙迁,無需加u姊扔,'林'也會被以unicode形式保存新的內存空間中,

#s可以直接encode成任意編碼格式
s1 = s.encode('utf-8')
s2 = s.encode('gbk')

print(s1)   #b'\xe6\x9e\x97'(utf-8三個字節(jié))
print(s2)   #b'\xc1\xd6' (gbk兩個字節(jié))
print(type(s)) #<class 'str'>

bytes 就是 bytes

#coding:utf-8
s='林' #當程序執(zhí)行時佛南,無需加u嗅回,'林'也會被以unicode形式保存新的內存空間中,

#s可以直接encode成任意編碼格式
s1=s.encode('utf-8')
s2=s.encode('gbk')



print(s) #林
print(s1) #b'\xe6\x9e\x97' 在python3中绵载,是什么就打印什么
print(s2) #b'\xc1\xd6' 同上

print(type(s)) #<class 'str'>
print(type(s1)) #<class 'bytes'>
print(type(s2)) #<class 'bytes'>

二娃豹、文件操作

1懂版、文件處理流程

  • 1.打開文件躯畴,得到文件句柄并賦值給一個變量
  • 2.通過文件句柄對文件進行操作
  • 3.關閉文件

2蓬抄、基本操作

2.1 打開文件并讀取

打開文件時倡鲸,需要指定文件路徑和以何等方式打開文件峭状,打開后优床,即可獲取該文件句柄胆敞,日后通過此文件句柄對該文件操作移层。

f = open('data','r',encoding='utf-8')  #這里的f指向的是一個內存空間地址
file = f.read()  #通過read方法將內存空間中的內容讀取出來并賦值給file
print(f)    #輸出一個內存空間地址观话,及文件名频蛔、打開的模式晦溪、編碼格式三圆。
f.close()  #關閉文件

print(file) #輸出文件內容

輸出:
<_io.TextIOWrapper name='data' mode='r' encoding='utf-8'>

打開文件的模式有:

  • r 嫌术,只讀模式【默認】
  • w度气,只寫模式【不可讀磷籍;不存在則創(chuàng)建院领;存在則清空內容丈氓;】
  • x万俗, 只寫模式【不可讀闰歪;不存在則創(chuàng)建库倘,存在則報錯】
  • a教翩, 追加模式【可讀饱亿; 不存在則創(chuàng)建路捧;存在則只追加內容杰扫;】

"+" 表示可以同時讀寫某個文件:

  • r+, 讀寫【可讀凡伊,可寫】
  • w+系忙,寫讀【可讀银还,可寫】
  • x+ 蛹疯,寫讀【可讀捺弦,可寫】
  • a+, 寫讀【可讀冈欢,可寫】

"b"表示以二進制的方式操作

  • rb 或 r+b
  • wb 或 w+b
  • xb 或 w+b
  • ab 或 a+b

以二進制的方式讀寫一個圖片:

with open('sb.jpg','rb') as f,\
        open('sb_alex.jpg','wb') as f1:
    data=f.read()
    f1.write(data)

注:b 方式打開時凑耻,讀取到的內容是bytes類型香浩,寫入時也需要提供bytes類型邻吭。


2.2 with語句

為了避免打開文件后忘記關閉膏蚓,可以通過管理上下文驮瞧,即:

with open('log','r') as f:
     print(f.read())
  • 以此方式打開论笔,當with代碼塊執(zhí)行完畢時狂魔,內部會自動關閉并釋放文件資源。
  • 在Python2.7后淫痰,with又支持同時對多個文件的上下文進行管理最楷,即:
with open('log1') as obj1, open('log2') as obj2:
    pass

2.3 常用操作

read
讀取文件

with open('a.txt','r',encoding='utf-8') as f:
    print(f.read(4))    #數(shù)字指的是讀的是字符個數(shù)

write
往文件中寫入

with open('access.log','a',encoding='utf-8') as f:
    f.write('\n我是一個好人')

seek/tell
seek是將光標跳轉到指定位置
tell是顯示當前光標所在位置

with open('a.txt','r',encoding='utf-8') as f:
    f.seek(3)       #seek內指定的數(shù)字代表字節(jié),默認情況待错,是以文件起始位置作為開始管嬉,往后移動3個bytes
    print(f.tell()) # 打印當前光標所在的位置

以當前光標所在的位置為開始,移動光標

with open('b.txt','rb') as f:
    f.seek(2,1)    # 1 代表以當前光標所在的位置為開始朗鸠,往后移動2個 bytes

從文件末尾開始,移動光標

with open('b.txt','rb') as f:
    f.seek(-3,2) # 2表示從文件末尾為開始烛占,往前移動3個bytes

truncate
截斷,從指定位置截斷,truncate中的數(shù)字是字節(jié)數(shù)

with open('a.txt','r+',encoding='utf-8') as f:
    f.truncate(3)   #truncate中的數(shù)字是字節(jié)數(shù)胎挎,3個字節(jié)可以保留一個漢字,如果只截斷1個字節(jié)忆家,文件將出現(xiàn)亂碼

模擬Linux命令tail -f access.log
打開文件犹菇,并將光標移動到文件末尾,循環(huán)讀取文件芽卿,這樣每當文件中新增一條日志并保存后揭芍,就會被程序讀取到并打印出來。

# tail -f access.log
import time
with open('access.log','r',encoding='utf-8') as f:
    f.seek(0,2)       # 將光標移動末尾第一位
    while True:
        line=f.readline().strip()
        if line:
            print('新增一行日志',line)
        time.sleep(0.5)

close
關閉文件

f = open('test','w')
f.write('11111\n22222\n')
f.close()

closed
判斷文件是否關閉卸例,關閉返回

f = open('test','w')
f.write('11111\n22222\n')
f.close()
print(f.closed)

readline
一行一行的讀取文件

with open('access.log','r') as f:
    print(f.readline())
    print(f.readline())
    print(f.readline())
 
輸出:
11111

22222

33333  
# 有空行是因print默認會打換行符称杨,在print中加上end=''即可取消空行

readlines
一次讀取全部文件

with open('access.log','r') as f:
    print(f.readlines())
輸出:
['11111\n', '22222\n', '33333\n', '44444\n', '55555\n', '66666\n', '77777\n', '88888']
# 可以看出readlines將文件內容變成一個列表了
with open('access.log','r') as f:
    for i in f.readlines():
        print(i,end='')
輸出:
11111
22222
33333
44444
55555
66666
77777
88888

注:以上兩種方法都會將文件一次加載到內存中,如果文件特別大筷转,比如打開一個20G的文件姑原,而機器內存只有16G,通過這兩種方法無疑會將機器內存撐爆呜舒。

想要一行一行讀取文件內容锭汛,而每次讀取一行內容將覆蓋之前一行,這樣就不會將一個文件中的所有內容全部加載到內存了。想要實現(xiàn)這點唤殴,可以采用下面這種方法:
直接循環(huán)文件句柄

with open('access.log','r') as f:
    for i in f:
        print(i,end='')
輸出:
11111
22222
33333
44444
55555
66666
77777
88888

模擬文件改名

# 模擬文件改名
f1 = open('c','r')
f2 = open('.c.swap','w')

for i in f1:
    # print(i)
    if i.startswith('5'):    # 修改以5開頭的行
        i = '11111\n'
    f2.write(i)
f1.close()
f2.close()
import os
os.remove('c')    # 先刪除般婆,再改名
os.rename('.c.swap','c')

readable
判斷文件是否以只讀模式打開

with open('access.log','a',encoding='utf-8') as f:
    print(f.readable())
輸出:
False
# 因為是以a模式打開,所以返回False

writeable
是否以可寫的模式打開文件朵逝,與readable類似

writelines
將列表寫入文件腺兴,不過請注意,列表中的數(shù)據(jù)類型只能是字符串

with open('access.log','w',encoding='utf-8') as f:
    f.writelines(['111\n','222\n','333\n'])

flush
操作系統(tǒng)在將數(shù)據(jù)寫入硬盤時會等內存中積累到一定量時廉侧,才會數(shù)據(jù)一次性寫入硬盤,這樣可以節(jié)省磁盤 I/O 篓足,flush方法是將內存中的數(shù)據(jù)強制刷到硬盤

with open('access.log','w',encoding='utf-8') as f:
    f.write('111\n222')
    f.flush()

三段誊、函數(shù)

  • Python中函數(shù)的定義:函數(shù)是邏輯結構化和過程化的一種編程方法。
    函數(shù)的特性:

    • 減少重復代碼
    • 使程序變的可擴展
    • 使程序變得易維護
  • 以我自己的理解栈拖,函數(shù)(function)--> 即功能连舍,由一段代碼實現(xiàn)的一個特定的功能,然后在程序中可以反復調用此功能涩哟,減少代碼冗余索赏。這是我簡單的理解,不詳之處還請大家多多指正贴彼。

  • 在python中潜腻,函數(shù)分為兩類:

    • 內置函數(shù),點擊查看
    • 自定義函數(shù)器仗,請繼續(xù)向下看

1. 函數(shù)的定義

# 語法
# def 函數(shù)名(參數(shù)1融涣,參數(shù)2,...):
#     """文檔注釋"""
#     函數(shù)體
#     return 值

函數(shù)的定義主要有如下要點:

  • def:表示函數(shù)的關鍵字
    函數(shù)名:函數(shù)的名稱精钮,后續(xù)代碼可根據(jù)函數(shù)名調用此函數(shù)
    函數(shù)體:函數(shù)中進行一系統(tǒng)的邏輯計算威鹿,如:發(fā)送郵件、計算出[11,22,38,55,2]中的最大數(shù)等轨香。忽你。。
    參數(shù):為函數(shù)體提供數(shù)據(jù)
    返回值:當函數(shù)執(zhí)行完畢后臂容,可以給調用者返回數(shù)據(jù)科雳。

1.1 定義函數(shù)的二種形式

1.1.1 無參函數(shù)

如果函數(shù)的功能僅僅只是執(zhí)行一些操作而已,就定義成無參函數(shù)脓杉,無參函數(shù)通常都沒有返回值

def print_star():
    print('#'*6)

print_star()   # 調用函數(shù)
1.1.2 有參函數(shù)

函數(shù)的功能的執(zhí)行依賴于外部傳入的參數(shù)炸渡,有參函數(shù)通常都有返回值。

def my_max(x,y):
    res=x if x >y else y  # 三元運算
    print(res)
    return res
my_max(5,8)   # 5和8是傳給my_max函數(shù)的參數(shù)

2 函數(shù)調用

按照有參和無參丽已,可以將函數(shù)調用分為兩種蚌堵,如下:

def foo():
    print('from foo')

def bar(name):
    print('bar===>',name)

foo()  # 定義時無參,調用時也無需傳入?yún)?shù)
bar('egon') # 定義時有參,調用時也必須傳入?yún)?shù)

按照函數(shù)的調用形式和出現(xiàn)的位置吼畏,分三種:

  • foo() # 調用函數(shù)的語句形式
  • 調用函數(shù)的表達式形式
def my_max(x,y):
    res=x if x >y else y
    return res
res=my_max(1,2)*10000000 #調用函數(shù)的表達式形式
print(res)
  • 把函數(shù)調用當中另外一個函數(shù)的參數(shù)
def my_max(x,y):
    res=x if x >y else y
    return res
res=my_max(my_max(10,20),30) #把函數(shù)調用當中另外一個函數(shù)的參數(shù)
print(res)
輸出:
30

3. 函數(shù)的返回值

以下三種情況返回值都為None

  • 沒有return
  • return 什么都不寫
  • return None
def foo():
    print('from foo')
    return None
res=foo()
print(res)  # res接收返回值None

多個返回值督赤,將返回成一個元組

def foo():
    print('from foo')
    return 1,[2,3],(4,5),{}
res=foo()
print(res) #打印結果:(1,[2,3],(4,5),{})
a,b,c,d=foo()  # 可以直接用函數(shù)的返回值賦值給變量
print(d)

輸出結果:
from foo
(1, [2, 3], (4, 5), {})
from foo
{}

4. 函數(shù)的參數(shù)

4.1 從大的角度去看,函數(shù)的參數(shù)分兩種:

  • 形參(可以理解為變量名)
  • 實參(賦予變量的值)
形參與實參
#定義階段
def foo(x,y): #x=1,y=2
    print(x)
    print(y)

#調用階段
foo(1,2)

輸出:
1
2

4.2 詳細區(qū)分函數(shù)的參數(shù)

詳細的區(qū)分函數(shù)的參數(shù)分為五種:

  • 位置參數(shù)
  • 關鍵字參數(shù)
  • 默認參數(shù)
  • 可變長參數(shù)( *args泻蚊,**kwargs)
  • 命名關鍵字參數(shù)
4.2.1 位置參數(shù)

實參必須與形參一一對應躲舌,實參的個數(shù)不能多也不能少。

def foo(x,y,z):#位置形參:必須被傳值的參數(shù)
    print(x,y,z)

foo(1,2,3) #位置實參數(shù):與形參一一對應
輸出:
1 2 3
4.2.2 關鍵字參數(shù)

Key = value

def foo(x,y,z):
    print(x,y,z)

foo(z=3,x=1,y=2)
輸出:
1 2 3 

注:位置參數(shù)與關鍵字參數(shù)可以一起使用性雄,但是需要注意以下問題:
1.關鍵字實參必須在位置實參后面
2.不能重復對一個形參傳值

# foo(1,z=3,y=2) #正確
# foo(x=1,2,z=3) #錯誤
# foo(1,x=1,y=2,z=3) #錯誤
4.2.3 默認參數(shù)

在定義函數(shù)時没卸,如果使用了默認參數(shù);那在調用此函數(shù)時秒旋,如果對默認參數(shù)指定了新值约计,則取新值;如果沒有對默認參數(shù)指定值迁筛,則使用默認參數(shù)定義的值煤蚌。

def register(name,age,sex='male'): #形參:默認參數(shù)sex='male'
    print(name,age,sex)
register('alex',age=40)  # 調用時沒有給sex賦值
輸出結果:
alex 40 male

給默認參數(shù)賦新值:

def register(name,age,sex='male'): #形參:默認參數(shù)
    print(name,age,sex)
register('鋼蛋',20,'female')
register('鐵蛋',sex='female',age=19)

# 輸出:
鋼蛋 20 female
鐵蛋 19 female

默認參數(shù)需要注意的問題:

  1. 默認參數(shù)必須跟在非默認參數(shù)后面
```
# def register(sex='male',name,age): #在定義階段就會報錯
#     print(name,age,sex)
```
  1. 默認參數(shù)在定義階段就已經(jīng)賦值了,而且只在定義階段賦值一次
```
a=100000000
def foo(x,y=a):
    print(x,y)
a=0
foo(1)
# 輸出結果:
1 100000000
    ```
注:由結果可以看出细卧,后來給a賦值0后并沒有生效
  1. 默認參數(shù)的值通常定義成不可變類型的數(shù)據(jù)
4.2.4 可變長參數(shù)

第一種:args*
*會把溢出的按位置定義的實參都接收尉桩,以元組的形式賦值給args

def foo(x,y,*args): #*會把溢出的按位置定義的實參都接收,以元組的形式賦值給args
    print(x,y)
    print(args)

foo(1,2,3,4,5)
輸出:
1 2
(3, 4, 5)

利用可變長參數(shù)計算任意長度的和

def add(*args):
    res=0
    for i in args:
        res+=i
    return res
print(add(1,2,3,4))
print(add(1,2))
輸出:
10 
3

*第二種:*kwargs **
**會把溢出的按關鍵字定義的實參都接收贪庙,以字典的形式賦值給kwargs

def foo(x, y, **kwargs):  # **會把溢出的按關鍵字定義的實參都接收蜘犁,以字典的形式賦值給kwargs
    print(x, y)
    print(kwargs)
foo(1,2,a=1,name='egon',age=18)
輸出:
1 2
{'age': 18, 'a': 1, 'name': 'egon'}
4.2.5 命名關鍵字參數(shù)(了解)
def foo(name,age,*,sex='male',height):
    print(name,age)
    print(sex)
    print(height)

foo('egon',17,height='185')
輸出:
egon 17
male
185

*后定義的參數(shù)為命名關鍵字參數(shù),這類參數(shù)止邮,必須被傳值沽瘦,而且必須以關鍵字實參的形式去傳值

4.2.6 各種形式的參數(shù)混合使用
def foo(name,age=10,*args,sex='male',height,**kwargs):
    print(name)
    print(age)
    print(args)
    print(sex)
    print(height)
    print(kwargs)

foo('alex',1,2,3,4,5,sex='female',height='150',a=1,b=2,c=3)

輸出結果:

alex
1       # 雖然age是默認參數(shù),但是這里以位置參數(shù)的方式农尖,將1傳給age為值
(2, 3, 4, 5)
female
150
{'b': 2, 'c': 3, 'a': 1}
4.2.7 其他姿勢

可變長參數(shù)的其他玩法:
*args :

# def foo(*args):
#     print(args)
# foo(1,2,3,4) # 1,2,3,4 <=====>*(1,2,3,4)

#*['A','B','C','D'], 等同于'A','B','C','D'
# foo(*['A','B','C','D']) ===> foo('A','B','C','D')
# foo(['A','B','C','D']) #

# def foo(x,y,z):
#     print(x,y,z)
#
# # foo(*[1,2,3]) #相當于foo(1,2,3)
# foo(*[1,2]) #相當于foo(1,2)

**kwargs :

def foo(**kwargs):
    print(kwargs)

foo(**{'y': 2, 'x': 1,'a':1}) #相當于foo(a=1,y=2,x=1)
輸出:
{'y': 2, 'x': 1, 'a': 1}

*args 與 *kwargs*混合使用:

def wrapper(*args,**kwargs):
    print(args)
    print(kwargs)

wrapper(1,2,3,a=1,b=2)
輸出:
(1, 2, 3)
{'b': 2, 'a': 1}

嵌套:

def foo(x,y,z):
    print('from foo',x,y,z)
def wrapper(*args,**kwargs):
    print(args) #args=(1,2,3)
    print(kwargs) #kwargs={'a':1,'b':2}
    foo(*args,**kwargs) #foo(*(1,2,3),**{'a':1,'b':2}) #foo(1,2,3,b=2,a=1)
# wrapper(1,2,3,a=1,b=2)
wrapper(1,z=2,y=3)

# 輸出:
(1,)
{'y': 3, 'z': 2}
from foo 1 3 2

注:函數(shù)定義階段到底干了什么事情:只檢測函數(shù)體的語法析恋,并不會執(zhí)行

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市盛卡,隨后出現(xiàn)的幾起案子助隧,更是在濱河造成了極大的恐慌,老刑警劉巖滑沧,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件并村,死亡現(xiàn)場離奇詭異,居然都是意外死亡滓技,警方通過查閱死者的電腦和手機哩牍,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來令漂,“玉大人膝昆,你說我怎么就攤上這事丸边。” “怎么了荚孵?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵妹窖,是天一觀的道長。 經(jīng)常有香客問我收叶,道長骄呼,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任判没,我火速辦了婚禮蜓萄,結果婚禮上,老公的妹妹穿的比我還像新娘澄峰。我一直安慰自己嫉沽,他們只是感情好,可當我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布摊阀。 她就那樣靜靜地躺著,像睡著了一般踪蹬。 火紅的嫁衣襯著肌膚如雪胞此。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天跃捣,我揣著相機與錄音漱牵,去河邊找鬼。 笑死疚漆,一個胖子當著我的面吹牛酣胀,可吹牛的內容都是我干的。 我是一名探鬼主播娶聘,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼闻镶,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了丸升?” 一聲冷哼從身側響起铆农,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎狡耻,沒想到半個月后墩剖,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡夷狰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年岭皂,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片沼头。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡爷绘,死狀恐怖书劝,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情揉阎,我是刑警寧澤庄撮,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站毙籽,受9級特大地震影響洞斯,放射性物質發(fā)生泄漏。R本人自食惡果不足惜坑赡,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一烙如、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧毅否,春花似錦亚铁、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至捆探,卻和暖如春然爆,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背黍图。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工曾雕, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人助被。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓剖张,卻偏偏與公主長得像,于是被迫代替她去往敵國和親揩环。 傳聞我的和親對象是個殘疾皇子搔弄,可洞房花燭夜當晚...
    茶點故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內容

  • 字符集和編碼簡介 在編程中常常可以見到各種字符集和編碼丰滑,包括ASCII,MBCS,Unicode等字符集肯污。確切的說...
    蘭山小亭閱讀 8,494評論 0 13
  • http://python.jobbole.com/85231/ 關于專業(yè)技能寫完項目接著寫寫一名3年工作經(jīng)驗的J...
    燕京博士閱讀 7,579評論 1 118
  • 編碼問題一直困擾著開發(fā)人員,尤其在 Java 中更加明顯吨枉,因為 Java 是跨平臺語言蹦渣,不同平臺之間編碼之間的切換...
    x360閱讀 2,480評論 1 20
  • 炫麗多姿物欲橫流, 浮華一片人心躁動貌亭, 追求夢想破碎現(xiàn)實柬唯, 來來去去疲于歸路, 日復一日年復一年圃庭。 在人生旅途中走...
    夏天free閱讀 211評論 0 0
  • 當我拋下一切想與你浪跡天涯锄奢,你卻離我而去獨付榮華
    淺七柒閱讀 97評論 0 1