【注】書籍作者:Mark Lutz (原書第五版)
# Python
? Python 是一門通用型的編程語言东臀,而它時(shí)常扮演著腳本語言的角色。一般來說剧浸,它可定義為一門面型對象的腳本語言,是一門融合了面向過程,函數(shù)式和面向?qū)ο缶幊谭绞降亩嗄繕?biāo)語言击罪。
? Python的傳統(tǒng)運(yùn)行時(shí)執(zhí)行模型是,輸入的源代碼轉(zhuǎn)換為字節(jié)碼贪薪,之后字節(jié)碼在Python虛擬機(jī)中運(yùn)行媳禁。代碼自動被編譯之后再被執(zhí)行
? Python中, 一個(gè)以擴(kuò)展名.py
結(jié)尾的源代碼文件都是一個(gè)模塊画切。一個(gè)Python程序往往由多個(gè)模塊文件構(gòu)成竣稽,通過import
連接在一起。其中的一個(gè)文件被指定為主文件,或叫頂層文件毫别,或腳本
--就是那個(gè)啟動后能夠運(yùn)行整個(gè)程序的文件娃弓,至此之下,全部都是模塊導(dǎo)入模塊拧烦。
? 模塊往往就是變量名的包忘闻,即眾所周知的命名空間,而在那個(gè)包中的變量名稱為屬性恋博。模塊中的變量之間不會發(fā)生沖突
# Python 自測試辦法
? 控制臺啟動Python交互式命令模式齐佳,在控制臺中執(zhí)行實(shí)驗(yàn)和測試代碼
# 幾個(gè)用法
- 打印輸出:
print('Hello world!')
- 退出Python執(zhí)行環(huán)境:
<Ctrl-Z>
或exit()
- 注釋: Python 采用
#
實(shí)現(xiàn)注釋內(nèi)容 - 導(dǎo)入模塊:
import
, 它是一個(gè)語句,不需要括號债沮,用法如:import math
- 導(dǎo)入模塊中的屬性:
from - import
炼吴。用法如:from myfile import title
- 重載模塊:
reload()
他是一個(gè)函數(shù), 用法如:reload(script.py)
疫衩。3.X移到imp標(biāo)準(zhǔn)庫中
?
# Python 核心數(shù)據(jù)類型
? Python具有一些內(nèi)置的類型硅蹦, 它們使程序更容易編寫,比自己實(shí)現(xiàn)的數(shù)據(jù)結(jié)構(gòu)效率更高一些闷煤,他們也可擴(kuò)展童芹,是在語言標(biāo)準(zhǔn)的一部分。常見的對象類型及可變性如下所示:
? 除此之外鲤拿,還有 程序單元類型:函數(shù)假褪、模型、類近顷;Python實(shí)現(xiàn)相關(guān)類型: 已編譯代碼生音、調(diào)用棧跟蹤。
?
# 數(shù)據(jù)類型詳解及方法
? Python的變量是動態(tài)語言窒升,可以自動適應(yīng)不同類型的對象缀遍。它允許對一個(gè)已經(jīng)賦值為數(shù)字類型的變量重新賦值覆蓋成一個(gè)字符串類型,如s = 20
饱须,s = 'str'
域醇。
1. 數(shù)字
- 支持一般的數(shù)學(xué)運(yùn)算:(+)代表加法,(*)代表乘法蓉媳,(**)代表冪
- 浮點(diǎn)數(shù)顯示有
repr函數(shù)
和str形式
譬挚,repr函數(shù)的顯示有時(shí)會比預(yù)期更加精確,這不是bug督怜。另外,浮點(diǎn)數(shù)之所以稱之為浮點(diǎn)數(shù)狠角,是因?yàn)榭茖W(xué)計(jì)數(shù)法法時(shí)小數(shù)點(diǎn)位置是可變的号杠。如下
>>> 3.1415 * 2
6.2830000000000004
>>> print(3.1415 * 2)
6.283
- 支持導(dǎo)入常用的數(shù)學(xué)模塊
import math
;import random
>>> import random
>>> random.random()
0.7082048489415987
>>> random.choice([1,2,3,4])
3
2. 字符串
(1)序列操作:除字符串外,列表和元組也同樣有序列操作
- 獲取字符串長度:
len(s)
- 根據(jù)索引下標(biāo)獲取元素姨蟋。正向索引 :
s[0]
屉凯;反向索引:s[-1]
。反向索引的原理是s[-1]
其實(shí)等同于s[len(s)-1]
- 字符串中眼溶,方括號內(nèi)可以是任意表達(dá)式悠砚,如:
s[10-2]
- 字符串分片,也稱截取堂飞。規(guī)則:左閉右開:如
s[1:3]
獲取第二個(gè)到第三個(gè)元素灌旧。分片規(guī)則默認(rèn)左邊界為0,右邊界為分片序列的長度 - 字符串拼接:(+)表示拼接绰筛,(*)表示重復(fù)復(fù)制
- 不可變性: 字符串的不可變性比較難理解枢泰,指的是創(chuàng)建后不能在原位置修改,指的是字符串本身不能被修改铝噩,而不是字符串所對應(yīng)的那個(gè)變量不能被修改衡蚂,如下案例
>>> S = 'Spam'
>>> S
Spam # 已經(jīng)獲得變量 S的值為字符串 Spam
>>> S[0] = 'z'
...error text omitted...
TypeError: 'str' object doe not support item assignment
>>> S = 'z' + S[1:]
zspm # 先獲取S切片,在利用字符串拼接生成新的字符串骏庸,并用該值覆蓋原變量
【分析】 案例中試圖通過S[0]
的重新賦值修改原字符串毛甲,執(zhí)行時(shí)報(bào)錯。但通過s[1:]
獲取字符串切片后拼接字符串z
具被,再賦值給變量S
玻募,則執(zhí)行成功。這個(gè)案例充分表現(xiàn)了Python字符串不可變性的特征和工作范圍硬猫。通俗的說补箍,不可變性就是通過下標(biāo)方式只能獲取到字符串元素,而不能設(shè)置它啸蜜,因?yàn)榇藭r(shí)作用對象是字符串本身坑雅。但是允許我們對表示字符串的那個(gè)變量重新賦值,因?yàn)镻ython變量是動態(tài)語言衬横,允許被重新賦值和覆蓋裹粤。
- 字符串按單個(gè)字符轉(zhuǎn)成列表:
list()
- 字符串根據(jù)特定字符分割成列表:
split()
。注意使用的區(qū)別
>>> str = 'Hi,zfs'
>>> list(str) # list()中參數(shù)是要操作的對象
['H','i','z','f','s']
>>> str.split(',') # split()主語是操作對象蜂林,參數(shù)是識別分割的字符
['Hi', 'zfs']
-
列表轉(zhuǎn)字符串:
join()
遥诉,注意用法, 如使用杠拼接列表'-'.join(L)
- 字節(jié)編碼:
decode()
噪叙,如:B.decode()
(2)特定類型操作矮锈;字符串獨(dú)享
- 子字符串序列查找:
find()
。 返回一個(gè)傳入子字符串的偏移量睁蕾,沒找到返回-1
- 子字符串全局搜索和替換:
replace()
苞笨,不修改原對象
>>> S = 'Spam'
>>> S.find('pa')
1
>>> S.replace('pa', 'ZFS')
'SZFSm'
- 大寫格式化:
upper()
债朵,如:S.upper()
- 小寫格式化:
lowercase()
,如:S.lowercase()
- 是否是首字母大寫:
isalpha()
瀑凝, 如:'Span'.isapha()
序芦,返回 true - 移除右側(cè)不可視字符:
rstrip()
,如:'aa,bb,cc,dddd,dd\n' = rstrip()
, - 鏈?zhǔn)秸{(diào)用操作:
line.rstrip().split(',')
>>> line = 'aa,bb,c,dd\n'
>>> line = rstrip()
'aa,bb,c,dd'
>>> line.rstrip().split(',')
['aa', 'bb', 'c', 'dd']
- 高級替換操作
>>> '%s, eggs, add %s' % ('spam', 'SPAM') # %形式
'spam, eggs. and SPAM'
>>> '{0}, eggs, and {1}'.format('spam', 'SPAM') # format形式1
'spam, eggs, and SPAM'
>>> '{}, eggs, and {}'.format('spam', 'SPAM') # format形式2
'spam, eggs, and SPAM'
- 字符串格式化(用于數(shù)字形式):
>>> '{:,.2f}'.format(296999.3766)
'296,999.37'
>>> '%.2f | %+05d' % (3.14159, -42)
'3.14 | -0042'
- 單引號表示法
''
等同于 雙引號表示法""
粤咪;另外谚中,三引號'''
或"""
支持字符串換行書寫 - 模式匹配: 需要導(dǎo)入
re
模塊,調(diào)用re.match()
寥枝。超綱宪塔,讀者可自行了解
3. 列表 -List
(1)序列操作:列表也是序列,各元素存在順序關(guān)系
創(chuàng)建一個(gè)列表直接賦值即可脉顿,如L = [123, 'spam', 1.23]
- 獲取長度蝌麸;
len()
; 如:len(L)
- 列表切片:
L[start:end]
艾疟;如:L[:-1]
来吩,注意當(dāng)出現(xiàn)賦值時(shí),Python將自動為其加上len(L)
值 - 列表拼接:使用加號蔽莱,如:
L + ['abc', 12]
弟疆;運(yùn)行結(jié)果[123, 'spam', 1.23, 'abc', 12]
- 列表重復(fù):使用星號, 如:
L * 2
盗冷;運(yùn)行結(jié)果[123, 'spam', 1.23, 123, 'spam', 1.23]
【注】這些操作都不會改變原列表
(2)特定類型操作怠苔;列表獨(dú)享
- 在列表最后壓入一個(gè)元素:
append('NI')
;運(yùn)行結(jié)果[123, 'sapm', 1.23, 'NI']
- 根據(jù)下標(biāo)彈出元素仪糖,返回彈出的職:
pop(2)
柑司;執(zhí)行結(jié)果1.23
- 根據(jù)下標(biāo)插入一個(gè)元素:
insert(2, ‘a(chǎn)bc’)
- 根據(jù)元素內(nèi)容移除一個(gè)元素锅劝,但只會移除第一個(gè)匹配項(xiàng):
remove('Ni')
>>> L = [123, 'spam']
>>> L.append('Ni')
[123, 'spam', 'Ni']
>>> L.pop(1)
[123, 'Ni']
>>> L.insert(2, 'abc')
[123, 'Ni', 'abc']
>>> L.remove('Ni')
[123, 'abc']
- 重排序辦法:
sort()
攒驰; 規(guī)則:按照字母表排序 - 逆序輸出辦法:
reserve()
【注】這些操作都會改變原列表
(3)邊界檢查
? Python 的列表邊界檢查很嚴(yán)格,它不允許引用不存在的元素故爵,也就是說引用超出列表末尾之外的索引會報(bào)錯玻粪,無論是獲取還是賦值
>>> L = [123, 'spam', 'Ni']
>>> L[8]
# ...error text omitted...
# IndexError: list index out of range
>>> L[8] = 1 # error...
(4)嵌套 與 推導(dǎo)
? 列表中允許嵌套列表,看起來像是其他語言中的二維數(shù)組:
>>> M = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> M[0]
[1, 2, 3]
>>> M[1][2]
6
? Python中存在一種處理像矩陣這樣結(jié)構(gòu)的強(qiáng)大工具诬垂,稱作為 列表推導(dǎo)表達(dá)式劲室,他的格式如下:
[表達(dá)式 for 變量 in 列表]
或者[表達(dá)式 for 變量 in 列表 if 條件]
含義:在矩陣(或列表)中遍歷出‘變量’,如果有‘if條件’结窘,則對‘變量’執(zhí)行過濾很洋,最后對該變量執(zhí)行‘表達(dá)式’操作,執(zhí)行結(jié)束后返回一個(gè)新列表
>>> M = [[1,2,3],[4,5,6],[7,8,9]]
>>> [row[1] for row in M if row[1] % 2 == 0]
[2, 8]
>>> double = [c * 2 for c in 'spam']
>>> double
['ss', 'pp', 'aa', 'mm']
【解釋】in
執(zhí)行循環(huán)遍歷隧枫,if
執(zhí)行過濾操作喉磁,row[1]
執(zhí)行針對每個(gè)的row
表達(dá)式
(5)擴(kuò)展:list()結(jié)合range() 生成連續(xù)整數(shù)
? range()
用來指定一個(gè)數(shù)據(jù)范圍棺克,遵循左閉右開原則,可接受1,2,3個(gè)參數(shù)线定。結(jié)合list()
執(zhí)行后返回一個(gè)列表。
>>> list(range(4)) # 一個(gè)參數(shù)确买,表示 0-4
[0, 1, 2, 3]
>>> list(range(-4, 5, 2)) # 開始范(閉)斤讥,結(jié)束范圍(開),步長
[-4, -2, 0, 2, 4]
>>> [[x**2, x**3] for x in range(3)] # range()也可以用在列表推導(dǎo)表達(dá)式中
[[0, 0], [1, 1], [4, 8]]
(6)其他
- 內(nèi)置求和函數(shù):
sum()
- 內(nèi)置高階函數(shù):
map()
4. 字典
? 字典湾趾,不是序列芭商,而是一種映射(mapping
)。它是通過鍵(key
)而不是相對位置來存儲對象的搀缠。對象與列表不同铛楣,沒有它沒有邊界限制。當(dāng)對一個(gè)新的字典的鍵賦值時(shí)會創(chuàng)建該鍵
(1)字典賦值辦法
? 常見的對象賦值辦法有1. 直接創(chuàng)建法艺普;2. 根據(jù)鍵值對賦值簸州;3. zip整體賦值法
>>> D = {'a': 1, 'b': 2, 'c': 3 }
>>> bob1 = dict(name='Bob', Job='dev', age=40)
>>> bob1
{ 'age': 40, 'name': 'Bob', 'job': 'dev' }
>>> bob2 = dict(zip(['name', 'job', 'age'], ['Bob', 'dev', 40]))
>>>bob2
{ 'age': 40, 'name': 'Bob', 'job': 'dev' }
(2)重訪嵌套
? 字典允許嵌套存儲,即在字典的某個(gè)鍵屬性上存儲另一個(gè)字典歧譬,或者存儲其他類型的數(shù)據(jù)結(jié)構(gòu)岸浑,如 列表等。對這些嵌套的數(shù)據(jù)結(jié)果瑰步,他們的用法和其本身沒有區(qū)別矢洲。
>>> res = ['name': {'first': 'Bob', 'last': 'Smith'}, 'job': ['dev', 'mgr']]
>>> rec['job'].append('janitor')
['name': {'first': 'Bob', 'last': 'Smith'}, 'job': ['dev', 'mgr', 'janitor']]
(3)垃圾回收機(jī)制GC
? Python具有一種叫做垃圾回收的特性,在程序運(yùn)行時(shí)可以清理不在使用的內(nèi)存缩焦。一旦一個(gè)對象的最后一次引用被移除读虏,即變量引用數(shù)為0時(shí),空間將立即被回收袁滥。
(4)鍵值存在性檢查
>>> D = { 'a': 1, 'b': 2, 'c': 3 }
- in 關(guān)系表達(dá)式
'f' in D
===>false
- get() 方法
D.get('x', 0)
===>0
盖桥;因?yàn)?code>x 不存在與D
中,因此獲取默認(rèn)值0
- try語句 捕獲異常工具
- if/else 三元表達(dá)式:
>>> value = D['x'] if 'x' in D else 0
(5)鍵的排序 與 循環(huán)
? 字典不是序列呻拌,他們并不包含任何可靠的從左至右的順序, 對齊簡單的輸出其順序并不能得到保證葱轩。我們可以通過keys()
方法收集一個(gè)鍵的列表。使用列表的sort()
進(jìn)行排序
>>> D = { 'a': 1, 'b': 2, 'c': 3 }
>>> Ks = list(D.keys())
>>> Ks
{ 'a', 'c', 'b' } # 輸出順序是亂的
>>> Ks.sort()
{ 'a', 'b', 'c' } # sort() 使其按照字母順序輸出
>>> for key in Ks:
print (key, '=>', D[key])
? 與 for
循環(huán)相近的還有 while
循環(huán)
>>> x = 4
>>> while x > 0:
print ('spam' * 4)
x -= 1
(6)迭代和優(yōu)化
? Python中循環(huán)工作于任意的遵守迭代協(xié)議的可迭代對象中藐握。
? 一個(gè)可迭代對象可以是在內(nèi)存中物理存儲的序列靴拱,也可以是一個(gè)在迭代操作情況下每次產(chǎn)生元素的新對象:一種“虛擬”的序列。這兩種類型的對象都被認(rèn)為是可迭代的猾普。因?yàn)樗麄兌贾С值_協(xié)議: 他們在響應(yīng)next
之前先用一個(gè)對象對iter
內(nèi)置函數(shù)做出響應(yīng)袜炕,并在結(jié)束時(shí)觸發(fā)一個(gè)異常
? 迭代使用循環(huán) 如 :for
來實(shí)現(xiàn),盡管如此很高效初家,列表推導(dǎo)和相關(guān)的函數(shù)編程工具(如map和filter)在某些代碼上通常運(yùn)行比for
快甚至兩倍偎窘。 因此編程原則是:首先根據(jù)簡單和可讀性編寫乌助,在可以工作并證明確實(shí)有必要考慮性能是,在進(jìn)行以上優(yōu)化