1. 程式人生 > >python學習筆記(集合的使用、文件操作、字符編碼與轉碼、函數)

python學習筆記(集合的使用、文件操作、字符編碼與轉碼、函數)

函數式編程 close 取值 指定編碼 mage 指定位置 lac 空白 你在

集合

集合(set):把不同的元素組成一起形成集合,是python基本的數據類型。

集合元素(set elements):組成集合的成員

為什麽需要集合?

集合的作用

1 .列表去重復數據

按照現有知識的解決思路:先設置空列表,然後使用for尋獲,把需要去重的列表的第一個數據放到新列表中,然後依次取出第二個數據,把第二個數據和第一個數據作比較,如果不一樣,則存入新列表中;以此類推,每取一次都要和新列表中的數據作對比,不一樣的則添加入新列表中。

2. 關系測試

比如有學員同時報了python班和linux班,同時在2個列表中,可以用集合來找出該關系。

列表去重

list_1 =[1,4,5,7,3,6,7,9,9,9,1,3,2,5,11,23,222,234,35,11]
list_1 = set(list_1)
print(list_1)

查看運行結果,列表在轉成集合後去除了重復數據。

註意點:集合也是無序的。

集合的關系測試

技術分享
list_1 =[1,4,5,7,3,6,7,9,9,9,1]
list_1 = set(list_1)

list_2 = set([2,6,0.66,22,8,4])

# print(list_1,list_2)
#交集
print(list_1.intersection(list_2))

#並集
print(list_1.union(list_2))

#差集   list_1裏有,list_2裏沒有
print(list_1.difference(list_2))
print(list_2.difference(list_1))

#子集
list_3 = set([1,3,7])
print(list_3.issubset(list_1)) #list_3是list_1的子集,返回True
#父集
print(list_1.issuperset(list_3)) #list_1是list_3的父集,返回True

#對稱差集
print(list_1.symmetric_difference(list_2))

print("-----------")
list_4 = set([5,6,8])
print(list_3.isdisjoint(list_4)) #判斷是否是分離集合,不相交
技術分享

集合的運算符

技術分享
list_1 =[1,4,5,7,3,6,7,9,9,9,1]
list_1 = set(list_1)
list_2 = set([2,6,0.66,22,8,4])

#交集(intersection):&
print(list_1 & list_2)

#並集(union):|
print(list_1 | list_2)

#差集(difference):-
print(list_1 - list_2)

#對稱差集(symmetric_difference):^
print(list_1 ^ list_2)
技術分享

集合的增刪改查

技術分享
list_1 = set([1,3,5,2,8,11,17])
list_1.add(999) #添加一項
list_1.update([888,777,555]) #添加多項
print(list_1)
list_1.remove(888) #刪除一項
print(list_1)
print(len(list_1)) #集合的長度

list_1 in list_2 #判斷list_1是否是list_2的成員
list_1 not in list_2 #判斷list_1是否不是list_2的成員

print(list_1.pop()) #任意刪除一項
print(list_1.remove(‘ddd‘)) #使用remove時,如果對象不存在,會出現報錯信息
print(list_1.discard(‘ddd‘)) #使用discard時,對象不存在也不會報錯
技術分享

文件操作

對文件操作流程:

1. 打開文件,得到文件句柄並賦值給一個變量

2. 通過句柄對文件進行操作

3. 關閉文件

實例一:

f = open(‘yesterday.txt‘,encoding=‘utf-8‘) #文件句柄 文件的內存對象
data = f.read()
data2 = f.read()
print(data)
print(‘data2‘.center(50,‘-‘),data2)

以上例子中,data和data2讀取了2次文件內容,但在屏幕輸出時,只顯示一次內容。因為文件的操作在讀取完之後,指針停留在最後一行,所以data2的賦值,並沒有讀取到內容。

文件基礎操作:

以下三種文件打開操作,寫入並不兼容讀取。有‘r’權限的時候不能寫入,有‘w‘權限的時候不能讀取,程序會報錯。

#讀取文件內容
f = open(‘yesterday2.txt‘,‘r‘,encoding=‘utf-8‘) #文件句柄 文件的內存對象
data = f.read()
print(data)
f.close()
技術分享
#文件只寫操作
f = open(‘yesterday2.txt‘,‘w‘,encoding=‘utf-8‘) #文件句柄 文件的內存對象,open可以創建文件,使用寫入權限時千萬註意
f.write("我愛北京天安門,\n")
f.write("天安門上太陽升,\n")
f = open(‘yesterday2.txt‘,‘r‘,encoding=‘utf-8‘)
data = f.read()
print(data)
#查看輸出,文件原有內容丟失。證明open ‘w’操作是創建文件。不能亂用。
技術分享 技術分享
#文件追加內容
f = open(‘yesterday2.txt‘,‘a‘,encoding=‘utf-8‘) #文件句柄 文件的內存對象
#a = append 追加
f.write("我愛北京天安門2,\n")
f.write("天安門上太陽升2,\n")
f = open(‘yesterday2.txt‘,‘r‘,encoding=‘utf-8‘)
data = f.read()
print(data)

f.close()
技術分享

其他文件打開模式:

文件讀寫:(r+)

文件寫讀:(w+)

文件追加讀:(a+)

"U"表示在讀取時,可以將 \r \n \r\n自動轉換成 \n (與 r 或 r+ 模式同使用)

  • rU
  • r+U

"b"表示處理二進制文件(如:FTP發送上傳ISO鏡像文件,linux可忽略,windows處理二進制文件時需標註)

  • rb
  • wb
  • ab

實例:

需求:打印歌詞文件,跳過第十行不打印,第十行打印分割線。

f = open(‘yesterday.txt‘,‘r‘,encoding=‘utf-8‘)
for index,line in enumerate(f.readlines()): #註意:readlines一次讀取文件內容到內存,只適合小文件。
    if index == 9:
        print("-------------------------")
        continue
    print(line.strip()) #strip()默認刪除空白符(包括‘\n‘, ‘\r‘,  ‘\t‘,  ‘ ‘)

前一個需求的改進寫法:

技術分享
#高效率方法
f = open(‘yesterday.txt‘,‘r‘,encoding=‘utf-8‘)
count = 0
for line in f: #文件變成叠代器,讀取一行刪除一行,內存中只占一行內容
    if count == 9:
        print("-------我是分割線-------")
        count +=1
        continue
    print(line.strip())
    count +=1
技術分享

文件讀/寫指針操作:

技術分享
f = open(‘yesterday.txt‘,‘r‘,encoding=‘utf-8‘)
print(f.tell()) #返回文件讀/寫指針當前位置,開始是0
print(f.read(5)) #讀取字符數
print(f.tell()) #返回當前指針所在位置,按字符計算
f.seek(0) #讓文件讀/寫指針移到指定位置
print(f.readline()) #文件已回到開頭

f.close()
技術分享
以1個例子說明tell()和seek()函數的作用:
技術分享
fso = open("a.txt",‘w+‘) #以w+方式,並非a方式打開文件,故文件原內容被清空
print(fso.tell()) #文件原內容被清空,故此時tell()=0
fso.write("abcde\n") #寫入文件abcde\n,因為換行\n占兩個字符,故共寫入7個字符
print(fso.tell()) #此時tell()=7
fso.write("fghwm") #又寫入文件fghwm,故此時文件共寫入7+5 =12個字符
print(fso.tell()) #此時tell()=12
fso.seek(1, 0) #從起始位置即文件首行首字符開始移動1個字符
print(fso.tell()) #此時tell() =1
print(fso.readline()) #讀取當前行,即文件的第1行,但是從第二個字符(tell()+1)開始讀,結果為:bcde。
#若換成for讀取整個文件或read讀取整個文件則結為bcdefghwm
print(fso.tell()) #因為readline此時tell() =7,
fso.truncate(8) #從寫入後文件的首行首字符開始階段,截斷為8個字符,即abcde\nf,即文件的內容為:abcde\nf
print(fso.tell()) #tell() 依舊為7,並為受truncate(8)影響,但是此時文件內容為abcde\nf
print(fso.readline()) #從tell()+1=8開始讀取,讀取當前行內容:f
fso.close()
技術分享
 

文件操作:flush()實例

flush() 方法是用來刷新緩沖區的,即將緩沖區中的數據立刻寫入文件,同時清空緩沖區,不需要是被動的等待輸出緩沖區寫入。

一般情況下,文件關閉後會自動刷新緩沖區,但有時你需要在關閉前刷新它,這時就可以使用 flush() 方法。

在cmd命令行中才能看到實際測試效果。在命令行中往文本文件中寫入數據後,並不是馬上就會保存,python會在寫滿緩存後再一次性寫入硬盤。使用了f.flush()代碼後,可以馬上寫入硬盤。

進度條實例:

import sys,time

for i in range(50):
    sys.stdout.write("#")
    sys.stdout.flush()
    time.sleep(0.1)

文件修改實例:

需求:已有Yesterday when I was young這首歌的歌詞文件yesterday.txt,修改其中的一句歌詞翻譯:”肆意的快樂等我享受”改為“肆意的快樂等Alex享受”。

解決方法:一行行讀取,遇到符合條件的行後進行修改,然後新建yesterday3.txt文件保存歌詞文件。

技術分享
f = open("yesterday.txt",‘r‘,encoding="utf-8")
f_new = open("yesterday3.txt","w",encoding="utf-8")

for line in f:
    if "肆意的快樂" in line:
        line = line.replace("肆意的快樂等我享受","肆意的快樂等Alex享受")
    f_new.write(line)

f.close()
f_new.close()
技術分享

with語句

with語句作用,自動關閉文件

with open("yesterday.txt","r",encoding="utf-8") as f:
    for line in f:
        print(line.strip())

可以用with同時打開多個文件

with open("yesterday.txt","r",encoding="utf-8") as f ,       open("yesterday3.txt","r",encoding="utf-8") as f2: #官方文檔建議每行代碼不超過82個字符,所以分行編寫
      for line in f:
          print(line)

字符編碼與轉碼

#-*- coding:utf-8 -*-      #python2中需要指定編碼類型為:utf-8,python3中默認編碼類型為Unicode

ASCII碼

GB2312:GB是“國標”兩字的拼音首字,2312是標準序號。GB2312編碼是第一個漢字編碼國家標準,由中國國家標準總局1980年發布,1981年5月1日開始使用。共收錄漢字6763個。

GBK:是對GB2312編碼的擴展。共收錄漢字和圖形符號21886個。其中漢字21003個。

GB18030:2000年3月17日發布。是對GBK編碼的擴充。收錄27484個漢字。

UNICODE(統一碼、萬國碼、單一碼)是一種在計算機上使用的字符編碼。

Unicode 是為了解決傳統的字符編碼方案的局限而產生的,它為每種語言中的每個字符設定了統一並且唯一的二進制編碼,規定雖有的字符和符號最少由 16 位來表示(2個字節),即:2 **16 = 65536, 註:此處說的的是最少2個字節,可能更多

UTF-8:是對Unicode編碼的壓縮和優化,他不再使用最少使用2個字節,而是將所有的字符和符號進行分類:ascii碼中的內容用1個字節保存、歐洲的字符用2個字節保存,東亞的字符用3個字節保存...

編碼實例:

來自於:http://www.cnblogs.com/luotianshuai/articles/5735051.html

python3中:

技術分享
#!/usr/bin/env python
#-*- coding:utf-8 -*-
#author luotianshuai

tim = ‘天帥‘
#轉為UTF-8編碼
print(tim.encode(‘UTF-8‘))
#轉為GBK編碼
print(tim.encode(‘GBK‘))
#轉為ASCII編碼(報錯為什麽?因為ASCII碼表中沒有‘天帥’這個字符集~~)
print(tim.encode(‘ASCII‘))
技術分享

python2中:

因為在python2.X中默認是ASCII編碼,你在文件中指定編碼為UTF-8,但是UTF-8如果你想轉GBK的話是不能直接轉的,的需要Unicode做一個轉接站點。

技術分享
#!/usr/bin/env python
#-*- coding:utf-8 -*-
#author luotianshuai

import chardet
tim = ‘你好‘
print chardet.detect(tim)
#先解碼為Unicode編碼,然後在從Unicode編碼為GBK
new_tim = tim.decode(‘UTF-8‘).encode(‘GBK‘)
print chardet.detect(new_tim)

#結果
‘‘‘
{‘confidence‘: 0.75249999999999995, ‘encoding‘: ‘utf-8‘}
{‘confidence‘: 0.35982121203616341, ‘encoding‘: ‘TIS-620‘}
‘‘‘
技術分享

函數與函數式編程

編程方式:

1. 面向對象:類----->>class

2. 面向過程:過程---->>def

3. 函數式編程:函數---->>def

函數定義:

初中數學函數定義:一般的 ,在一個變化過程中,如果有兩個變量x和y,並且對於x的每一個確定的值,y都有唯一確定的值與其對應,那麽我們就把x稱為自變量,把y稱為因變量,y是x的函數。自變量x的取值範圍叫做這個函數的定義域。

編程語言中函數定義:函數式邏輯結構化和過程化的一種編程方法。

python中函數定義方法:

技術分享
#python中函數定義方法:
def test(x):
    ‘‘‘The function definitions‘‘‘
    x +=1
    return x
# def:定義函數的關鍵字
# test:函數名
# ():內可定義形參
# ‘‘‘‘‘‘:文檔描述(非必要,但是強烈建議為你的函數添加描述信息)
# x+=1:泛指代碼塊或程序處理邏輯
# return:定義返回值
技術分享

函數式編程就是:先定義一個數學函數,然後按照這個數學模型用編程語言去實現它。

為什麽要使用函數:

沒有函數的編程只是在寫邏輯(功能),想脫離函數,重用你的邏輯,唯一的方法就是拷貝

例子一:

技術分享
def test1():
    print(‘in the test1‘)
    with open(‘a.txt‘,‘a+‘) as f:
        f.write(‘end action\n‘)

def test2():
    print(‘in the test2‘)
    with open(‘a.txt‘,‘a+‘) as f:
        f.write(‘end action\n‘)
def test3():
    print(‘in the test3‘)
    with open(‘a.txt‘,‘a+‘) as f:
        f.write(‘end action\n‘)
test1()
test2()
test3()
技術分享

例子二:對以上代碼進行優化,並且加入日誌時間。使用函數編程方法:

技術分享
import time

def logger():
    time_format = ‘%Y-%m-%d %X‘
    time_current = time.strftime(time_format)
    with open(‘a.txt‘,‘a+‘) as f:
        f.write(‘%s end action\n‘ %time_current)

def test1():
    print(‘in the test1‘)
    logger()

def test2():
    print(‘in the test2‘)
    logger()
def test3():
    print(‘in the test3‘)
    logger()
test1()
test2()
test3()
技術分享

使用函數的三大優點:

1. 代碼重用

2. 保持一致性

3. 可擴展性

函數參數及調用

函數返回值:

技術分享
def test1():
    print(‘in the test1‘)

def test2():
    print(‘in the test2‘)
    return 0
def test3(): print(‘in the test3‘) return 1,‘hello‘,[‘alex‘,‘wupeiqi‘],{‘name‘:‘alex‘}   #return test2 #return可以返回任意類型,也可以是函數 x=test1() y=test2() z=test3() print(x) print(y) print(z)
技術分享

總結:

  返回值數=0;返回None

  返回值數=1;返回object

  返回值數>1;返回tuple

為什麽要有返回值?

  其他的程序邏輯需要根據返回值進行操作

調用方法:

1. 形參和實參

  根據位置一一對應

例一:

技術分享
def test(x,y):
    print(x)
    print(y)

test(1,2)
# test(y=2,x=1) #與形參順序無關
# test(1,2) #位置參數與形參一一對應
test(3,x=1) #程序報錯,因為同時給x賦值2次,y沒有賦值
技術分享

例二:

技術分享
def test(x,y,z):
    print(x)
    print(y)
    print(z)

test(3,y=1,z=6) #這樣賦值是允許的
test(3,y=1,6) #位置參數雖然一一對應,但程序會報錯。因為關鍵參數不能出現在位置參數前面。切記。
技術分享

函數的非固定參數

默認參數:

def test(x,y=2): #y=2是默認參數
    print(x)
    print(y)
test(1,3)

默認參數特點:調用函數的時候,默認參數非必須傳遞

默認參數用途:例如連接mysql數據時,可以默認指定端口號:3306

參數組:

1.

def test(*args):
    print(args)

test(1,2,3,4,5,5)
test(*[1,2,3,4,5]) # args=tuple([1,2,3,4,5])

2.

# **kwargs:把N個關鍵字參數,轉換成字典的方式
def test2(**kwargs):
    print(kwargs)

test2(name=‘alex‘,age=8,sex=‘F‘)
def test3(name,**kwargs):
    print(name)
    print(kwargs)
test3(‘alex‘,age=18,sec=‘m‘) # 使用關鍵字方式傳入
def test4(name,age=18,**kwargs):
    print(name)
    print(age)
    print(kwargs)
test4(‘alex‘,sex=‘m‘,age=3,hobby=‘tesla‘) #age參數可以在任意位置

3.

def test4(name,age=18,*args,**kwargs):
    print(name)
    print(age)
    print(args) #args接收N個位置參數
    print(kwargs) #kwargs接收N個關鍵字參數
test4(‘alex‘,34,1,2,3,sex=‘m‘,hobby=‘tesla‘) #34傳遞給age,1,2,3傳遞給了args

作用域、局部與全局變量

在子程序中定義的變量稱為局部變量,在程序的一開始定義的變量稱為全局變量。

全局變量作用域是整個程序,局部變量作用域是定義該變量的子程序。

當全局變量與局部變量同名時:在定義局部變量的子程序內,局部變量起作用;在其他地方全局變量起作用。

實例一:局部變量、作用域、全局變量的定義

技術分享
school = "Oldboy edu." #全局變量
def change_name(name):
    school = "Mage" #局部變量
    print("before change",name,school)
    name = "Alex Li" #局部變量,只在函數內生效。這個函數就是該變量的作用域。
    age =23
    print("after change",name)

name = ‘alex‘
change_name(name)
print(name)
print(school)
技術分享

實例二:如何在子程序(函數)中修改全局變量。

註意事項:千萬不要在函數中改全局變量。容易造成程序邏輯混亂,增加排錯難度。

技術分享
school = "Oldboy edu." #全局變量
def change_name(name):
    global school  # 在函數中定義全局變量
    school = "Mage" #使用global後,school被聲明為全局變量
    print("before change",name,school)
    name = "Alex Li" 
    print("after change",name)

name = ‘alex‘
change_name(name)
print(name)
print(school)
技術分享

註意事項二:

字符串和整數類型變量不能在函數中直接更改

列表、字典、集合、類都可以在函數中更改

遞歸

在函數內部,可以調用其他函數。如果一個函數在內部調用自身,這個函數就是遞歸函數。

遞歸特性:

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

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

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

函數式編程介紹

函數式編程中的函數這個術語不是指計算機中的函數(實際上是Subroutine),而是指數學中的函數,即自變量的映射。也就是說一個函數的值僅決定於函數參數的值,不依賴其他狀態。比如sqrt(x)函數計算x的平方根,只要x不變,不論什麽時候調用,調用幾次,值都是不變的。

函數式編程(請註意多了一個“式”字)——Functional Programming,雖然也可以歸結到面向對象過程的程序設計,但其思想更接近數學計算。

函數式編程時一種抽象程度很高的編程範式。

定義:

簡單說,“函數式編程”是一種“編程範式”(programming paradigm),也就是如何編寫程序的方法論。

主要思想是把運算過程盡量寫成一系列嵌套的函數調用。

高階函數

變量可以指向函數,函數的參數能接收變量,那麽一個函數就可以接收另一個函數作為參數,這種函數就稱之為高階函數。

舉例:

def add(a,b,f):
    return f(a)+f(b)

res = add(3,-6,abs) #abs是絕對值函數
print(res)

python學習筆記(集合的使用、文件操作、字符編碼與轉碼、函數)