第三週總結

一、基礎概念

1集合:

集合是一個無序的、不重複的數據組,它的作用:

1)、去重複、把一個列表變成集合,就會自動去重

2)、關係測試,測試兩組數據之間的交集、差集、並集等關係

集合的方法:

a、設置集合

>>>list_1 = [1,3,5,6,77,3,12]   #列表1
>>>list_2 = [1,3,88,4,33,77]  #列表2
>>>list_1 = set(list_1)  #通過set方法可以將列表變爲集合
>>>list_1
{1, 3, 5, 6, 12,77}  #集合list_1現在已經去重
>>>list_2 = set(list_2)
>>>list_2
{1, 33, 3, 4, 77,88}
>>>print(list_1,type(list_1))#打印list_1類型,發現爲set類型,證明爲集合

 

b、取交集 intersection(list_1  list_2共有的元素)

>>>list_1.intersection(list_2)    
{1, 3, 77}
>>> print(list_1  & list_2)
{1, 3, 77}
#上述兩種方法均可以取出list_1與list_2的交集

c、取並集union(list_1 與list_2中全部去重元素)

>>>list_1.union(list_2)                 
{1, 33, 3, 4, 5,6, 12, 77, 88}
>>>list_1  | list_2
{1, 33, 3, 4, 5,6, 12, 77, 88}
#上述兩種方法取兩個集合的全部去重元素

d、取差集(差集是一個集合有,但是另一個集合沒有的元素,所以差集可以得到兩種不同的結果)

>>>list_1.difference(list_2) #list_1中存在但是list_2中不存在
{12, 5, 6}
>>>list_2.difference(list_1) ##list_2中存在但是list_1中不存在
{88, 33, 4}
>>> list_1 - list_2
{12, 5, 6}
>>> list_2 - list_1 
{88, 33, 4}

 基本操作:

a、添加(集合操作沒有插入動作,只能添加)

>>> list_1
{1, 3, 5, 6, 12,77}
>>>list_1.add(999)    #添加單項
>>>list_1.add('wang')
>>>list_1
{1, 3, 5, 6, 999,12, 77, 'wang'}
>>>list_1.update(['alex','john','tom'])  #添加多項
>>>list_1
{1, 3, 5, 6, 999,12, 77, 'john', 'tom', 'wang', 'alex'}

b、刪除

>>>list_1
{1, 3, 5, 6, 999,12, 77, 'john', 'tom', 'wang', 'alex'}
>>>list_1.remove(999)  #通過remove方法刪除,刪除後不顯示刪除項,刪除需要明確指定刪除項的內容,因爲集合是無序的,沒有索引的概念
>>>list_1
{1, 3, 5, 6, 12,77, 'john', 'tom', 'wang', 'alex'}
>>>list_1.remove(wang)  #針對字符串需要加引號
Traceback (mostrecent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'wang'isnot defined
>>>list_1.remove('wang')
>>>list_1
{1, 3, 5, 6, 12,77, 'john', 'tom', 'alex'}
>>> list_1.pop()  #pop方法屬於隨機刪除,刪除後顯示刪除的內容
1
>>>list_1.pop()
3
>>>list_1.pop()
5
>>>list_1.pop()
6
>>>list_1.pop()
12
>>>list_1.pop()
77
>>>list_1.pop()
>>>list_1.pop()
'john'
>>>list_1
{'tom', 'alex'}

c、discard刪除

>>>list_1
{'wang', 1, 3, 5, 6, 999, 12, 77, 'john', 'tom', 'alex'}
>>>list_1.discard(999)  
>>>list_1
{'wang', 1, 3, 5, 6, 12, 77, 'john', 'tom', 'alex'}
>>>list_1.discard(888)    #discard與remove的不同之處在於,discard如果是刪除不存在的內容,不會報錯,但是remove會報錯
>>>list_1.remove(999)
Traceback (mostrecent call last):
  File "<stdin>", line 1, in <module>
KeyError: 999

d、長度len

>>>len(list_1)
10
>>>list_1
{'wang', 1, 3, 5, 6, 12, 77, 'john', 'tom', 'alex'}

e、成員判斷(in 和not in)

>>>list_1
{'wang', 1, 3, 5, 6, 12, 77, 'john', 'tom', 'alex'}
>>> 'wang'in list_1
True
>>> 11 in list_1     
False
>>> 11 notin list_1
True

 

 2、文件操作:

1、文件操作包括以下幾種方式:

1)讀模式

>>> data= open('yesterday.txt', 'r')   #open函數默認是讀默認,所以r可以省略,但是爲了規範最好寫清楚已哪種方式打開
>>> print(data)  #當打開這個文件後,print會返回該文件名字,默認與默認編碼等文件本身屬性
<_io.TextIOWrappername='yesterday.txt' mode='r' encoding='UTF-8'>

2)寫模式

>>> data= open('yesterday1.txt', 'w')   #文件已寫模式打開
>>>data.write('1234\n')   #當打開後,可以使用wirite方法進行寫入操作,如果需要每行結束後換行,需要手動添加“\n”  這樣保證在輸入後進行換行操作,當寫入後,會自動提示寫了多少個字符
5
>>> f =data.read()    #由於模式之間不兼容,如果只以寫模式打開文件,進行讀操作會報錯
Traceback (mostrecent call last):
  File "<stdin>", line 1, in <module>
io.UnsupportedOperation:not readable

3)追加模式

>>> data= open('yesterday1.txt', 'a')  #和寫模式不同,已追加模式打開文件,不會覆蓋原文件內容,只會在文件後面進行添加,如果以w模式打開,會將文件原有內容全部清空,重新編寫
>>>
>>>
>>>data.write('wwwyy\n')   #對於寫與追加模式,都可以進行write操作
6
>>> f =data.read()    #追加模式也同樣不能進行讀操作
Traceback (mostrecent call last):
  File "<stdin>", line 1, in <module>
io.UnsupportedOperation:not readable

 

  總結:

文件打開最常用三種模式爲讀、寫、追加。默認爲open函數以讀模式方式工作,在讀模式中可以讀取文件內容,寫與追加模式均可以對文件進行修改,不同的是,讀模式打開文件後,會將原有文件內容清空,添加新內容,而追加模式不會清空原有內容,會在文件最後添加新的需要追加的內容,至於如何在將r、w和a模式進行結合操作,會在修改文件時進行介紹

2、讀模式的相關操作

1)read操作

>>>data= open('yesterday.txt', 'r')

>>>data.read()    #read操作會一次性將文件全部內容讀取到內存中

'往日重現\n\n當我年輕的時候\n聽着收音機\n等待着我最喜愛的歌\n當它播放時我獨自跟唱\n讓我心情愉快起來\n\n就像那些快樂時光\n驚訝消失的無影無蹤\n但當它們回來時\n就像是久沒聯絡的朋友一樣\n這都是我喜歡的歌\n\n每個Sha-la-la-la\n每個Wo-o-wo-o\n記憶依鮮明\n每個shing-a-ling-a-ling\n節奏依然美好\n\n當故事到了那個段落\n他傷了她的心\n讓我流下淚來\n就像從前\n往日重現'

>>>data.read()  # 由於文件指針的存在,當一次性讀取文件到內存後如果不進行指針回退操作前再次讀取,會返回空值,表示該內容上一次已經讀取完畢,本次讀取沒有內容顯示

2)readline操作

>>>data= open('yesterday.txt', 'r')
>>>data.readline()  #與read操作一次性讀取不同,readline操作每次只會讀取一行內容存儲到內存中,readline方法可以針對每行內容進行操作
>>>data.readline()
'往日重現\n'

3)readlines操作

>>>data= open('yesterday.txt', 'r')
>>> data.readlines()#區別於read於readline操作,readlines操作也是一次性讀取,不同的是它會將讀取的內容放入到一個列表中,這樣後續可以操作列表的方式對該文件內容進行需要的操作

4)close操作

>>>data.close() #在r、w、a操作的最後需要將文件關閉,採用close方法進行關閉,這樣纔會將文件修改保存到硬盤中,如果沒有關閉操作,默認情況下都是在內存中進行操作的

5)文件的編碼格式

>>>data= open('yesterday.txt', 'r',encoding='utf-8') #在打開文件時需要跟文件的編碼格式,python3中默認是採用utf-8格式的編碼,所以可以省略
>>> print(data)
<_io.TextIOWrappername='yesterday.txt' mode='r' encoding='utf-8'>

 

3、文件的其他操作

1)encoding:打印文件編碼

>>>data.encoding
'utf-8'

2)  fino()返回文件句柄所在操作系統的編碼  基本不使用操作

3)isatty()該文件是否是一個終端設備,linux系統中可以用來判斷是否是一個tty文件

4)name打印文件名稱

>>>data.name
'yesterday.txt'

5)  seekable() 是否可以移動指針

>>>data.seekable()
True

6)  flush()刷新操作:

如果以寫模式打開文件,寫完後不一定立即寫入磁盤,如果此時突然斷電可能沒有及時寫入進文件,所以可以通過flush方法刷新進磁盤

例子:可以在安裝程序時,打印進度條

importtime,sys
for i in range(50):
    sys.stdout.write('#')
    sys.stdout.flush()  #將#號實時刷新到屏幕上來
    time.sleep(0.1)

7)closed 判斷文件是否關閉

>>>data.closed
False
>>>data.close()
>>>data.closed
True

8)  truncate()如果不寫入任何東西就是清空文件

data.truncate(10)會只保留10個字節,其餘的會刪除,同時truncate自帶文件指針,無論通過seek移到任何位置,truncate都會按照初始位置來刪除與保留

 

4、修改文件:

  修改文件分爲兩種模式:

1、將文件全部讀入內存中,然後修改,該方式典型代表就是vim程序

2、將文件按照行模式讀,然後每行操作完畢後再放入新文件,這種方式節約內存佔用,類似與sed與awk操作

 

對於文件操作,除了典型r/w/a方式外還有其他操作,下面來簡要介紹這幾種更常用操作:

1)r+  讀寫操作,表示又能讀又能寫,這個表示以讀與追加模式開始,如果寫,會將寫的內容放入最後

2)w+寫讀模式,創建新文件,輸入內容,然後讀取文件指針所在位置,在回退,再輸入,會發現插入的內容,仍然在最後而不是通過seek調轉

3)a+追加讀模式,在追加的過程中可以進行讀

5、二進制文件

針對二進制文件有兩種方式,rb與wb,其中兩種情況下使用rb:

1、網絡傳輸,socket傳輸時只能使用二進制格式編碼

2、視頻文件打開,也必須使用二進制格式打開

6、with語句

當with代碼執行完畢後,內部會自動關閉並釋放文件所在內存,同時也可以同時打開多個文件

with open('tes2.txt','w') as f, open('test3.txt','w') as f2:#兩個文件之間用‘,’來分割
    f.write('nnn\n')
    f2.write('mmmm\n')

 

3、字符編碼與轉碼

知識點:

1.在python2默認編碼是ASCII, python3裏默認是unicode

2.unicode 分爲 utf-32(佔4個字節),utf-16(佔兩個字節),utf-8(佔1-4個字節), soutf-16就是現在最常用的unicode版本,不過在文件裏存的還是utf-8,因爲utf8省空間

3.在py3中encode,在轉碼的同時還會把string 變成bytes類型,decode在解碼的同時還會把bytes變回string

在介紹編碼之前先介紹下計算機語言與人類可識別語言轉換:

計算機只能識別二進制編碼,即0和1,在二進制編碼中採用bit(位)來表示,但是這種方式對人類來講是不可讀的,所以初始階段,發明了ASII碼,即採用一個byte(8個bits)方式來表示人類可識別字母,2的8次方-1也就是使用255個ASII碼來表示A-Za-z0-9這些數字與字母,但是對於非英語國家來說,255個字符表示沒法完全表示自己本國語言,對於中國來說,本身採用了gbk gbk2308 gbk2312等編碼方式來進行特定的編碼,但是這種方式到了其他國家由於編碼格式未統一,所以導致本國的程序到其他國家未必會被採用,基於這種情況,標註化組織開發了unicode即萬國碼的方式來代替了原有的各自爲政的局面,unicode要求:最少已2個資金來表示,這樣又引入了新的問題,就是比較浪費資源,所以最後統一使用utf-8編碼方式:英語國家採用ASII編碼,一個字節,歐洲等國家採用兩個字節,而中國這種亞洲國家採用3個字節來表示自己的編碼,至此解決了編碼方式的問題

在說的編碼與解碼,由於類似bgk與utf-8之間沒法直接轉換,都需要經過unicode作爲中轉編碼,所以需要編碼與解碼過程

import sys
print(sys.getdefaultencoding())   #打印得出默認編碼爲utf-8
utf-8
s = '你好'      #在python3中默認編碼爲unicode
s_gbk = s.encode('gbk')  #由於默認編碼爲unicode,所以這裏從unicode到gbk編碼採用的是encode模式,因爲unicode沒有decode過程了,可以直接encode
print(s_gbk)  #這裏輸出爲gbk編碼格式
b'\xc4\xe3\xba\xc3'
s_to_utf8 =s.encode('gbk').decode('gbk').encode('utf-8')  '''從bgk變爲utf-8:需要先把編碼encode爲bgk,然後在解碼decode,解碼是告訴自己爲bgk,這時已經轉換爲unicode了,再從unicode狀態encode成utf-8'''
print(s_to_utf8)
b'\xe4\xbd\xa0\xe5\xa5\xbd'
s_to_unicode =s.encode('gbk').decode('gbk').encode('utf-8').decode('utf-8')  #在上面的基礎上再使用decode模式解碼到unicode
print(s_to_unicode)
你好

 

4、函數

1、編程方式

1)面向對象:類 ,定義用class

2)面向過程:過程,定義用def

3)函數式編程:函數,定義用def

      其中函數式編程,其中沒有任何變量,對於某一輸入一定存在確定的輸出,這種編程語言包括Lisp、relang,這裏對函數式編碼不做過多討論

2、定義函數

def func1():   #通過def方式定義函數
  '''testing'''
  print('func1')
  return 0   #函數可以有返回值
 
a = func1()   #調用該函數

3、定義過程

def func2():  #定義過程與定義函數的區別在於定義過程是沒有返回值的
    '''testing'''
    print('in the func2')

4、調用函數與調用過程,查看返回值

def func1():  
  '''testing'''
  print('func1')
  return 0
 
def func2():
    '''testing'''
    print('in the func2')
 
a = func1()  #調用函數1
b = func2() #調用過程2
 
print(a)
#打印返回值爲0
print(b)
#打印沒有返回值,按照默認來定義:None

 

5、使用函數的好處

1)代碼的重複利用

2)程序容易擴展

3)保持代碼的一致性

6、函數的返回值

def func1():
  '''testing1'''
 
def func2():
    '''testing2'''
    return 1
 
def func3():
    '''testing3'''
    return 1,[1,2,3,4,5,6,7],(1,2,4,3,3,'wang'),{'name':'gavin','age':99}
 
a = func1()
b = func2()
c = func3()
 
print(a)
None
print(b)
1
print(c)
(1, [1, 2, 3, 4,5, 6, 7], (1, 2, 4, 3, 3, 'wang'), {'age': 99, 'name': 'gavin'})

    返回值個數=0,返回None,系統默認返回空

    返回值個數=1,反正object,定義哪個返回值,就返回哪個

    反正值個數>1,返回tuple,當返回值個數大於1時,返回一個元組包含哪些需要返回的數值

 7、形參與實參

def func1(x,y):  #x與y時函數的形參,在沒有調用該函數時,x與y不代表任何變量,不佔用內存
  '''testing1'''
  x = x + y
  return x
 
 
a =func1(10,20)  #10與20是在調用該函數式傳遞給該函數的實參,目的是代替形參傳入函數得到預期的結果
print(a)   #在沒有默認參數的情況下,形參與實參是需要一一對應的,如果調用時不一一對應會導致報錯
30

8、默認參數

def func1(x,y=20):#y有默認參數,但是實際調用時沒有實參對y賦值,y將採用默認參數,需要注意的是,默認參數要放在最後

 

def func1(x,y=20):#y有默認參數,但是實際調用時沒有實參對y賦值,y將採用默認參數,需要注意的是,默認參數要放在最後
  '''testing1'''
  x = x + y
  return x
a = func1(10)
print(a)
30
b = func1(11,21)
print(b)
32

  默認參數特點:

調用函數時,默認參數可有可無,默認參數的用途是1在默認安裝軟件時使用,2在連接數據庫端口號時使用

9、局部變量與全局變量

  局部變量只在函數中生效,而全部變量是在整個程序中都生效的變量,代碼頂層定義的變量,局部變量變成全局變量需要在函數中global這個局部變量,但是千萬不要這麼使用,但是需要注意的是,列表、字典、集合、類都是可以在函數中修改內容的,字符串與整數在局部變量中不能修改

name = 'gavin'
 
def my(name,age):
    name = 'jack'   #局部變量
    age = 23
    return name,age
 
 
a =my(name,44)   #name的局部變量在函數中生效變爲jack,但是函數結束後仍然爲gavin這個全局變量
print(a)   #傳入的44在函數中沒有生效
('jack', 23)
print(type(a))  #返回值多於一個,反正的是tuple
<class 'tuple'>
print(a[0])  #可以按照元組方式調用返回值
jack
print(a[1])
23
print(name)
gavin


a = 'gavin'
 
def my(name):
    global a    #將a變爲全局變量
    name = 'jack'   #局部變量
    a = 'john'
    print(name,a)
 
my('a')
jack john
print(a)
john
names = ['alex','gavin','tom']
 
def my():
    print(names)
    names[1] = 'jack'   #將全局變量中的names[1]修改爲jack
    return names
 
my()
['alex', 'gavin', 'tom']
print(names)  #在打印時發現局部變量中的jack替換了全部變量中的gavin
['alex', 'jack', 'tom']

10、遞歸

在函數內部,可以調用其他函數,如果一個函數在內部調用函數本身,這個函數就叫做遞歸函數

  遞歸的特點:

1)必須有一個明確的結束條件

2)每次進入更深的一層遞歸時,問題規模相比上一次遞歸應有所減少

3)遞歸效率不高,遞歸層次過多會導致棧溢出(在計算機中,函數調用是通過棧這種數據結構實現的,每當進入一個函數調用,棧會增加一層棧幀,每當函數返回會減少一層棧幀,由於棧的大小不是無限的,所以遞歸次數過多會導致棧的溢出)

defcalc(n):
    print(n)
    if int(n/2) > 0:
       returncalc(int(n/2))
    print('--->', n)
calc(10)
10
5
2
1
---> 1

11、高階函數

變量可以指向函數,函數的參數能接受變量,那麼一個函數就能接收另一個函數作爲參數,這種函數叫做高階函數

def add(a,b,f):
    return f(a) + f(b)
res =add(3,-10,abs)
print(res)
13

 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章