1. 程式人生 > 實用技巧 >Python學習手冊之Python物件型別(本人菜雞,勿噴,謝謝)

Python學習手冊之Python物件型別(本人菜雞,勿噴,謝謝)

Python學習手冊之Python物件型別

歡迎大家,評論,互相學習,謝謝~!

郵箱:[email protected]

為什麼使用內建型別

1.容易編寫

2.拓展的元件

3.內建物件往往比內建的資料結構更有效率

4.內建物件是語言標準的一部分

Python的核心資料型別

數字

當有需要的時候,Python3.0整數型別會自動提供額外的精度。

全精度以及使用者友好形式,全精度使用repr,第二種是使用者友好形式str。

>>> import math                                                         >>> math.pi                                                              3.141592653589793                                                   
>>> math.sqrt(85)                                                        9.219544457292887  

random :隨機數字的生成器和選擇器

import random
>>> random.random()
0.9612122816381569
>>> random.choice(1,2,3,4)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: choice() takes 2 positional arguments but 5 were given
>>> random.choice([1,2,3,4])
2

字串

序列的操作

字串支援假設其中各個元素包含位置順序的操作。

>>> S = 'Spam'
>>> len(S)
4
>>> S[0]
'S'
>>> S[1]
'p'

索引是按照從最前面的偏移量開始編碼的,也就是從0開始,第一項索引為0,第二項索引為1,以此類推

反向索引

>>> S[-1]
'm'
>>> S[-2]
'a'
>>> S[len(S)-1]
'm'
>>> S
'Spam'

可以在方括號中使用任意表達是,而不僅僅能使用數字常量

分片:一般形式為X[I:J],表示“取出在X中從偏移量為I,知道但不包括偏移量為J的內容”。結果是返回一個新物件。

>>> S = 'spwan'
>>> S
'spwan'
>>> S[1:3]
'pw'

在一個分片中,左邊界預設為0,並且右邊界預設為分片序列的長度

>>> S
'spwan'
>>> S[1:]
'pwan'
>>> S[0:3]
'spw'
>>> S[:-1]
'spwa'
>>> S[:]
'spwan'
>>> S
'spwan'
>>> S + 'xyz'
'spwanxyz'
>>> S
'spwan'
>>> S * 8
'spwanspwanspwanspwanspwanspwanspwanspwan'

作為一個序列,字串也支援用加號合併(將兩個字串合成一個新的字串),或者(通過重複一個建立一個新的字串)

+對不同物件有不同意義:對於數字為加法,對於字串為合併。

不可變性

字串在Python中具有不可變性 在建立或不能就地改變。例如,不能通過對其進行復制。因為Python在執行過程中會清理舊物件

>>> S
'spwan'
>>> S[0]='Z'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment
>>> S = 'Z' + S[1:]
>>> S
'Zpwan'

在Python中每一個物件都可以分為不可變性或者可變性。

不變:數學、字串和元祖

可變:列表和字典

型別特定的方法

字串的find方法是一個基本的子字串查詢的操作(它將放回一個傳入子字串中的偏移量,或者沒有找到的情況下返回-1),而字串的replace方法將會對全域性進行搜尋和替換。

>>> S.find('pa')
-1
>>> S
'Zpwan'
>>> S.find('pW')
-1
>>> S.find('pw')
1
>>> S.replace('Zp','AAA')
'AAAwan'
>>> S
'Zpwan'
>>> line = 'aaa,bbb,ccccc,ddd'
>>> line.split(',')
['aaa', 'bbb', 'ccccc', 'ddd']
>>> line.split(',')[:1]
['aaa']
>>> line.split(',')[:]
['aaa', 'bbb', 'ccccc', 'ddd']
>>> line.split(',')[0:]
['aaa', 'bbb', 'ccccc', 'ddd']
>>> line.split(',')[0:1]
['aaa']
>>> line.split(',')[1:3]
['bbb', 'ccccc']
>>> line ='aaa,bbb,cccc,dd\n'
>>> line = line.rstrip()
>>> line
'aaa,bbb,cccc,dd'

Python split() 通過指定分隔符對字串進行切片,如果引數 num 有指定值,則分隔num+1 個子字串

Python rstrip() 刪除 string 字串末尾的指定字元(預設為空格).

字串還支援一個叫做格式化的高階代替操作,可以以一個表示式的形式(最初的)和一個字串的方法呼叫:

>>> '%s eggs,and %s' %('spam','SPWAM!')
'spam eggs,and SPWAM!'

>>> '{0},eggs and {1}'.format('span','SPAM!')
'span,eggs and SPAM!'

一條簡明法則是這樣的:可作用於多種型別的通用操作型操作都是以內建函式或表示式的形式出現的[例如,len(x),len[0] ], 但是型別特定的操作是以方法呼叫的形式出現的[ 例如,aString.upper() ]。 如果經常使用Python,你會更順利地從這些分類中找到你所需要的工具

幫助

dir函式簡單地給出方法的總稱,要查詢他們是做什麼的,你可以將其傳遞給help函式。

>>> help(S.replace)

編寫字串的其他方法

反斜線轉義序列表示特殊的符號

>>> S = 'A\nB\tC'
>>> len(S)
5
>>> ord('\n')
10
>>> S = 'A\o\B\oC'
>>> len(S)
8

Python允許字串包括在單引號或雙引號中(他們代表著相同的東西)。它也允許在三個引號(單引號或雙引號)中包括多行字串常亮。當採用這種形式的時候,所有的行都合併在一起,並在沒一行的末尾增加換行符。

>>> msg = """ aaaaaaaaaaaaaaa bbb'''bbbbbbbbbbbbb""bbbbbbbbb'bbbbbbbb cccccccccccccccccccc"""
>>> msg
' aaaaaaaaaaaaaaa bbb\'\'\'bbbbbbbbbbbbb""bbbbbbbbb\'bbbbbbbb cccccccccccccccccccc'

python也支援原始(raw) 字串常量,即去掉反斜線轉義機制(這樣的字串常量是以字母“r”)。Python還支援Unicode字串形式從而支援國際化。在Python3.0中,基本的str字串型別也處理Unicode,並且用bytes型別表示原始位元組字串,在Python2.6中,Unicode是一種單獨的型別,str處理8位字串和二進位制資料。在Python3.0中,檔案也改變為返回和接受str,從而處理二進位制資料文字和位元組。

模式匹配

>>> import re
>>> match = re.match('Hello[\t]*(.*)world','Hello Python world')
>>> match.group(1)
' Python '

這個子字串以“Hello”,開始,後面跟著零個或幾個製表符或空格,接著又任意字元並將其報酬之匹配的group中,最後以”world.“ 結尾。

模式匹配本身是一個相當高階的文字處理工具,但是在Python中還支援更高階的語言處理工具。

列表

列表是一個任意型別的物件位置相關的有序集合

序列操作

列表支援所有對字串的序列操作,唯一區別就是其結果往往是列表不是字串

>>> L = [123,'spam',1.23]
>>> len(L)
3
>>> L[0]
123
>>> L[::-1]
[1.23, 'spam', 123]
>>> L+[4,5,6]
[123, 'spam', 1.23, 4, 5, 6]
>>> L
[123, 'spam', 1.23]

型別特定的操作

Python的列表於其他語言中的陣列有些類似,但是列表要強大的多,其中一個方面就是,列表沒有固定型別的約束。

>>> L.append('NI')
>>> L
[123, 'spam', 1.23, 'NI']
>>> L.pop(2)
1.23
>>> L
[123, 'spam', 'NI']

列表的append方法擴充了列表的大小並在列表的尾部插入一項;pop方法(或者等效的del語句)移除給定偏移量的一項,從而讓列表減小。其他的列表方法可以在任意位置插入(insert)元素,按照值移除(remove)元素等。因為列表是可變的,大多數列表的方法都會就地改變列表物件,而不會建立一個新的列表:

>>> M = ['bb', 'aa','cc']
>>> M.sort()
>>> M
['aa', 'bb', 'cc']
>>> M.reverse()
>>> M
['cc', 'bb', 'aa']

邊界檢查

儘管列表沒有固定大小,Python仍不允許引用不存在的元素。超出列表末尾之外的索引總是會導致錯誤,對列表末尾範圍之外的賦值也是如此。

>>> L[99] =1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: list assignment index out of range

巢狀

Python核心資料型別的一個優秀特性就是它們支援任意的巢狀。能夠以任意組合對其進行巢狀,並可以多個層次進行巢狀。這種特性的一個直接應用就是實現矩陣,或者Python中的多維陣列,一個巢狀列表的列表能夠完成這個基本操作。

>>> M = [ [1,2,3],
... [4,5,6],
... [7,8,9]]
>>> M
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

列表解析

提供了一種處理想矩陣這樣結構強大工具。

>>> col2= [row[1] for row in M]
>>> col2
[2, 5, 8, 11]
>>> M
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 2]]

他是通過對序列中每一項執行一個表示式來建立一個新的列表,每次一個,從左至右。列表解釋是編寫在方括號中的,並且使用同一種變量表達式和迴圈結構組合。

列表解析源自集合的概念。

>>> [row[1]+1 for row in M]
[3, 6, 9, 12]
>>> M
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 2]]
>>> [row [1] for row in M if row[1]%2 == 0]
[2, 8]
>>> diag = [M[i][i] for i in [0,1,2]]
>>> diag
[1, 5, 9]
>>> M
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> doubles = [c *2 for c in 'spam']
>>> doubles
['ss', 'pp', 'aa', 'mm']
>>>G = (sum(row) for row in M)
>>> next (G)
6
>>> next (G)
15

內建函式map可以做類似的事情,產生對各項執行一個函式的結果

>>> list(map(sum,M))
[6, 15, 24]
>>> {sum(row) for row in M}
{24, 6, 15}

map() 會根據提供的函式對指定序列做對映。

第一個引數 function 以引數序列中的每一個元素呼叫 function 函式,返回包含每次function 函式返回值的新列表。

解析語法也可以用來建立集合和字典:

>>> {i : sum(M[i]) for i in range(3)}
{0: 6, 1: 15, 2: 24}
>>> [ord(x) for x in 'spaam']
[115, 112, 97, 97, 109]
>>> {ord(x) for x in 'spaam'}
{112, 97, 115, 109}
>>> {x:ord(x) for x in 'spaam'}
{'s': 115, 'p': 112, 'a': 97, 'm': 109}

字典

Python中的字典是完全不同的東西,它們不是序列,而是一種對映。對映是一個其他物件的集合,但是它們是通過鍵而不是相對位置來儲存。實際上,對映並沒有任何可靠的從左至右的順序。它們簡單地將鍵對映到值。字典是Python核心物件集合的唯一一種對映型別,也具有可變性——可以就地改變,並可以隨需求增大或減小。

對映操作

作為常量編寫時,字典編寫在大括號中,並且包含一系列的“鍵:值” 對。在我們需要將鍵於一系列值相關聯(例如,為了表述某物的某屬性)的時候,字典是很有用的。

>>> D = {'food':'Spam','quantity':4,'color':'pink'}
>>> D
{'food': 'Spam', 'quantity': 4, 'color': 'pink'}
>>> D['food']
'Spam'
>>> D['quantity'] +=1
>>> D
{'food': 'Spam', 'quantity': 5, 'color': 'pink'}
>>> D ={}
>>> D['name'] = 'Bob'
>>> D['job'] = 'dev'
>>> D['age'] = 40
>>> D
{'name': 'Bob', 'job': 'dev', 'age': 40}
>>> print(D['name'])
Bob

重訪巢狀

>>> rec = {'name': {'first' : 'Bob','last':'Smith'},
... 'job':['dev','mgr'],
... 'age':40.5}
>>> rec ['name']
{'first': 'Bob', 'last': 'Smith'}
>>> rec ['name'] ['last']
'Smith'
>>> rec ['job']
['dev', 'mgr']
>>> rec ['job'][-1]
'mgr'
>>> rec['job'].append('janitor')
>>> rec
{'name': {'first': 'Bob', 'last': 'Smith'}, 'job': ['dev', 'mgr', 'janitor'], 'age': 40.5}

Python具有一種叫垃圾收集的特性,在程式執行時可以清理不再使用的記憶體,並將你從管理程式碼中這樣的細節中解放出來。在Python中,一旦一個物件的最後一次引用被移除,空間將會立即回收。

鍵的排序:for迴圈

因為字典不是序列,它們並不包含任何可靠的從左至右的順序。

D = {'a':1,'b':2,'c':3}
Ks = list(D.keys())
for key in Ks:
	print(key,'=>',D[key])

for迴圈是遍歷一個序列中的所有元素並按順序對每一元素執行一些程式碼的簡單並有效的一種方法。一個使用者定義的迴圈變數(這裡是key)用作每次執行過程中當前元素的參考量。

>>> for c in 'spam':
...   print (c.upper())
S
P
A
M

while迴圈是一種更為常見的排序迴圈工具,它不僅限於遍歷序列:

>>> x = 4
>>> while x> 0:
...  print ('spam!' *x )
...  x -= 1
...
spam!spam!spam!spam!
spam!spam!spam!
spam!spam!
spam!

迭代和優化

迭代協議(這是Python中無處不在的一個概念,表示在記憶體中的物理儲存序列,或一個在迭代操作情況下每次產生一個元素的物件)的任意物件。

從左往右地掃描一個物件的每個Python工具都使用迭代協議。

squares = [x ** 2 for x in [1,2,3,4,5,6]]
print (squares)
[1, 4, 9, 16, 25, 36]

編寫一個等效的for迴圈

squares = []
for x in [1,2,3,4,5]:
	squares.append(x**2)
print(squares)

[1, 4, 9, 16, 25]

if測試

D = {'a':1,'b':2,'c':3}
D['e'] = 12
print(D)
{'a': 1, 'b': 2, 'c': 3, 'e': 12}
print('f' in D)
False
>>> D = {'a':1,'b':2,'c':3}
>>> if 'f' not in D:
...  print ('missing')
...
missing

get方法(帶有一個預設值得條件索引)try語句(一個捕獲異常並從異常中恢復的工具)

>>> value = D['x'] if 'x' in D else 0
>>> value
0

元組

基本就像一個不可以改變額列表,就像列表一樣,元組是序列,但是它具有不可變性,和字串類似。從語法上,它們編寫在圓括號中而不是方括號

>>> T = (1,2,3,4)
>>> len(T)
4
>>> T + (5,6)
(1, 2, 3, 4, 5, 6)
>>> T[0]
1
>>> T
(1, 2, 3, 4)

元組的真正不同之處就在於一旦建立或就不能再改變。元組是不可變序列

>>> T = ('spam',3.0,[11,22,33])
>>> T
('spam', 3.0, [11, 22, 33])
>>> T[1]
3.0
>>> T[2]
[11, 22, 33]
>>> T[2][1]
22
>>> T.append(3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'tuple' object has no attribute 'append'

為什麼要用元組

元組在實際中往往沒有列表那樣常用,它是關鍵是不可變。元組提供了一個完整性的約束

檔案

檔案物件是Python程式碼對電腦上外部檔案的主要介面。雖然檔案是核心型別,但是它有些特殊:沒有特定的常量語法建立檔案。要建立一個檔案物件,需呼叫內建的open函式以字串的形式傳遞給他一個外部的檔名以及一個處理模式的字串。

f = open('data.txt','w')
f.write('hello\n')
f.wirte('world\n')
f.close

這樣就在當前檔案下建立了一個檔案,並向它寫入文字(檔名可以是完整的路徑,如果需要讀取電腦上其他位置的檔案)。為了讀出剛才所寫的內容,重新以‘r’處理模式開啟檔案,讀取輸入(如果在呼叫時忽略模式的話,這將是預設的)。之後將檔案的內容瀆職一個字串,並顯示它

f = open('data.txt')
text = f.read()
text.split()分隔,預設以逗號

Python3在檔案和二進位制資料之間劃出了一條清晰的界限。文字檔案把內容顯示為字串,並且自動執行Unicode編碼和解碼,而二進位制檔案把內容顯示為一個特定的位元組字串型別,並且執行你不修改地訪問

data = open('data.bin','rb').read

其他核心型別

集合不是對映也不是序列,相反他是唯一的不可改變的物件的無序集合。集合通過呼叫內建set函式而建立,或者使用Python3.0中新的集合常量和表示式建立,並且支援一般的數學集合操作

>>> X = set ('spam')
>>> Y={'h','a','m'}
>>> X,Y
({'s', 'm', 'a', 'p'}, {'h', 'a', 'm'})
>>> X&Y
{'a', 'm'}
>>> X|Y
{'h', 'p', 's', 'a', 'm'}
>>> X-Y
{'s', 'p'}
>>> {x **2 for x in [1,2,3,4]}
{16, 1, 4, 9}

如何破壞程式碼的靈活性

內建函式:type返回的型別物件是賦給該型別的另一個物件,其結果在Python3.0中略有不同,因為型別已經完全和類結合起來了。

>>> L=[x for x in range(4)]
>>> L
[0, 1, 2, 3]
>>> type(L)
<class 'list'>
>>> type(type(L))
<class 'type'>
>>> if type(L) == type([]):
...  print('yes')
...
yes

使用者定義的類

類定義了新的物件型別,擴充套件了核心型別

class  Worker:
	def __init__(self,name,pay):
		self.name=name
		self.pay=pay
	def lastName(self):
		return self.name.split()[-1]
	def giverRaise(self,percent):
		self.pay *= (1.0+percent)
		

這個類定義了一個新的物件的種類,有name和pay兩個屬性(有時候叫狀態資訊),也有兩個小的行為編寫為函式(通常叫方法)的形式。就像函式那樣去呼叫,會生成新的型別例項,並且類的方法呼叫,類的方法自動獲取被處理的例項

隱含的“self”物件是我們八折叫做面對物件模型的原因,即一個類中的函式總有一個隱含的物件。一般來說,儘管這樣,基於類的型別是建立在並使用了核心型別的。

剩餘內容

Python指令碼中能處理的所有事情都是某種型別的物件,Python中每樣東西都是一個物件