面向過程:python
直接一行一行寫代碼,遇到重複的內容複製黏貼。app
不利於代碼閱讀函數
代碼沒有複用編碼
面向對象spa
將代碼塊定義爲函數,之後直接調用函數設計
加強了複用性指針
函數的定義方法對象
def 函數名(傳遞參數):ip
函數體內存
return
一、def關鍵字,建立函數
二、函數名
三、():
四、 函數體
五、返回值return
函數必須先定義,以後調用。不能反過來
在執行函數體的過程當中,一旦執行到return,則會當即退出函數,return以後的語句將不會被執行
當定義一個函數後,執行的時候會按照函數體進行執行,而且能夠將函數體的return賦值給變量
def f1():
函數體
return 111
r = f1()
print(r) 會顯示111
可是若是函數體中沒有寫return,python會自動給函數體返回一個默認值就是None
在執行函數的時候使用
try:
函數體
expect:
return False
else:
return True
會判斷函數體的執行結果,若是遇到錯誤就會執行expect裏的內容,不然會執行else,返回值能夠自定義
函數的參數
形式參數 在定義函數時,爲了可以讓調用時能夠輸入參數而設計的參數
實際參數 在調用函數時傳遞的參數
def f1(形式參數)
函數體
r = f1(實際參數)
調用時傳遞的實際參數數量須要與定義時定義的形式參數數量一致,形式參數能夠在同一個函數中定義多個,實際參數的傳遞順序也須要遵循形式參數的順序
集中傳遞參數的方式
函數有四類類參數
一、普通參數,按順序複製
二、默認參數,在定義函數時定義,可是在定義時python要求默認參數必須放在形式參數列表的最後
默認參數 在定義形式參數時能夠定義默認參數
def f2(xx,yy,zz="ok")
其中zz就是默認參數,在調用這個函數的時候,能夠傳遞三個參數也能夠僅傳遞2個參數,當三個參數時zz等於第三個參數,當兩個參數時zz等於默認值"ok"
三、指定參數,在調用函數時指定賦值參數的名字
指定參數必須在調用函數時放到最後,可是不容許重複賦值給同一個參數
指定參數,默認狀況下傳遞參數的順序是要嚴格按照形式參數的順序的,可是經過在調用時指定參數也能夠改變順序
def f3(xx,yy,zz)
f3(yy="11",zz="ok",xx="ye")
def f1(arg1,arg2,arg3)
pass
錯誤的指定參數
f1(arg1 = 2,arg2 =3,4) # 這是不行的
f1(4,arg2=3,arg1 =2) # 這也不行,由於至關於給arg1先賦值4 後賦值2 不容許重複賦值一個參數
f1(4,arg2=3,arg3 = 2) # 正確
四、動態參數 定義形式參數時,按正常模式應該是定義多少個參數就能使用多少個參數,可是可使用*來轉換參數,這樣調用函數時傳遞的實際參數就再也不有數量限制,而傳遞進的多個參數將會顯示爲元組的格式
def f3(*xx):
print(type(xx))
for x in xx:
print("x= %s " % x)
f3("aa","bb",33,44)
結果
<class 'tuple'>
x=aa
x=bb
x=33
x=44
傳遞的多個參數就是一個元組
這種方式有幾種狀況
當傳遞的實際參數是一個列表,那麼傳遞進去後,會將這個列表做爲元組中的第一個元素
def f3(*xx):
print(xx)
print(type(xx))
for x in xx:
print("x= %s " % x)
li=["aa","bb",33,44]
f3(li,"xx")
結果
(['aa', 'bb', 33, 44], 'xx') # li的所有列表做爲參數的第一個元素,xx做爲第二個元素
<class 'tuple'> # 整個參數變爲一個列表
x=['aa', 'bb', 33, 44] # 在執行for循環時值執行了列表被完整的輸出了
x=xx
當傳遞的實際參數自己也加了*,則會將傳遞的列表內的元素拆出轉換爲元組中的元素
def f3(*xx):
print(xx)
print(type(xx))
for x in xx:
print("x=%s"%x)
li=["aa","bb",33,44]
f3(*li,"xx") # 傳遞的列表前有一個星號
結果
('aa', 'bb', 33, 44, 'xx')
<class 'tuple'>
x=aa
x=bb
x=33
x=44
x=xx
當傳遞一個帶星的字符串時,這個字符串裏的每個字母也會被轉化爲元組的元素
def f3(*xx):
print(xx)
print(type(xx))
for x in xx:
print("x=%s"%x)
f3(*"alix")
('a', 'l', 'i', 'x')
<class 'tuple'>
x=a
x=l
x=i
x=x
當傳遞2個*號時,傳遞的參數爲字典類型
def f3(**xx):
print(xx)
print(type(xx))
for x in xx:
print("x= %s " % x)
f3(kk=11,aa=22)
輸出
{'aa': 22, 'kk': 11}
<class 'dict'>
x=aa
x=kk
若是傳遞的參數自身是一個字典,則須要將這個傳遞的參數前加2個星號
def f3(**xx):
print(xx)
print(type(xx))
for x in xx:
print("x=%s"%x)
ss={'aa':22,'kk':11}
f3(**ss)
{'aa': 22, 'kk': 11}
<class 'dict'>
x=aa
x=kk
五、萬能參數(*args,**kwargs):在設置形式參數時,同時制定兩種動態參數,這樣傳入的普通參數會做爲函數中元組的元素,而傳入的字典,則會被**的參數轉換爲字典
def f4(*args,**kwargs):
print(args)
print(kwargs)
f4("aa","bb","cc",kk=123,ss="bbb")
輸出
('aa', 'bb', 'cc')
{'ss': 'bbb', 'kk': 123}
萬能參數會自動識別不一樣類型的動態參數,同時由於字典仍是元組都容許爲空,因此即使傳遞的參數並未按照函數建立的所有順序輸入,仍然能夠建立對應的空元組或空字典
def f4(*args,**kwargs):
print(args)
print(kwargs)
f4(kk=123,ss="bbb") # 只傳遞字典格式
輸出
() # 元組自動被識別爲空
{'kk': 123, 'ss': 'bbb'}
萬能參數在設置形式參數時必須是單個星號在前,2個星號在後,也就是必須是(*args,**kwargs)
針對函數的幾點補充:
一、根據解釋器讀取的順序,當出現重名函數時,最後一次出現的函數將會被執行,由於以前的函數會被以後出現的函數替換加載進內存中。
def f1():
retrun a+b
def f1():
retrun a*b
a = f1(3,4)
最終的結果,相乘的函數被執行。
二、當調用函數時,傳遞的並非一個複製的值,而是合格參數的地址,所以當咱們傳遞了一個列表給函數時,函數對這個列表作的任何操做,都將直接做用於這個列表自己。
def f1(a):
a.append(99)
list = [11,22,33]
f1(list)
print(list)
最終的結果是[11,22,33,99]
三、全局變量,定義在函數外的變量能夠被任何函數引用,所以稱爲全局變量。而定義在函數內的變量只能被本函數引用,所以稱爲局部變量。全局變量應該全大寫,在局部變量中若是想要更新全局變量,須要使用global,可是若是全局變量是字典或列表,則只能夠修改,不能夠從新賦值。
修改字符串,須要用global聲明變量
NAME = "LIUBO"
def f1()
global NAME
NAME = "ZHANGSAN"
f1()
print(NAME)
修改字典
li={"a":11}
def chli():
li["b"]=22
chli()
print(li)
輸出
{'a': 11, 'b': 22}
修改列表
li=[11,22]
def chli():
li.append(22)
chli()
print(li)
輸出
[11, 22, 22]
上面的例子,按正常來講函數中變動的變量僅在函數內有效,可是由於使用了global的方式宣告了這個是全局變量,所以後面對NAME的修改就會應用到全局變量中
三元運算,三目運算
爲真的處理 if 條件 else 爲假的處理
print(1)if 1==2 else print(0)
至關於
if 1 == 2:
print(1)
else:
print(0)
條件爲真 打印1 ,條件爲假打印0
a = 1 if 1 == 1 else 2
條件爲真時 a = 1 ,條件爲假時 a = 2
等價於
if 1 == 1:
a = 1
else:
a = 2
lambda表達式,對於簡單的函數能夠直接使用lambda表達式定義
def f1(a1,a2):
return a1+a2
上面的函數等價於
f1 = lambda a1,a2: a1+a2
def f1(a1,a2=9)
return a1+a2+100
能夠寫爲
f1 = lambda a1,a2=9 : a1+a2+100
f1(9) #由於函數定義了默認參數,所以只須要傳遞一個參數便可
lambda表達式僅能使用一行定義,所以只能定義簡單函數,即函數中不能在加入其它的操做,直接返回
內置函數
abs() 取絕對值
n = abs(-1)
print(n)
輸出爲1
all() 全部爲真,才爲真
在布爾函數中表示False的內容有0,None,「」,[],{}
即空的字符串,列表,字典 元祖都是False
all([11,22,33]) 這樣爲真
all([11,22,「」) 這樣就爲假了
any() 有真就是真
ascii() 自動執行對象的_repr_方法
bin() 接收一個十進制數字轉爲二進制
oct() 接收一個十進制數字轉爲八進制
hex() 接收一個十進制數字轉爲十六進制
bool() 返回真假
bytes()
對於UTF-8編碼一個漢字佔3個字節
GBK編碼一個漢字2個字節
字符串轉換爲字節類型,bytes("要轉換的字符串",encoding="所用的編碼類型")
print(bytes("劉",encoding="utf-8"))
print(bytes("劉",encoding="gbk"))
str()
將字節轉化爲字符串
str(須要轉化的字節,encoding="須要的編碼類型")
print(str(b'\xe5\x88\x98',encoding="utf-8"))
open()
文件操做
一、打開文件
f = open("文件名","操做模式",encoding="編碼")
在打開一個文件時,這個文件裏的內容是二進制的,那麼二進制轉換爲字符串時有一個轉換動做的。
open語句會使用一個默認的編碼方式來讀取文件,更換編碼須要在open中指定
open("text.log","r",encoding="gbk")
在操做模式中有一個b(rb,xb,wb),這樣至關於咱們不須要python幫咱們作編碼轉換,那麼不管是咱們寫仍是讀就都須要使用二進制的數據類型傳遞。
也就是操做模式沒有b則是字符串類型str ,只要有b則是字節型,bytes
f=open("test.log","ab")
f.write(bytes("劉博",encoding="utf-8")) # 寫操做必需要加編碼
f.close()
文件內容(追加)
dial-peer voice 1 voip1
dial-peer voice 1 voip2
dial-peer voice 1 voip3
dial-peer voice 1 voip4
dial-peer voice 1 voip5
dial-peer voice 1 voip6
劉博
+符號表明操做模式可讀可寫,可是方式有所區別
每當open一個文件時,至關於有一個指針出如今文件中,當read()時表明文件內全部的字節都被讀了一次,這時指針也就隨之指向到文件的最後。
能夠經過seek(位置)方法來指定指針的位置。不管是使用b仍是不帶b的方式讀取,seek都是按照字節來制定位置,若是存在漢字,一個漢字在utf8中是3個字節,若是文件只有一個漢字,可是seek(1)這樣指針其實是指到了這個漢字的第一個字節的後面。
在寫入一個內容的時候,python會默認從指針的位置向後替換 原有的字符
f=open("test.log","r+")
f.seek(10) #將指針指向第10個位置
f.write("ssss")
f.close()
結果
dial-peer sssse 1 voip1 #能夠看到從第十個字符開始原來的voice前4個字母被替換爲s了
dial-peer voice 1 voip2
dial-peer voice 1 voip3
dial-peer voice 1 voip4
dial-peer voice 1 voip5
dial-peer voice 1 voip6
劉博
獲取當前指針的位置tell(),tell方法指定的位置永遠是字節
f=open("test.log","r+")
f.seek(10)
a=f.tell()
f.close()
print(a)
打印
10
r+,a+,w+三種都是可讀可寫,可是隻有r+能夠指定指定指針的位置寫入,a+是追加不管怎麼指定,寫入的都只能從最後追加,w+則會清空源文件
所以寫入方式中r+使用的最普遍
操做模式:
r |
只讀 |
w |
只寫(先清空源文件,後寫入) |
x |
python3.0新增:若是文件存在時則報錯,若是不存在建立並寫內容 |
a |
追加 |
r+ |
可讀可寫,最經常使用 |
a+ |
可讀可寫,從最後寫 |
w+ |
可讀可寫,可是先清空源文件 |
二、操做文件
經過源代碼查看功能
read(),若是無參數,則讀所有,若是有參數,打開方式若是有b按字節讀取,無b按字符讀取。
seek(),按字節指定指針位置
tell(),按字節獲取當前指針位置
write(),寫數據,若是打開方式中有b按字節,無b按字符寫
close()
fileno() 文件描述符,即文件的數字表達方式
flush() 強刷,將內容強刷到硬盤上,當咱們打開了一個文件,寫入一個內容,以後作了一個操做暫停在這裏(好比input要求用戶輸入,但用戶沒有輸入)此時文件沒有關閉。默認狀況下這個內容是不會寫到文件裏的。此時能夠經過flush方法在文件關閉前強制將內容寫到文件中。
readable() 判斷是否可讀
seekable() 判斷是否能夠移動指針
readline() 僅讀取一行,實際是執行完這句後,指針指向第二行開始,因此在此執行就會讀取第二行
writeable() 判斷是否可寫
truncate() 會將指針後面的內容所有清空
for循環open以後的文件對象,循環每一行
f = open("test.log","r")
for line in f:
print(line)
三、關閉文件
f.close()
使用with的文件操做
with open("文件名") as f:
pass
上面的with代碼執行完,文件自動關閉,不須要特地寫close
python 2.7以後with支持打開多個文件
with open("1.log","r",encoding="utf-8") as f1, open("2.log","w",encoding="utf-8") as f2:
time = 0
for line in f1:
time += 1
if time <=10:
f2.write(line)
else:
break
上面的代碼使用with,只讀打開1.log,只寫打開2.log,而後將1.log中前10行數據寫入2.log中
上面說打在python中寫入數據是從指針位置開始替換後面的,那麼當咱們要修改文件中不等長的數據(例如將alex替換爲st)就會破壞原有的數據。
而open讀取的數據默認是字符串的類型,所以咱們可使用字符串的操做。str.replace("源字符串","替換字符串")的方式替換。
逐行處理就是
with open("1.log","r",encoding="utf-8") as f1, open("2.log","w",encoding="utf-8") as f2:
for line in f1:
new_str = line.replace("alex","st")
f2.write(new_str)