日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > python >内容正文

python

python基础语法及知识点总结

發(fā)布時(shí)間:2024/3/13 python 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python基础语法及知识点总结 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

本文轉(zhuǎn)載于星過(guò)無(wú)痕的博客http://www.cnblogs.com/linxiangpeng/p/6403991.html

在此表達(dá)對(duì)原創(chuàng)作者的感激之情,多謝星過(guò)無(wú)痕的分享!謝謝!

?

Python學(xué)習(xí)的個(gè)人筆記

題外話:

我是一個(gè)大二的計(jì)算機(jī)系的學(xué)生,這份python學(xué)習(xí)個(gè)人筆記是趁寒假這一周在慕課網(wǎng),w3cschool,還有借鑒了一些博客,資料整理出來(lái)的,用于自己方便的時(shí)候查閱,一開(kāi)始保存在word上,代碼不是很好看,于是決定復(fù)制到博客里面,可能有復(fù)制過(guò)程中出錯(cuò)的,或者我本身在理解方面有出錯(cuò)的地方,希望能得到指正,謝謝

?后續(xù)的內(nèi)容我會(huì)繼續(xù)學(xué)習(xí)……

?

python下載地址??www.python.org

Python?分為2.7和3.3兩個(gè)版本,3.3有些庫(kù)不兼容,因此用2.7版本

Python解釋型語(yǔ)言? 代碼量小,可移植性高,執(zhí)行速度慢

配置環(huán)境變量 Path?? ;C:\Python27;

對(duì)縮進(jìn)要求嚴(yán)格,四個(gè)空格,不建議用Tab,不同平臺(tái)上縮進(jìn)不一樣

要輸出中文在開(kāi)頭寫(xiě)上? # -*- coding: utf-8 -*-

我使用的IDE為Pycharm注釋為ctrl + /

官方文檔?http://docs.python.org/2/

中文文檔??http://python.usyiyi.cn/

http://www.pythondoc.com/

一張圖概況Python學(xué)習(xí)(轉(zhuǎn)自W3Cschool)

目錄:

Python基礎(chǔ)語(yǔ)法:

(1)打印出hello world

(2)注釋

(3)數(shù)據(jù)類型

(4)運(yùn)算

(5)輸入

(6)輸出

(7)序列

(8)相等比較

(9)選擇

(10)循環(huán)

(11)字典(dict)

(12)集合(set)(不常用)

(14)pass,del,exec,eval

(15)內(nèi)建函數(shù)

Python進(jìn)階語(yǔ)法:

(1)文件

(2)錯(cuò)誤和異常

(3)模塊和包

(4)作用域

(5)高階函數(shù)

(6)裝飾器

(7)參數(shù)

(8)面向?qū)ο?/strong>

(9)定制類(魔術(shù)方法)

(10)日期和時(shí)間

(11)數(shù)學(xué)與隨機(jī)數(shù)

(12)正則表達(dá)式

?

?

?

Python基礎(chǔ)語(yǔ)法:

(1)打印出hello world

# -*- coding: utf-8 -*- print "hello world" print "你好 世界"

(2)注釋

1(單行注釋)以?#?開(kāi)頭,后面的文字直到行尾都算注釋 2、(多行注釋)多行注釋是用三引號(hào)'''?? '''包含的(單引號(hào)和雙引號(hào)均可) 3、(中文注釋)要注釋中文必須程序開(kāi)頭先寫(xiě)上# -*- coding: utf-8 -*-,不然會(huì)報(bào)錯(cuò)

?

(3)數(shù)據(jù)類型

1、變量不需要聲明,可以直接輸入,大小寫(xiě)敏感 2、這里的var = xxxx不叫變量賦值,而叫變量綁定,一個(gè)符號(hào)可以綁定任意類型的值。 3內(nèi)置函數(shù)type(), 用以查詢變量的類型 var = 1 print var #1 print type(var) #整數(shù)類型 # <type 'int'> var = 1.1 print var # 1.1 print type(var) #浮點(diǎn)數(shù)類型 # <type 'float'> var = 'hello' print var # hello print type(var) #字符串 # <type 'str'> var = (1==1) print var # True print type(var) #布爾型 # <type 'bool'> var = None print var # None print type(var) #空值 # <type 'NoneType'> var = 1+1j 或者complex(a,b)表示, 復(fù)數(shù)的實(shí)部a和虛部b都是浮點(diǎn)型 print var # (1+1j) print type(var) #復(fù)數(shù)類型 # <type 'complex'> 4字符串以''或" "括起來(lái)的任意文本 5、布爾型(True, False,可以用and, or, not運(yùn)算,而不是C語(yǔ)言的&&和||) 6、多變量賦值 a = b = c = 1 a, b, c = 1, 2, "john" #等號(hào)兩邊都是元組,建議加上括號(hào),增加可讀性 x,y = y,x #兩值交換,不需要temp,更加簡(jiǎn)潔 ?7、賦值語(yǔ)句不可以返回值,對(duì)象是通過(guò)引用傳遞的 y = (x = x + 1) #這是非法的

(4)運(yùn)算

1、加、減、乘、除、求余、乘方 2、乘方? ** 右結(jié)合 2**3=8 2**2**3=256 (2**2)**3=64 3、整數(shù)運(yùn)算結(jié)果仍然是整數(shù),浮點(diǎn)數(shù)運(yùn)算結(jié)果仍然是浮點(diǎn)數(shù)。 但是整數(shù)和浮點(diǎn)數(shù)混合運(yùn)算的結(jié)果就變成浮點(diǎn)數(shù)了。 4、字符串與整數(shù)相乘 print 'abc' * 3? 結(jié)果 abcabcabc 5、因?yàn)镻ython把0、空字符串''和None看成?False,其他數(shù)值和非空字符串都看成?True True and 'a=T' 計(jì)算結(jié)果是 'a=T' 繼續(xù)計(jì)算 'a=T' or 'a=F' 計(jì)算結(jié)果還是 'a=T' 要解釋上述結(jié)果,又涉及到 and 和 or 運(yùn)算的一條重要法則:短路計(jì)算 在計(jì)算?a and b?時(shí),如果 a 是 False,則根據(jù)與運(yùn)算法則,整個(gè)結(jié)果必定為 False,因此返回 a;如果 a 是 True,則整個(gè)計(jì)算結(jié)果必定取決與 b,因此返回 b。 在計(jì)算?a or b?時(shí),如果 a 是 True,則根據(jù)或運(yùn)算法則,整個(gè)計(jì)算結(jié)果必定為 True,因此返回 a;如果 a 是 False,則整個(gè)計(jì)算結(jié)果必定取決于 b,因此返回 b。 所以Python解釋器在做布爾運(yùn)算時(shí),只要能提前確定計(jì)算結(jié)果,它就不會(huì)往后算了,直接返回結(jié)果。 6、不支持自加(i++)和自減(i--) 7、地板除(//)除法不管操作數(shù)何種數(shù)值類型,總是舍去小數(shù)部分,返回?cái)?shù)字序列中比真正的商小的最接近的數(shù)字。 print 5//3 #1 print 1.0//2.0 #0.0 print -1/2 #-1

(5)輸入

x = input() #1+2 print type(x) #<type 'int'> y = raw_input() #1+2 print type(y) # <type 'str'> 1、由此可見(jiàn), input() 在對(duì)待純數(shù)字輸入返回所輸入的數(shù)字的類型(int,float) raw_input()?將所有輸入作為字符串看待,返回字符串類型 為了避免類型發(fā)生錯(cuò)誤,一般情況下使用 raw_input() 來(lái)與用戶交互。 ?

(6)輸出

1、Python2 里面print可以直接接字符串或者運(yùn)算。 2、Python3 里面print變成了一個(gè)函數(shù),上面的寫(xiě)法不支持了,必須用一個(gè)括號(hào)括起來(lái),否則會(huì)報(bào)告語(yǔ)法錯(cuò)誤。 3、>>>是Python解釋器的提示符,不是代碼的一部分。 4、print語(yǔ)句也可以跟上多個(gè)字符串,用逗號(hào)“,”隔開(kāi),遇到逗號(hào)“,”會(huì)輸出一個(gè)空格: print '1+2=',1+2 #1+2= 3 5、多行輸出使用三個(gè)引號(hào)和使用換行符\n一致 print '''哈 哈 哈''' print "哈\n哈\n哈" # 輸出結(jié)果 # 哈 # 哈 # 哈 # 哈 # 哈 # 哈 6、轉(zhuǎn)義 print r'C:\log.txt' print 'C:\\log.txt' # C:\log.txt # C:\log.txt 7print 語(yǔ)句與字符串格式運(yùn)算符( % )結(jié)合使用,可實(shí)現(xiàn)字符串替換功能 print "%s is number %d!" % ("Python", 1) %s表示由一個(gè)字符串來(lái)替換,%d表示由一個(gè)整數(shù)來(lái)替換,%f表示由一個(gè)浮點(diǎn)數(shù)來(lái)替換。 Python 非常靈活,即使將數(shù)字傳遞給 %s,也不會(huì)像其他要求嚴(yán)格的語(yǔ)言一樣引發(fā)嚴(yán)重后果。 ?

(7)序列

1、序列有兩種: list (可變列表) 和tuple(不可變?cè)M) 2、定義:序列是一組有順序的元素的集合,可以包含一個(gè)或多個(gè)元素,也可以沒(méi)有任何元素。 list = [0,1,2,3,4,5] #列表用中括號(hào),可改變,理解為數(shù)組 tuple = (0,1,2,3,4,5) #元祖用小括號(hào),不可改變 由于Python是動(dòng)態(tài)語(yǔ)言,所以list中包含的元素并不要求都必須是同一種數(shù)據(jù)類型 2、序列的通用操作 seq = "0123456789" print seq[0] #序列元素的下標(biāo)從0開(kāi)始。注意不要越界 print seq[-1] #倒序索引,-1代表倒數(shù)第一。 print seq[1:5] #支持切片操作,seq[start:end],start包含在結(jié)果中,end不包含在結(jié)果中。 print range(1,101)[0:10]#從第1個(gè)數(shù)元素開(kāi)始取,到第11元素結(jié)束 print seq[7:] #seq[start:end]中的end可以省略。 print seq[-3:] #分片也支持負(fù)數(shù)。 print seq[:3] #seq[start:end]中的start也可以省略。 print seq[:] #全部省略會(huì)復(fù)制整個(gè)序列。 print seq[::2] #支持步長(zhǎng)。 print seq[::-1] #逆序輸出。 print seq[9:1:-1] #支持負(fù)步長(zhǎng)。 print range(1,101)[2::3]#從第三元素開(kāi)始取,每隔2個(gè)取一個(gè)元素,即3的倍數(shù) print range(1,101)[4:50:5]#從第五個(gè)取,每隔4個(gè)取一個(gè),50以內(nèi)5的倍數(shù) print [1, 2, 3] + [4, 5, 6] # 序列支持相加,這解釋了為啥字符串可以相加。 print [1, 2, 3] * 3 #序列支持相乘,這解釋了為啥字符串可以相稱。 print [None] * 10 #生成一個(gè)空序列。 print 1 in [1, 2, 3] #成員判斷。 print range(1,101)[4::5][-10:] #切片可以嵌套,最后10個(gè)5的倍數(shù),先獲得5的倍數(shù)再取后10個(gè) 記住倒數(shù)第一個(gè)元素的索引是-1。倒序切片包含起始索引,不包含結(jié)束索引。 3、可變的列表(list) list = [0,1,2,3,4,5] list.append(7) #append()總是把新元素添加到list的尾部 print list # [0, 1, 2, 3, 4, 5, 7] list.insert(0,-1) #insert()接受兩個(gè)參數(shù),第一個(gè)是索引,第二個(gè)是元素 print list # [-1, 0, 1, 2, 3, 4, 5, 7] list.insert(-1,6) #insert(-1)是最后一個(gè)元素之前,即倒數(shù)第二個(gè)元素,因?yàn)閕nsert()前插 print list # [-1, 0, 1, 2, 3, 4, 5, 6, 7] list.pop() #pop()方法總是刪掉最后一個(gè)元素 print list # [-1, 0, 1, 2, 3, 4, 5, 6] list.pop(0) #參數(shù)為索引 print list # [0, 1, 2, 3, 4, 5, 6] list[6]=7 #對(duì)list中的某一個(gè)索引賦值,就可以直接用新的元素替換掉原來(lái)的元素 print list # [0, 1, 2, 3, 4, 5, 7] list[0],list[-1]=list[-1],list[0] #第一與最后位置調(diào)換 print list # [7, 1, 2, 3, 4, 5, 0] 在使用可變對(duì)象的方法如 sort(),extend()和 reverse()的時(shí)候要注意,這些操作會(huì)在列表
中原地執(zhí)行操作,也就是說(shuō)現(xiàn)有的列表內(nèi)容會(huì)被改變,但是
沒(méi)有返回值! 4、不可變的元組(tuple) 字符串是一種特殊的元組 沒(méi)有 append()方法,也沒(méi)有insert()和pop()方法,也不能賦值 Tuple list 操作速度快.如果您定義了一個(gè)值的常量集,并且唯一要用它做的是不斷地遍歷它,請(qǐng)使用 tuple 代替 list.如月份,星期。 print (1,) #一個(gè)元素的元祖。 因?yàn)?span lang="en-us">()既可以表示tuple,又可以作為括號(hào)表示運(yùn)算時(shí)的優(yōu)先級(jí),結(jié)果 (1) 被Python解釋器計(jì)算出結(jié)果 1,導(dǎo)致我們得到的不是tuple,而是整數(shù) 1。正是因?yàn)橛?span lang="en-us">()定義單元素的tuple有歧義,所以 Python 規(guī)定,單元素 tuple 要多加一個(gè)逗號(hào)“,”,這樣就避免了歧義。 可變的元組:tuple的元素指向list,而list內(nèi)的值可變 5、序列解包 x, y, z = 1, 2, 3 print x, y, z (x, y, z) = (1, 2, 3) print x, y, z (x, y, z) = [1, 2, 3] print x, y, z

(8)相等比較

#== 和 is的差別,==比較的是值,is比較的是引用。 x = [1, 2, 3] y = x z = [1, 2, 3] print(x == y) #True print(x == z) #True print(x is y) #True print(x is z) #False

(9)選擇

1、Python代碼的縮進(jìn)規(guī)則。具有相同縮進(jìn)的代碼被視為代碼塊 2、縮進(jìn)請(qǐng)嚴(yán)格按照Python的習(xí)慣寫(xiě)法:4個(gè)空格,不要使用Tab,更不要混合Tab和空格 3、格式 if 條件1:statement elif 條件2:statement elif 條件3:statement else:statement ? If后面不需要括號(hào),但是條件后面需要冒號(hào) ???elif else if 4、三元運(yùn)算符 x, y = 4, 3 if x < y:result = x else:result = y print result #等價(jià)于 result = x if x < y else y print result

(10)循環(huán)

1、for循環(huán)依次把list或tuple的每個(gè)元素迭代出來(lái) 格式 for 元素 in 序列: statement name 這個(gè)變量是在 for 循環(huán)中定義的,意思是,依次取出list中的每一個(gè)元素,并把元素賦值給 name,然后執(zhí)行for循環(huán)體(就是縮進(jìn)的代碼塊) L = ['Adam', 'Lisa', 'Bart'] for name in L:print name 這樣一來(lái),遍歷一個(gè)list或tuple就非常容易了。 2while循環(huán),不會(huì)迭代 list 或 tuple 的元素,而是根據(jù)表達(dá)式判斷循環(huán)是否結(jié)束。 while 條件:statement 3、中斷循環(huán) break和continue 4range()的用法 range(1,5) #代表從1到5(不包含5)?? [1, 2, 3, 4] range(1,5,2) #代表從1到5,間隔2(不包含5)?? [1, 3] range(5) #代表從0到5(不包含5)?? [0, 1, 2, 3, 4] 5Python中,迭代永遠(yuǎn)是取出元素本身,而非元素的索引。 對(duì)于有序集合,元素確實(shí)是有索引的。使用enumerate() 函數(shù)拿到索引 L = ['Adam', 'Lisa', 'Bart', 'Paul'] for index, name in enumerate(L):print index, '-', name #結(jié)果 # 0 - Adam # 1 - Lisa # 2 - Bart # 3 - Paul 使用 enumerate() 函數(shù),我們可以在for循環(huán)中同時(shí)綁定索引index和元素name。但是,這不是 enumerate() 的特殊語(yǔ)法。實(shí)際上,enumerate() 函數(shù)把: ['Adam', 'Lisa', 'Bart', 'Paul'] 變成了類似: [(0, 'Adam'), (1, 'Lisa'), (2, 'Bart'), (3, 'Paul')] 因此,迭代的每一個(gè)元素實(shí)際上是一個(gè)tuple: 6、好用的zip()方法 for x, y in zip(range(1, 10), range(1, 10)):print(x, y) # 結(jié)果 # (1, 1) # (2, 2) # (3, 3) # (4, 4) # (5, 5) # (6, 6) # (7, 7) # (8, 8) # (9, 9) 7、列表生成式,非常簡(jiǎn)潔 要生成[1x1, 2x2, 3x3, ..., 10x10] print [x * x for x in range(1, 11)] #[1, 4, 9, 16, 25, 36, 49, 64, 81, 100] 列表生成式的?for 循環(huán)后面還可以加上 if 判斷。例如:
print [x * x for x in range(1, 11) if x % 2 == 0] # [4, 16, 36, 64, 100] 8、迭代器 它為類序列對(duì)象提供了一個(gè)類序列的接口。 迭代非序列集合(例如映射和文件)時(shí), 可以創(chuàng)建更簡(jiǎn)潔可讀的代碼。 myTuple = (123, 'xyz', 45.67) i = iter(myTuple) print i.next() #123 print i.next() #xyz print i.next() #45.67 i.next() #報(bào)錯(cuò)

(11)字典(dict)

1、字典的元素沒(méi)有順序。你不能通過(guò)下標(biāo)引用元素。字典是通過(guò)鍵來(lái)引用,用大括號(hào) 查找速度快,無(wú)論dict有10個(gè)元素還是10萬(wàn)個(gè)元素,查找速度都一樣。而list的查找速度隨著元素增加而逐漸下降。 dict的缺點(diǎn)是占用內(nèi)存大,還會(huì)浪費(fèi)很多內(nèi)容 dict是按 key 查找,所以,在一個(gè)dict中,key不能重復(fù) 作為 key 的元素必須不可變 2、已知兩個(gè)列表,一個(gè)是名字,一個(gè)是成績(jī),要根據(jù)名字找到對(duì)應(yīng)的成績(jī)用兩個(gè)list不方便,如果把名字和分?jǐn)?shù)關(guān)聯(lián)起來(lái),組成類似的查找表,即 Python中的dict 用?dict?表示“名字”-“成績(jī)”的查找表如下: dic = {'tom':11, 'sam':57,'lily':100} print type(dic) #<type 'dict'>d = {'Adam': 95,'Lisa': 85,'Bart': 59 } print d #{'Lisa': 85, 'Adam': 95, 'Bart': 59} 3、我們把名字稱為key,對(duì)應(yīng)的成績(jī)稱為value,dict就是通過(guò)?key?來(lái)查找?value。 4、花括號(hào)?{}?表示這是一個(gè)dict,然后按照?key: value, 寫(xiě)出來(lái)即可。最后一個(gè) key: value 的逗號(hào)可以省略。 5、由于dict也是集合,len()函數(shù)可以計(jì)算任意集合的大小: print len(d) #運(yùn)算結(jié)果為3 一個(gè) key-value 算一個(gè),因此,dict大小為3。 6、可以簡(jiǎn)單地使用?d[key]?的形式來(lái)查找對(duì)應(yīng)的 value,這和 list 很像,不同之處是,list 必須使用索引返回對(duì)應(yīng)的元素,而dict使用key: print d['Adam'] #95 注意:?通過(guò) key 訪問(wèn) dict 的value,只要 key 存在,dict就返回對(duì)應(yīng)的value。如果key不存在,會(huì)直接報(bào)錯(cuò):KeyError。 要避免 KeyError 發(fā)生,有兩個(gè)辦法:

一是先判斷一下 key 是否存在,用 in 操作符: 二是使用dict本身提供的一個(gè) get 方法,在Key不存在的時(shí)候,返回None:

?

print d.get('Bart') #59 print d.get('Paul') #None 7、在字典中增添一個(gè)新元素的方法: d = {'Adam': 95,'Lisa': 85,'Bart': 59 } print d #{'Lisa': 85, 'Adam': 95, 'Bart': 59} d['lilei'] = 99 print d #{'lilei': 99, 'Lisa': 85, 'Adam': 95, 'Bart': 59} 8、循環(huán)調(diào)用 for key in d: #或for key in d.keys()print d[key] # 結(jié)果 # 99 # 85 # 95 # 59 9、字典的常用方法 print d.keys()????????? # 返回d所有的鍵 print d.values()???????? # 返回d所有的值 print d.items()?????????# 返回d所有的元素(鍵值對(duì)) d.clear()????????????# 清空d,dict變?yōu)?span lang="en-us">{} del d[‘xxx’]??????????? ???????# 刪除 d 的‘xxx’元素 for key, value in d.items():print key, ':', value 10、cmp()比較 (1)先比較字典長(zhǎng)度 (2)再比較字典的鍵 (3)最后比較字典的值 (4)都一樣就相等 ?

(12)集合(set)(不常用)

1、dict的作用是建立一組 key 和一組 value 的映射關(guān)系,dict的key是不能重復(fù)的。 有的時(shí)候,我們只想要 dict 的 key,不關(guān)心 key 對(duì)應(yīng)的 value,目的就是保證這個(gè)集合的元素不會(huì)重復(fù),這時(shí),set就派上用場(chǎng)了。 2、set 持有一系列元素,這一點(diǎn)和 list 很像,但是set的元素沒(méi)有重復(fù),而且是無(wú)序的,這點(diǎn)和 dict 的 key很像。 3、創(chuàng)建 set 的方式是調(diào)用 set() 并傳入一個(gè) list,list的元素將作為set的元素: s = set(['A', 'B', 'C']) print s #set(['A', 'C', 'B']) 4、添加、刪除: s.add('D') print s #set(['A', 'C', 'B', 'D']) s.add('D') #已存在不會(huì)報(bào)錯(cuò) s.remove('D') print s #set(['A', 'C', 'B']) s.remove('D') #報(bào)錯(cuò),需要先判斷

?

(13)函數(shù)

1、定義一個(gè)函數(shù)要使用?def?語(yǔ)句,依次寫(xiě)出函數(shù)名、括號(hào)、括號(hào)中的參數(shù)和冒號(hào):,然后,在縮進(jìn)塊中編寫(xiě)函數(shù)體,函數(shù)的返回值用?return?語(yǔ)句返回。 def say_b():print "b" say_b() #調(diào)用函數(shù),打印出b 2、如果沒(méi)有return語(yǔ)句,函數(shù)執(zhí)行完畢后也會(huì)返回結(jié)果,只是結(jié)果為 None。 3、函數(shù)返回多個(gè)值 import math def move(x, y, step, angle):nx = x + step * math.cos(angle)ny = y - step * math.sin(angle)return nx, ny x, y = move(100, 100, 60, math.pi / 6) print x, y #151.961524227 70.0 r = move(100, 100, 60, math.pi / 6) print r #(151.96152422706632, 70.0) 其實(shí)這只是一種假象,Python函數(shù)返回的仍然是單一值,是一個(gè)tuple: 但是,在語(yǔ)法上,返回一個(gè)tuple可以省略括號(hào),而多個(gè)變量可以同時(shí)接收一個(gè)tuple,按位置賦給對(duì)應(yīng)的值,所以,Python的函數(shù)返回多值其實(shí)就是返回一個(gè)tuple,但寫(xiě)起來(lái)更方便。 4、在函數(shù)內(nèi)部,可以調(diào)用其他函數(shù)。如果一個(gè)函數(shù)在內(nèi)部調(diào)用自身本身,這個(gè)函數(shù)就是遞歸函數(shù)。 def fact(n):if n==1:return 1return n * fact(n - 1) print fact(10) #計(jì)算10的階乘 5、定義函數(shù)的時(shí)候,還可以有默認(rèn)參數(shù)。 def power(x, n=2):s = 1while n > 0:n = n - 1s = s * xreturn s print power(2) #默認(rèn)計(jì)算2的平方 print power(2,3) #計(jì)算2的三次方 由于函數(shù)的參數(shù)按從左到右的順序匹配,所以默認(rèn)參數(shù)只能定義在必需參數(shù)的后面: 6、一個(gè)函數(shù)能接受任意個(gè)參數(shù),我們就可以定義一個(gè)可變參數(shù): def fn(*args):print args fn('a') #('a',) fn('a', 'b') #('a', 'b') fn('a', 'b', 'c') #('a', 'b', 'c') 可變參數(shù)的名字前面有個(gè)?*?號(hào),我們可以傳入0個(gè)、1個(gè)或多個(gè)參數(shù)給可變參數(shù): 7、基本數(shù)據(jù)類型的參數(shù):值傳遞 表作為參數(shù):指針傳遞

?

(14)pass,del,exec,eval

1、pass語(yǔ)句 pass代表該語(yǔ)句什么都不做,因?yàn)閜ython中空代碼是非法的,比如一個(gè)if語(yǔ)句要求什么內(nèi)容都不做,我們就可以使用pass語(yǔ)句。 2、del語(yǔ)句 一般來(lái)說(shuō)python會(huì)刪除那些不在使用的對(duì)象(因?yàn)槭褂谜卟粫?huì)再通過(guò)任何變量或者數(shù)據(jù)結(jié)構(gòu)引用它們) 3、exec語(yǔ)句(運(yùn)行字符串中的程序) exec "print 'hello world'" #hello world 4eval函數(shù)(會(huì)計(jì)算python表達(dá)式(以字符串形式書(shū)寫(xiě)),并且返回結(jié)果) print eval('2+ 2') #4 print eval(raw_input("please input number:")) #輸入2+2 得4

??

(15)內(nèi)建函數(shù)

1cmp(obj1, obj2)?比較 obj1 和 obj2, 根據(jù)比較結(jié)果返回整數(shù) i:
? ? ?if obj1 < obj2?? 返回i < 0
? ? if obj1 > obj2?? 返回i > 0
? ? if obj1 == obj2? 返回i == 0

如果是用戶自定義對(duì)象, cmp()會(huì)調(diào)用該類的特殊方法__cmp__()

2str()?強(qiáng)制轉(zhuǎn)換成字符串

3type()?:詳見(jiàn)(3)數(shù)據(jù)類型 - 3、

4help():通過(guò)用函數(shù)名作為 help()的參數(shù)就能得到相應(yīng)的幫助信息

5isinstance(變量名,類型):?判斷是否是這個(gè)類型的元素,可以用if語(yǔ)句

6abs()取絕對(duì)值

7enumerate()詳見(jiàn)(10)循環(huán) - 5、

8len(seq):返回seq的長(zhǎng)度

9sorted(iter)排序,會(huì)調(diào)用cmp()

10zip(a1,a2……):詳見(jiàn)(10)循環(huán) - 6、

11range():詳見(jiàn)(10)循環(huán) - 4、

12string.lower()轉(zhuǎn)換字符串中所有大寫(xiě)字符為小寫(xiě)

13string.upper()轉(zhuǎn)換字符串中所有小寫(xiě)字符為大寫(xiě)

14string.strip()刪去字符串開(kāi)頭和結(jié)尾的空格

15string.capitalize()把字符串第一個(gè)字符大寫(xiě)

16string.title()所有單詞都以大寫(xiě)開(kāi)頭

17max()和min():找出最大和最小值

18sum()求和

19reversed():倒序輸出




?

?

?Python進(jìn)階語(yǔ)法:

(1)文件

1、文件也是一個(gè)對(duì)象。 2、打開(kāi)文件 f = open(文件名,模式) 文件名可以是相對(duì)路徑或者絕對(duì)路徑 模式有:"r" 只讀、“w” 寫(xiě)入、“a” 追加,“r+/w+”讀寫(xiě)

使用 'r' 或 'U' 模式打開(kāi)的文件必須是已經(jīng)存在的。 使用 'w' 模式打開(kāi)的文件若存在則首先清空, 然后(重新)創(chuàng)建。
'a' 模式打開(kāi)的文件是為追加數(shù)據(jù)作準(zhǔn)備的, 所有寫(xiě)入的數(shù)據(jù)都將追加到文件的末尾。 即使你 seek 到了其它的地方。 如果文件不存在, 將被自動(dòng)創(chuàng)建, 類似以 'w'模式打開(kāi)文件。 test = open("test.txt", "w") 3、屬性 test = open("test.txt", "w") print "文件名: ", test.name #文件名: test.txt print "是否已關(guān)閉 : ", test.closed #是否已關(guān)閉 : False print "訪問(wèn)模式 : ", test.mode #訪問(wèn)模式 : w 4、關(guān)閉 close() test = open("test.txt", "w") test.close() print "是否已關(guān)閉 : ", test.closed #是否已關(guān)閉 : True 5、寫(xiě)入write() write()方法可將任何字符串寫(xiě)入一個(gè)打開(kāi)的文件。 write()方法不在字符串的結(jié)尾不添加換行符('\n'): test = open("test.txt", "w") test.write("this is a test\n this is a test again \n") test.close() #可以在文件中看到 # this is a test # this is a test again 主動(dòng)調(diào)用close()寫(xiě)緩存同步到磁盤(pán),或者寫(xiě)入數(shù)據(jù)量大于或等于寫(xiě)緩存,寫(xiě)緩存同步到磁盤(pán) 6、讀取 read()、readline()、readlines() readsize)方法從一個(gè)打開(kāi)的文件中讀取一個(gè)字符串。size若不填則為盡量多的字符串,若填了則為結(jié)束位置。 readline()讀取當(dāng)前行,允許有參數(shù) readlines()讀取剩余行,返回一個(gè)字符串列表 test = open ("test.txt", "w") test.write("python is a language \npython is a great language ") test.close() test = open("test.txt", "r") str = test.read() print str test.close() #python is a language #python is a great language 7、文件位置 tell()方法告訴你文件內(nèi)的當(dāng)前位置;即下一次的讀寫(xiě)會(huì)發(fā)生在文件開(kāi)頭這么多字節(jié)之后: seekoffset [,from])方法改變當(dāng)前文件的位置。Offset變量表示要移動(dòng)的字節(jié)數(shù)。From變量指定開(kāi)始移動(dòng)字節(jié)的參考位置。如果from被設(shè)為0,這意味著將文件的開(kāi)頭作為移動(dòng)字節(jié)的參考位置。如果設(shè)為1,則使用當(dāng)前的位置作為參考位置。如果它被設(shè)為2,那么該文件的末尾將作為參考位置。
test = open ("test.txt", "w") test.write("python is a language \npython is a great language ") test.close() test = open("test.txt", "r") str = test.read() print "the first input:\n",str #輸出 # the first input: # python is a language # python is a great language # 查找當(dāng)前位置 position = test.tell() print position #50 # 把指針再次重新定位到文件開(kāi)頭 position = test.seek(0, 0) str2 = test.read(10) print "the second input:\n", str2 # the second input: # python is test.close() 8、重命名 Python的os模塊提供了幫你執(zhí)行文件處理操作的方法,必須先導(dǎo)入它,才可以調(diào)用。 os.rename(當(dāng)前文件名,新的文件名) 9、刪除文件 同樣需要導(dǎo)入os模塊,才可以調(diào)用。 os.remove(文件名)

?

(2)錯(cuò)誤和異常

1、錯(cuò)誤類型 OverflowError數(shù)值運(yùn)算超出最大限制 ZeroDivisionError 除(或取模)零 (所有數(shù)據(jù)類型) AttributeError對(duì)象沒(méi)有這個(gè)屬性 IOError 輸入/輸出操作失敗 IndexError? 序列中沒(méi)有此索引(index) NameError? 未聲明/初始化對(duì)象 (沒(méi)有屬性) SyntaxError Python 語(yǔ)法錯(cuò)誤 TypeError 對(duì)類型無(wú)效的操作 ValueError 傳入無(wú)效的參數(shù) 2、try-except處理異常 try-except語(yǔ)句用來(lái)檢測(cè)try語(yǔ)句塊中的錯(cuò)誤,從而讓except語(yǔ)句捕獲異常信息并處理。 try: <語(yǔ)句> #運(yùn)行別的代碼 except Exception1,e:#Exception是錯(cuò)誤類型名,e是儲(chǔ)存錯(cuò)誤,可以調(diào)用 <語(yǔ)句> #如果在try部份引發(fā)了'名字'異常 except Exception2,e: <語(yǔ)句> #如果引發(fā)了'名字'異常,獲得附加的數(shù)據(jù) else: <語(yǔ)句> #如果沒(méi)有異常發(fā)生 當(dāng)try后的語(yǔ)句執(zhí)行時(shí)發(fā)生異常,python就跳回到try并執(zhí)行第一個(gè)匹配該異常的except子句,異常處理完畢,控制流就通過(guò)整個(gè)try語(yǔ)句(除非在處理異常時(shí)又引發(fā)新的異常)。如果在try子句執(zhí)行時(shí)沒(méi)有發(fā)生異常,python將執(zhí)行else語(yǔ)句后的語(yǔ)句(如果有else的話),然后控制流通過(guò)整個(gè)try語(yǔ)句。 try:fh = open("testfile", "w")fh.write("This is my test file for exception handling!!") except IOError:print "Error: can\'t find file or read data" else:print "Written content in the file successfully" #Written content in the file successfullytry:fh = open("testfile", "r") #只讀文件不能寫(xiě)入fh.write("This is my test file for exception handling!!") except IOError,e:print "Error: can\'t find file or read data"print "catch error:",e else:print "Written content in the file successfully" #Error: can't find file or read data#atch error: File not open for writing except若不帶任何異常類型,即捕獲所有發(fā)生的異常。但是不能捕獲語(yǔ)法錯(cuò)誤異常,如if a,因?yàn)槭沁\(yùn)行前錯(cuò)誤而不是運(yùn)行時(shí)錯(cuò)誤 也可帶多種類型except(Exception1[, Exception2[,...ExceptionN]]]): 錯(cuò)誤類型后面跟著變量e,可以print錯(cuò)誤提示 案例如下 import random num = random.randint(0,100)while 1:try:guess = int(raw_input("Enter 1-100:"))except ValueError,e:print "error ! please enter 1-100"continueif guess > num:print "guess bigger:",guesselif guess < num:print "guess smaller:",guesselse:print "guess right,game over"break 3、try-finally語(yǔ)句 語(yǔ)句是否發(fā)生異常都將執(zhí)行最后的代碼。將異常保留下來(lái)交給系統(tǒng)處理,本身不處理異常。

作用:為處理異常事件提供清理機(jī)制,用來(lái)關(guān)閉文件或者釋放系統(tǒng)資源。

try: <語(yǔ)句> finally: <語(yǔ)句> #退出try時(shí)總會(huì)執(zhí)行 raise 可以使用except語(yǔ)句或者finally語(yǔ)句,但是兩者不能同時(shí)使用。else語(yǔ)句也不能與finally語(yǔ)句同時(shí)使用。 4try-except-finally? try語(yǔ)句沒(méi)有捕獲異常,執(zhí)行完try代碼段后,執(zhí)行finally try捕獲異常,首先執(zhí)行except處理異常,然后執(zhí)行finally 5try-except-else-finally try語(yǔ)句沒(méi)有捕獲異常,執(zhí)行完try代碼段后,執(zhí)行else代碼段,最后執(zhí)行finally try捕獲異常,首先執(zhí)行except處理錯(cuò)誤,然后執(zhí)行finally 6try-finally-except 當(dāng)在try塊中拋出一個(gè)異常,立即執(zhí)行finally塊代碼。 finally塊中的所有語(yǔ)句執(zhí)行后,異常被再次提出,并執(zhí)行except塊代碼。 7with語(yǔ)句 用來(lái)代替try-except-finally語(yǔ)句,使代碼更加簡(jiǎn)潔 with context[as var]:with_suite context表達(dá)式返回是一個(gè)對(duì)象 var用來(lái)保存context返回對(duì)象,單個(gè)返回值或元組 with_suite使用var變量對(duì)context返回對(duì)象進(jìn)行操作 with open("1.text") as f:for line in f.readline():print line 1、打開(kāi)1.txt文件 2f變量接收文件對(duì)象返回的對(duì)象 3with中的代碼執(zhí)行完成后,關(guān)閉文件 程序使用了上下文管理器 (with...as...)。上下文管理器有隸屬于它的程序塊。當(dāng)隸屬的程序塊執(zhí)行結(jié)束的時(shí)候(也就是不再縮進(jìn)),上下文管理器自動(dòng)關(guān)閉了文件 運(yùn)用情況:①文件操作 ②進(jìn)城之間互斥操作:例如互斥鎖? ③支持上下文的其他對(duì)象 8raise主動(dòng)拋出異常 #格式 rasie [exception[,args]] #Exception 異常類 #args 描述異常信息的元組 raise TypeError,"Test Error" #TypeError: Test Error 9assert語(yǔ)句 斷言語(yǔ)句:assert語(yǔ)句是用于檢測(cè)表達(dá)式是否為真,如果為假,引發(fā)AssertionError錯(cuò)誤 #格式 assert expression [,args] #expression 表達(dá)式 #args 判斷條件的描述信息 10、自定義異常 通過(guò)創(chuàng)建一個(gè)新的異常類,程序可以命名它們自己的異常。異常應(yīng)該是典型的繼承自Exception類,通過(guò)直接或間接的方式。 自定義異常只能主動(dòng)觸發(fā)。 class FileError(IOError):passtry:raise FileError,"test error" except FileError,e:print e #test error class CustomError(Exception):def __init__(self,info):Exception.__init__(self)self.errorinfo = infodef __str__(self):return "CustomError:%s" %self.errorinfotry:raise CustomError("test CustomError") except CustomError,e:print "ErrorInfo:",e #ErrorInfo: CustomError:test CustomError

?

(3)模塊和包

1、概念介紹

#test.py??自身模塊名test

import p1.util??引用p1包的模塊util

print p1.util.f(2)??調(diào)用p1.util的函數(shù)f()

如何區(qū)分包和普通目錄 包下面有個(gè)__inti__.py文件

2、如果我們只希望導(dǎo)入用到的math模塊的某幾個(gè)函數(shù),而不是所有函數(shù),可以用下面的語(yǔ)句:

from math import pow, sin, log

3、可以給函數(shù)起個(gè)“別名”來(lái)避免沖突:as

from math import log from logging import log as logger # logging的log現(xiàn)在變成了logger print log(10) # 調(diào)用的是math的log logger(10, 'import from logging') # 調(diào)用的是logging的log

4、如果導(dǎo)入的模塊不存在,Python解釋器會(huì)報(bào)?ImportError?錯(cuò)誤:

5、第三方模塊管理系統(tǒng)

-easy_install

-pip(推薦,已內(nèi)置到Python2.7.9)

?

(4)作用域

1、函數(shù)作用域LEGB?? L>E>G>B

L:local?函數(shù)內(nèi)部作用域

E:enclosing 函數(shù)內(nèi)部與內(nèi)嵌函數(shù)之間,即閉包

G:global全局作用域

B:bulid-in 內(nèi)置作用域 list,tuple之類

passline = 60 #全局 def func(val):passline = 90 #函數(shù)內(nèi)部if val >= passline:print "pass"else:print "failed"def in_func():print val #函數(shù)內(nèi)部與內(nèi)嵌函數(shù)之間in_func() func(69) #failed #69

?

(5)高階函數(shù)

1、由于參數(shù) x, y和 f 都可以任意傳入,如果 f 傳入其他函數(shù),就可以得到不同的返回值。

def add(x, y, f):return f(x) + f(y) print add(-5, 9, abs) #abs(-5) + abs(9) = 14

2、map() 映射

map()是 Python 內(nèi)置的高階函數(shù),它接收一個(gè)函數(shù)f和一個(gè)list,并通過(guò)把函數(shù)f依次作用在 list的每個(gè)元素上,得到一個(gè)新的 list 并返回。

def f(x):return x*x print map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9]) #[1, 4, 9, 16, 25, 36, 49, 64, 81]

利用map()函數(shù),可以把一個(gè) list 轉(zhuǎn)換為另一個(gè) list,只需要傳入轉(zhuǎn)換函數(shù)。

由于list包含的元素可以是任何類型,因此,map()不僅僅可以處理只包含數(shù)值的 list,事實(shí)上它可以處理包含任意類型的 list,只要傳入的函數(shù)f可以處理這種數(shù)據(jù)類型。

3、reduce()折疊

reduce()函數(shù)接收的參數(shù)和 map()類似,一個(gè)函數(shù)f,一個(gè)list,但reduce()傳入的函數(shù)f必須接收兩個(gè)參數(shù),reduce()對(duì)list的每個(gè)元素反復(fù)調(diào)用函數(shù)f,并返回最終結(jié)果值。

def f(x, y):return x + y print reduce(f, [1, 3, 5, 7, 9]) #25 #先計(jì)算頭兩個(gè)元素:f(1, 3),結(jié)果為4; #再把結(jié)果和第3個(gè)元素計(jì)算:f(4, 5),結(jié)果為9; #再把結(jié)果和第4個(gè)元素計(jì)算:f(9, 7),結(jié)果為16; #再把結(jié)果和第5個(gè)元素計(jì)算:f(16, 9),結(jié)果為25; #由于沒(méi)有更多的元素了,計(jì)算結(jié)束,返回結(jié)果25。 #初始值100 print reduce(f, [1, 3, 5, 7, 9], 100) #125

reduce()還可以接收第3個(gè)可選參數(shù),作為計(jì)算的初始值。

4、filter()?過(guò)濾

filter()函數(shù)接收一個(gè)函數(shù)f和一個(gè)list,這個(gè)函數(shù)?f?的作用是對(duì)每個(gè)元素進(jìn)行判斷,返回 True或 False,filter()根據(jù)判斷結(jié)果自動(dòng)過(guò)濾掉不符合條件的元素,返回由符合條件元素組成的新list。

def is_odd(x): #是奇數(shù)return x % 2 == 1 print filter(is_odd, [1, 4, 6, 7, 9, 12, 17]) #[1, 7, 9, 17]

利用filter(),可以完成很多有用的功能,例如,刪除 None 或者空字符串

def is_not_empty(s):return s and len(s.strip()) > 0 print filter(is_not_empty, ['test', None, '', 'str', ' ', 'END']) #['test', 'str', 'END']

5、sorted():對(duì)list進(jìn)行排序

print sorted([36, 5, 12, 9, 21]) #[5, 9, 12, 21, 36]

但sorted()也是一個(gè)高階函數(shù),它可以接收一個(gè)比較函數(shù)來(lái)實(shí)現(xiàn)自定義排序,比較函數(shù)的定義是,傳入兩個(gè)待比較的元素x, y,如果x應(yīng)該排在y的前面,返回-1,如果x應(yīng)該排在y的后面,返回1。如果x和y相等,返回0。

#倒序排序 def reversed_cmp(x, y):if x > y:return -1if x < y:return 1return 0 print sorted([36, 5, 12, 9, 21], reversed_cmp) #[36, 21, 12, 9, 5]

6、Python的函數(shù)不但可以返回int、str、list、dict等數(shù)據(jù)類型,還可以返回函數(shù)

def f():print 'call f()...'# 定義函數(shù)g:def g():print 'call g()...'# 返回函數(shù)g:return gx = f() # 調(diào)用f() call f()... x # 變量x是f()返回的函數(shù): #<function g at 0x00000000022CDA58> x() # x指向函數(shù),因此可以調(diào)用 call g()... x=f(),x()=g()

請(qǐng)注意區(qū)分返回函數(shù)和返回值:

def myabs():return abs # 返回函數(shù) def myabs2(x):return abs(x) # 返回函數(shù)調(diào)用的結(jié)果,返回值是一個(gè)數(shù)值

在函數(shù)內(nèi)部定義的函數(shù)和外部定義的函數(shù)是一樣的,只是他們無(wú)法被外部訪問(wèn):

7、閉包(closure)

內(nèi)部函數(shù)中引用了外層函數(shù)的變量(enclosing作用域的變量),然后返回內(nèi)層函數(shù)的情況。

閉包的作用是封裝和代碼復(fù)用。

傳遞的是參數(shù)

#如果要實(shí)現(xiàn)兩個(gè)功能,可以定義兩個(gè)函數(shù)。 def func_150(val):passline = 90 #150if val >= passline:print ("pass")else:print "failed"def func_100(val):passline = 60 #150if val >= passline:print ("pass")else:print "failed"func_100(69)#pass func_150(69)#failed#如果用閉包的話只需要定義一個(gè)函數(shù) def set_passline(passline):#passlinedef cmp(val):if val >= passline:print "pass"else:print "failed"return cmp #返回值是一個(gè)函數(shù)f_100 = set_passline(60) #f_100就是cmp,f_100()就是cmp(),而且內(nèi)置一個(gè)passline=60 f_150 = set_passline(90)f_100(69)#pass f_150(69)#failed

傳遞的是函數(shù)

#不用閉包 def my_sum(*arg):if len(arg)==0:return 0for val in arg:if not isinstance(val,int):return 0return sum(arg)def my_average(*arg):if len(arg)==0:return 0for val in arg:if not isinstance(val,int):return 0return sum(arg)/len(arg)print my_sum(1,2,3,4,5) #15 print my_sum(1,2,3,4,5,'6')#0 print my_average(1,2,3,4,5)#3 print my_average()#0#使用閉包 def my_sum(*arg):print "in my_sum"return sum(arg)def my_average(*arg): return sum(arg)/len(arg)def dec(func):def in_dec(*arg):print "in_dec()=",argif len(arg) == 0:return 0for val in arg:if not isinstance(val, int):return 0return func(*arg)return in_dec #別加括號(hào) #dec return in_dec -> my_sum #my_sum = in_dec(*arg) my_sum = dec(my_sum) my_average = dec(my_average)#同理print my_sum(1,2,3,4,5) print my_sum(1,2,3,4,5,'6')# 結(jié)果 # in_dec()= (1, 2, 3, 4, 5) # in my_sum # 15 # in_dec()= (1, 2, 3, 4, 5, '6') # 0

正確使用閉包,就要確保引用的局部變量在函數(shù)返回后不能變。

返回函數(shù)不要引用任何循環(huán)變量,或者后續(xù)會(huì)發(fā)生變化的變量。

# 希望一次返回3個(gè)函數(shù),分別計(jì)算1x1,2x2,3x3: def count():fs = []for i in range(1, 4):def f():return i*ifs.append(f)return fs f1, f2, f3 = count() print f1(),f2(),f3() #9 9 9 #當(dāng)count()函數(shù)返回了3個(gè)函數(shù)時(shí),這3個(gè)函數(shù)所引用的變量 i 的值已經(jīng)變成了3。由于f1、f2、f3并沒(méi)有被調(diào)用,所以,此時(shí)他們并未計(jì)算 i*i,當(dāng) f1 被調(diào)用時(shí),才計(jì)算i*i,但現(xiàn)在i的值已經(jīng)變?yōu)?#正確如下 def count():fs = []for i in range(1, 4):def f(j):def g():return j*jreturn gr = f(i)fs.append(r)return fs f1, f2, f3 = count() print f1(), f2(), f3() #1 4 9

8、匿名函數(shù)lambda

def f(x):return x*x print map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9]) #[1, 4, 9, 16, 25, 36, 49, 64, 81]print map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9]) #[1, 4, 9, 16, 25, 36, 49, 64, 81]

通過(guò)對(duì)比可以看出,匿名函數(shù)?lambda x: x * x?實(shí)際上就是:

def f(x):

??? return x * x

關(guān)鍵字lambda表示匿名函數(shù),冒號(hào)前面的x 表示函數(shù)參數(shù)。

匿名函數(shù)有個(gè)限制,就是只能有一個(gè)表達(dá)式,不寫(xiě)return,返回值就是該表達(dá)式的結(jié)果。

使用匿名函數(shù),可以不必定義函數(shù)名,直接創(chuàng)建一個(gè)函數(shù)對(duì)象,很多時(shí)候可以簡(jiǎn)化代碼:

print sorted([1, 3, 9, 5, 0], lambda x,y: -cmp(x,y)) #[9, 5, 3, 1, 0]

返回函數(shù)的時(shí)候,也可以返回匿名函數(shù):

myabs = lambda x: -x if x < 0 else x print myabs(-1) #1 print myabs(1) #1

?

(6)裝飾器

1、decorator本質(zhì)上就是一個(gè)高階函數(shù),它接收一個(gè)函數(shù)作為參數(shù),然后,返回一個(gè)新函數(shù)。

使用 decorator 用Python提供的@語(yǔ)法,這樣可以避免手動(dòng)編寫(xiě)f=decorate(f)這樣的代碼。

2、裝飾器用來(lái)裝飾函數(shù),返回一個(gè)函數(shù)對(duì)象

被裝飾函數(shù)標(biāo)識(shí)符指向返回的函數(shù)對(duì)象? ?

def dec(func):print "call dec"def in_dec(*arg):print "in_dec()=",argif len(arg) == 0:return 0for val in arg:if not isinstance(val, int):return 0return func(*arg)return in_dec #別加括號(hào)@dec # 代替了my_sum = dec(my_sum) def my_sum(*arg): #my_sum = in_decprint "in my_sum"return sum(arg)print my_sum(1,2,3,4,5)# call dec # in_dec()= (1, 2, 3, 4, 5) # in my_sum # 15

3、傳入函數(shù),含有兩個(gè)參數(shù)

def deco(func):def in_deco(x,y):print "in deco"func(x,y)print "call deco"return in_deco@deco #代替 bar = deco(bar) = in_deco #bar()-> in_deco()->bar() def bar(x,y):print "in bar",x+ybar(1,2)# call deco # in deco # in bar

4、@log的定義

def log(f):def fn(x):print 'call ' + f.__name__ + '()...'return f(x)return fn@log def factorial(n):return reduce(lambda x,y: x*y, range(1, n+1)) print factorial(10) # call factorial()... # 3628800

但是,對(duì)于參數(shù)不是一個(gè)的函數(shù),調(diào)用將報(bào)錯(cuò)。@log寫(xiě)死了只含一個(gè)參數(shù)的返回函數(shù)。

5、要讓@log自適應(yīng)任何參數(shù)定義的函數(shù),可以利用Python的*args和**kw,保證任意個(gè)數(shù)的參數(shù)總是能正常調(diào)用:

可變參數(shù)*args表示任何多個(gè)無(wú)名參數(shù),它是一個(gè)tuple;**kwargs表示關(guān)鍵字參數(shù),它是一個(gè)dict。并且同時(shí)使用*args和**kwargs時(shí),必須*args參數(shù)列要在**kwargs前。

def log(f):def fn(*args, **kw):print 'call ' + f.__name__ + '()...'return f(*args, **kw)return fn@log def add(x, y):return x + y print add(1, 2) # call add()... # 3

6、@performance,它可以打印出函數(shù)調(diào)用的時(shí)間。

計(jì)算函數(shù)調(diào)用的時(shí)間可以記錄調(diào)用前后的當(dāng)前時(shí)間戳,然后計(jì)算兩個(gè)時(shí)間戳的差。

import time def performance(f):def fn(*args, **kw):t1 = time.time()r = f(*args, **kw)t2 = time.time()print 'call %s() in %fs' % (f.__name__, (t2 - t1))return rreturn fn@performance def factorial(n):return reduce(lambda x,y: x*y, range(1, n+1)) print factorial(5) # call factorial() in 0.000000s # 120

7、對(duì)于被裝飾的函數(shù),log打印的語(yǔ)句是不能變的(除了函數(shù)名)。

如果有的函數(shù)非常重要,希望打印出'[INFO] call xxx()...',有的函數(shù)不太重要,希望打印出'[DEBUG] call xxx()...',這時(shí),log函數(shù)本身就需要傳入'INFO'或'DEBUG'這樣的參數(shù):

@log('DEBUG') def my_func():pass #把上面的定義翻譯成高階函數(shù)的調(diào)用,就是: my_func = log('DEBUG')(my_func) #上面的語(yǔ)句看上去還是比較繞,再展開(kāi)一下: log_decorator = log('DEBUG') my_func = log_decorator(my_func) #上面的語(yǔ)句又相當(dāng)于: log_decorator = log('DEBUG') @log_decorator def my_func():pass

所以,帶參數(shù)的log函數(shù)首先返回一個(gè)decorator函數(shù),再讓這個(gè)decorator函數(shù)接收my_func并返回新函數(shù):

而且wrapper(*args, **kw)要調(diào)用外層參數(shù)prefix,所以無(wú)法拆開(kāi)

def log(prefix):def log_decorator(f):def wrapper(*args, **kw):print '[%s] %s()...' % (prefix, f.__name__)return f(*args, **kw)return wrapperreturn log_decorator@log('DEBUG') def test():pass print test()# [DEBUG] test()... # None

8、區(qū)別

#在沒(méi)有decorator的情況下,打印函數(shù)名: def f1(x):pass print f1.__name__ #f1#有decorator的情況下,再打印函數(shù)名: def log(f):def wrapper(*args, **kw):print 'call...'return f(*args, **kw)return wrapper @log def f2(x):pass print f2.__name__ #wrapper

可見(jiàn),由于decorator返回的新函數(shù)函數(shù)名已經(jīng)不是'f2',而是@log內(nèi)部定義的'wrapper'。這對(duì)于那些依賴函數(shù)名的代碼就會(huì)失效。decorator還改變了函數(shù)的__doc__等其它屬性。如果要讓調(diào)用者看不出一個(gè)函數(shù)經(jīng)過(guò)了@decorator的“改造”,就需要把原函數(shù)的一些屬性復(fù)制到新函數(shù)中:

def log(f):def wrapper(*args, **kw):print 'call...'return f(*args, **kw)wrapper.__name__ = f.__name__wrapper.__doc__ = f.__doc__return wrapper

這樣寫(xiě)decorator很不方便,因?yàn)槲覀円埠茈y把原函數(shù)的所有必要屬性都一個(gè)一個(gè)復(fù)制到新函數(shù)上,所以Python內(nèi)置的functools可以用來(lái)自動(dòng)化完成這個(gè)“復(fù)制”的任務(wù):

import functools def log(f):@functools.wraps(f) def wrapper(*args, **kw):print 'call...'return f(*args, **kw)return wrapper @log def f2(x):pass print f2.__name__ #f2

9、當(dāng)一個(gè)函數(shù)有很多參數(shù)時(shí),調(diào)用者就需要提供多個(gè)參數(shù)。如果減少參數(shù)個(gè)數(shù),就可以簡(jiǎn)化調(diào)用者的負(fù)擔(dān)。

比如,int()函數(shù)可以把字符串轉(zhuǎn)換為整數(shù),當(dāng)僅傳入字符串時(shí),int()函數(shù)默認(rèn)按十進(jìn)制轉(zhuǎn)換:

但int()函數(shù)也提供額外的base參數(shù),默認(rèn)為10。如果傳入base參數(shù),就可以做N進(jìn)制轉(zhuǎn)換:

print int("10") #10 print int('10', 8) #8 print int('A', 16) #10

假設(shè)要轉(zhuǎn)換大量的二進(jìn)制字符串,每次都傳入int(x, base=2)非常麻煩,于是,我們想到,可以定義一個(gè)int2()的函數(shù),默認(rèn)把base=2傳進(jìn)去:

def int2(x, base=2):return int(x, base)print int2('1000000') #64 print int2('1010101') #85

functools.partial就是幫助我們創(chuàng)建一個(gè)偏函數(shù)的,不需要我們自己定義int2(),可以直接使用下面的代碼創(chuàng)建一個(gè)新的函數(shù)int2:

import functools int2 = functools.partial(int, base=2)print int2('1000000') #64 print int2('1010101') #85

所以,functools.partial可以把一個(gè)參數(shù)多的函數(shù)變成一個(gè)參數(shù)少的新函數(shù),少的參數(shù)需要在創(chuàng)建時(shí)指定默認(rèn)值,這樣,新函數(shù)調(diào)用的難度就降低了。

?

(7)參數(shù)

1位置參數(shù)必須以在被調(diào)用函數(shù)中定義的準(zhǔn)確順序來(lái)傳遞,參數(shù)數(shù)目必須一致。

2、所有必需的參數(shù)都要在默認(rèn)參數(shù)之前。

# 位置參數(shù) def func_with_parameters(x, y):print(x, y) func_with_parameters(1, 2)#默認(rèn)值參數(shù) def func_with_default_value_parameters(x, y, z = 3):print(x, y, z) func_with_default_value_parameters(y = 2, x = 1)

3、如果命名了參數(shù),這里可以不按順序給出參數(shù)。

#命名參數(shù) def func_with_named_parameters(x, y, z):print(x, y, z) func_with_named_parameters(z = 1, y = 2, x = 3)

4、變長(zhǎng)的參數(shù)在函數(shù)聲明中不是顯式命名的,因?yàn)?/strong>參數(shù)的數(shù)目在運(yùn)行時(shí)之前是未知的(甚至在運(yùn)行的期間,每次函數(shù)調(diào)用的參數(shù)的數(shù)目也可能是不同的),這和常規(guī)參數(shù)(位置和默認(rèn))明顯不同,常規(guī)參數(shù)都是在函數(shù)聲明中命名的。由于函數(shù)調(diào)用提供了關(guān)鍵字以及非關(guān)鍵字兩種參數(shù)類型,python 用兩種方法來(lái)支持變長(zhǎng)參數(shù)。

func(*tuple_grp_nonkw_args, **dict_grp_kw_args)

其中的?tuple_grp_nonkw_args?是以元組形式體現(xiàn)的非關(guān)鍵字參數(shù)組,?dict_grp_kw_args?是裝有關(guān)鍵字參數(shù)的字典

5、可變長(zhǎng)的參數(shù)元組必須在位置和默認(rèn)參數(shù)之后。

# 收集多余的位置參數(shù) def func_with_collection_rest_parameters(x, y=0, *rest):print(x, y)print(rest) func_with_collection_rest_parameters(1, 2, 3, 4, 5)

星號(hào)操作符之后的形參將作為元組傳遞給函數(shù),元組保存了所有傳遞給函數(shù)的"額外"的參數(shù)(匹配了所有位置和具名參數(shù)后剩余的)。如果沒(méi)有給出額外的參數(shù),元組為空。

6關(guān)鍵字變量參數(shù)(Dictionary)

在我們有不定數(shù)目的或者額外集合的關(guān)鍵字的情況中,?參數(shù)被放入一個(gè)字典中,字典中鍵為參數(shù)名,值為相應(yīng)的參數(shù)值。

#收集命名參數(shù) def func_with_collection_rest_naned_parameters(*args, **kw):print(args)print(kw) func_with_collection_rest_naned_parameters(1, 2, 3, x = 4, y = 5, z = 6)func_with_collection_rest_naned_parameters([1, 2, 3], {"x": 4, "y": 4, "z": 6}) #這會(huì)導(dǎo)致args[0]指向第一個(gè)實(shí)參,args[1]指向第二個(gè)實(shí)參。 #([1, 2, 3], {'y': 4, 'x': 4, 'z': 6}) #{} func_with_collection_rest_naned_parameters(*[1, 2, 3], **{"x": 4, "y": 4, "z": 6}) #這里的執(zhí)行相當(dāng)于func_with_collection_rest_naned_parameters(1, 2, 3, x = 4, y = 5, z = 6)。

?

(8)面向?qū)ο?/strong>

1、類通過(guò)class關(guān)鍵字定義。類名以大寫(xiě)字母開(kāi)頭,緊接著是(object),表示該類是從哪個(gè)類繼承下來(lái)的 類也要細(xì)致命名,像“AddrBookEntry”,“RepairShop”等等就是很好的名字 Python 并不支持純虛函數(shù)(像 C++)或者抽象方法(如在 JAVA 中) class Person(object):pass 2、有了Person類的定義,就可以創(chuàng)建出具體的xiaoming、xiaohong實(shí)例。創(chuàng)建實(shí)例使用類名+(),類似函數(shù)調(diào)用的形式創(chuàng)建: Python 規(guī)范推薦使用駱駝?dòng)浄ǖ南聞澗€方式,比如,“update_phone”“update_email”。 xiaoming = Person() xiaohong = Person() 3、由于Python是動(dòng)態(tài)語(yǔ)言,對(duì)每一個(gè)實(shí)例,都可以直接給他們的屬性賦值 xiaoming = Person() xiaoming.name = 'Xiao Ming' xiaoming.gender = 'Male' xiaoming.birth = '1990-1-1' 4、構(gòu)造函數(shù)__init__()方法 class Person(object):def __init__(self, name, gender, birth):self.name = nameself.gender = genderself.birth = birth __init__()方法的第一個(gè)參數(shù)必須是self(也可以用別的名字,但建議使用習(xí)慣用法),后續(xù)參數(shù)則可以自由指定,和定義函數(shù)沒(méi)有任何區(qū)別。 相應(yīng)地,創(chuàng)建實(shí)例時(shí),就必須要提供除self以外的參數(shù): xiaoming = Person('Xiao Ming', 'Male', '1991-1-1') xiaohong = Person('Xiao Hong', 'Female', '1992-2-2') print xiaoming.name # 輸出 'Xiao Ming' print xiaohong.birth # 輸出 '1992-2-2' 定義Person類的__init__方法,除了接受?name、gender??birth?外,還可接受任意關(guān)鍵字參數(shù),并把他們都作為屬性賦值給實(shí)例。 要定義關(guān)鍵字參數(shù),使用?**kw 除了可以直接使用self.name = 'xxx'設(shè)置一個(gè)屬性外,還可以通過(guò)?setattr(self, 'name', 'xxx')?設(shè)置屬性。 class Person(object):def __init__(self, name, gender, birth, **kw):self.name = nameself.gender = genderself.birth = birthfor k, v in kw.iteritems():setattr(self, k, v) xiaoming = Person('Xiao Ming', 'Male', '1990-1-1', job='Student') print xiaoming.name #輸出Xiao Ming print xiaoming.job #輸出Student 5、析構(gòu)函數(shù) 由于 Python 具有垃圾對(duì)象回收機(jī)制(靠引用計(jì)數(shù)),這個(gè)函數(shù)要直到該實(shí)例對(duì)象所有的引用都被清除掉后才會(huì)執(zhí)行。所以很少用到。 class Person(object):def __init__(self, ……): 6Python對(duì)屬性權(quán)限的控制是通過(guò)屬性名來(lái)實(shí)現(xiàn)的,如果一個(gè)屬性由雙下劃線開(kāi)頭(__),該屬性就無(wú)法被外部訪問(wèn) class Person(object):def __init__(self, name):self.name = nameself._title = 'Mr'self.__job = 'Student' p = Person('Bob') print p.name # => Bob print p._title # => Mr print p._Person__job # => Student #所以實(shí)際上并不是嚴(yán)格的私有成員 print p.__job # => Error 但是,如果一個(gè)屬性以"__xxx__"的形式定義,那它又可以被外部訪問(wèn)了,以"__xxx__"定義的屬性在Python的類中被稱為特殊屬性,有很多預(yù)定義的特殊屬性可以使用,通常我們不要把普通屬性用"__xxx__"定義。 以單下劃線開(kāi)頭的屬性"_xxx"可以在子類中使用,不應(yīng)該被外部訪問(wèn),理解為保護(hù)成員。 "__xxx"可以理解為私有成員,但實(shí)質(zhì)并不是,不建議訪問(wèn)。 7、類屬性是直接綁定在類上的,所以,訪問(wèn)類屬性不需要?jiǎng)?chuàng)建實(shí)例,就可以直接訪問(wèn): class Person(object):address = 'Earth'def __init__(self, name):self.name = name p1=Person(xiaoming) print Person.address # => Earth print p1.address # => Earth # 由于Python是動(dòng)態(tài)語(yǔ)言,類屬性也是可以動(dòng)態(tài)添加和修改的: Person.address = 'China' print p1.address # => 'China' 8、在實(shí)例變量上修改類屬性 當(dāng)實(shí)例屬性和類屬性重名時(shí),實(shí)例屬性優(yōu)先級(jí)高,它將屏蔽掉對(duì)類屬性的訪問(wèn)。而其他不變 9、訪問(wèn)類的屬性 有兩種方法。最簡(jiǎn)單的是使用 dir()內(nèi)建函數(shù)。另外是通過(guò)訪問(wèn)類的字典屬性__dict__,這是所有類都具備的特殊屬性之一。 10、實(shí)例的方法。 實(shí)例的方法就是在類中定義的函數(shù),它的第一個(gè)參數(shù)永遠(yuǎn)是self,指向調(diào)用該方法的實(shí)例本身,其他參數(shù)和一個(gè)普通函數(shù)是完全一樣的:在其他語(yǔ)言中,self就是this. class Person(object):def __init__(self, name):self.__name = namedef get_name(self):return self.__name p1 = Person('Bob') print p1.get_name() # self不需要顯式傳入 # => Bob print p1.__dict__ # {'_Person__name': 'Bob'} print p1._Person__name # => Bob 在實(shí)例方法內(nèi)部,可以訪問(wèn)所有實(shí)例屬性,這樣,如果外部需要訪問(wèn)私有屬性,可以通過(guò)方法調(diào)用獲得,這種數(shù)據(jù)封裝的形式除了能保護(hù)內(nèi)部數(shù)據(jù)一致性外,還可以簡(jiǎn)化外部調(diào)用的難度 11、方法也分實(shí)例方法和類方法。 @classmethod? 調(diào)用的時(shí)候用類名而不是某個(gè)對(duì)象 class中定義的全部是實(shí)例方法,實(shí)例方法第一個(gè)參數(shù)self是實(shí)例本身。 要在class中定義類方法,需要這么寫(xiě): class Person(object):count = 0@classmethoddef how_many(cls):return cls.countdef __init__(self, name):self.name = namePerson.count = Person.count + 1print Person.how_many() #0 p1 = Person('Bob') print Person.how_many() #1 通過(guò)標(biāo)記一個(gè)@classmethod,該方法將綁定到Person類上,而非類的實(shí)例。類方法的第一個(gè)參數(shù)將傳入類本身,通常將參數(shù)名命名為cls,上面的cls.count實(shí)際上相當(dāng)于Person.count。 因?yàn)槭窃陬惿险{(diào)用,而非實(shí)例上調(diào)用,因此類方法無(wú)法獲得任何實(shí)例變量,只能獲得類的引用 12@property ?像訪問(wèn)屬性一樣調(diào)用方法,即不用括號(hào) class Person(object):count = 0def __init__(self, name,age,weight):self.name = nameself._age = ageself.__weight = weightPerson.count = Person.count + 1@classmethoddef how_many(cls):return cls.count@propertydef get_weight(self):return self.__weightprint Person.how_many() # 0 p1 = Person('Bob',20,50) print Person.how_many() # 1 print p1.get_weight #50 get/set方法: class Student(object):def __init__(self, name, score):self.name = nameself.__score = scoredef get_score(self):return self.__scoredef set_score(self, score):if score < 0 or score > 100:raise ValueError('invalid score')self.__score = score #但是寫(xiě) s.get_score() 和 s.set_score() 沒(méi)有直接寫(xiě) s.score 來(lái)得直接。

  

用裝飾器函數(shù)把get/set方法“裝飾”成屬性調(diào)用: 把一個(gè)getter方法變成屬性,只需要加上 @ property就可以了 setter是關(guān)鍵字,這種“@+方法名字+點(diǎn)+setter”是個(gè)固定格式與@property搭配使用。 class Student(object):def __init__(self, name, score):self.name = nameself.__score = score@propertydef score(self):return self.__score@score.setterdef score(self, score):if score < 0 or score > 100:raise ValueError('invalid score')self.__score = scores = Student("Bob",100) print s.score #100 s.score = 90 #屬性賦值 print s.score #90 13、函數(shù)和方法 函數(shù)是直接調(diào)用函數(shù)名,僅僅是一部分代碼 方法必須和對(duì)象結(jié)合在一起使用,是類的一部分 方法可以看做是類的屬性 class Test(object):def test(self):passa = Test() print a.test #<bound method Test.test of <__main__.Test object at 0x00000000022B8E10>> print a.test() #None a.test= "123" print a.test #123 print a.test() #報(bào)錯(cuò) 14、定義子類 class Person(object):def __init__(self, name, gender):self.name = nameself.gender = gender class Student(Person):def __init__(self, name, gender, score):super(Student, self).__init__(name, gender) #初始化self.score = score 一定要用super(Student, self).__init__(name, gender)去初始化父類,否則,繼承自PersonStudent將沒(méi)有namegender 函數(shù)super(Student, self)將返回當(dāng)前類繼承的父類,即Person然后調(diào)用__init__()方法,注意self參數(shù)已在super()中傳入,在__init__()中將隱式傳遞,不需要寫(xiě)出(也不能寫(xiě)) 使用super()的漂亮之處在于,你不需要明確給出任何基類名字,這意味著如果你改變了類繼承關(guān)系,你只需要改一行代碼(class語(yǔ)句本身)而不必在大量代碼中去查找所有被修改的那個(gè)類的名字。 一個(gè)實(shí)例可以看成它本身的類型,也可以看成它父類的類型。 15、多重繼承 class A(object):def __init__(self, a):print 'init A...'self.a = a class B(A):def __init__(self, a):super(B, self).__init__(a)print 'init B...' class C(A):def __init__(self, a):super(C, self).__init__(a)print 'init C...' class D(B, C):def __init__(self, a):super(D, self).__init__(a)print 'init D...' 像這樣,D?同時(shí)繼承自?B??C,也就是?D?擁有了?A、B、C?的全部功能。多重繼承通過(guò)super()調(diào)用__init__()方法時(shí),A?雖然被繼承了兩次,但__init__()只調(diào)用一次: 多重繼承的目的是從兩種繼承樹(shù)中分別選擇并繼承出子類,以便組合功能使用。 舉個(gè)例子,Python的網(wǎng)絡(luò)服務(wù)器有TCPServer、UDPServer、UnixStreamServer、UnixDatagramServer,而服務(wù)器運(yùn)行模式有多進(jìn)程ForkingMixin多線程ThreadingMixin兩種。 要?jiǎng)?chuàng)建多進(jìn)程模式的?TCPServer class MyTCPServer(TCPServer, ForkingMixin)pass 要?jiǎng)?chuàng)建多線程模式的?UDPServer class MyUDPServer(UDPServer, ThreadingMixin):pass

如果沒(méi)有多重繼承,要實(shí)現(xiàn)上述所有可能的組合需要 4x2=8 個(gè)子類。

16多態(tài) 用一個(gè)類繼承多個(gè)類,調(diào)用同一個(gè)方法,會(huì)有不同的反應(yīng),因?yàn)楸恢貙?xiě)了。 17、鴨子類型 定義:“當(dāng)看到一只鳥(niǎo)走起來(lái)像鴨子、游泳起來(lái)像鴨子、叫起來(lái)也像鴨子,那么這只鳥(niǎo)就可以被稱為鴨子。 這種風(fēng)格適用于動(dòng)態(tài)語(yǔ)言(比如PHP、Python、Ruby、Typescript、Perl、Objective-C、Lua、Julia、JavaScript、Java、Groovy、C#等)和某些靜態(tài)語(yǔ)言 在鴨子類型中,關(guān)注的不是對(duì)象的類型本身,而是它是如何使用的。例如,在不使用鴨子類型的語(yǔ)言中,我們可以編寫(xiě)一個(gè)函數(shù),它接受一個(gè)類型為鴨的對(duì)象,并調(diào)用它的走和叫方法。在使用鴨子類型的語(yǔ)言中,這樣的一個(gè)函數(shù)可以接受一個(gè)任意類型的對(duì)象,并調(diào)用它的走和叫方法。 鴨子類型通常得益于不測(cè)試方法和函數(shù)中參數(shù)的類型,而是依賴文檔、清晰的代碼和測(cè)試來(lái)確保正確使用。從靜態(tài)類型語(yǔ)言轉(zhuǎn)向動(dòng)態(tài)類型語(yǔ)言的用戶通常試圖添加一些靜態(tài)的(在運(yùn)行之前的)類型檢查,從而影響了鴨子類型的益處和可伸縮性,并約束了語(yǔ)言的動(dòng)態(tài)特性。 鴨子類型比接口更好用。 class TestClass1:def say(self):print("我是鴨子1") class TestClass2:def say(self):print("我是鴨子2") def duck_say(duck):duck.say() duck_say(TestClass1()) # 我是鴨子1 duck_say(TestClass2()) # 我是鴨子2 18getattr()、setattr()和delattr(): getattr() setattr()函數(shù)相應(yīng)地取得和賦值給對(duì)象的屬性, getattr()會(huì)在你試圖讀取一個(gè)不存在的屬性時(shí),引發(fā) AttributeError 異常,除非給出那個(gè)可選的默認(rèn)參數(shù) setattr()將要么加入一個(gè)新的屬性,要么取代一個(gè)已存在的屬性。 delattr()函數(shù)會(huì)從一個(gè)對(duì)象中刪除屬性 class Person(object):def __init__(self, name, gender):self.name = nameself.gender = genderclass Student(Person):def __init__(self, name, gender, score):super(Student, self).__init__(name, gender)self.score = scoredef whoAmI(self):return 'I am a Student, my name is %s' % self.names = Student('Bob', 'Male', 88) print getattr(s, 'name') # 獲取name屬性 #Bobsetattr(s, 'name', 'Adam') # 設(shè)置新的name屬性 print s.name #Adam getattr(s, 'age') # 獲取age屬性,但是屬性不存在,報(bào)錯(cuò): getattr(s, 'age', 20) # 獲取age屬性,如果屬性不存在,就返回默認(rèn)值20:

?

(9)定制類(魔術(shù)方法)

1、__str__():把一個(gè)類的實(shí)例變成?str

__repr__()轉(zhuǎn)換為機(jī)器看的字符串,可以由eval()執(zhí)行

class Person(object):def __init__(self, name, gender):self.name = nameself.gender = genderdef __str__(self):return '(Person: %s, %s)' % (self.name, self.gender) p = Person('Bob', 'male') print p #(Person: Bob, male)

2、比較運(yùn)算符_cmp__():可以實(shí)現(xiàn)對(duì)一組?Student?類的實(shí)例排序

__eq__()判斷等于,__lt__()判斷小于,__gt__()判斷大于

class Student(object):def __init__(self, name, score):self.name = nameself.score = scoredef __str__(self):return '(%s: %s)' % (self.name, self.score)def __cmp__(self, s):if self.name < s.name:return -1elif self.name > s.name:return 1else:return 0L = [Student('Tim', 99), Student('Bob', 88), Student('Alice', 77)] print sorted(L) #[(Alice: 77), (Bob: 88), (Tim: 99)] L = [Student('Tim', 99), Student('Bob', 88), 100, 'Hello'] #list不僅僅包含 Student 類 print sorted(L) #報(bào)錯(cuò)

上述 Student 類實(shí)現(xiàn)了__cmp__()方法,__cmp__用實(shí)例自身self和傳入的實(shí)例?s?進(jìn)行比較,如果self應(yīng)該排在前面,就返回 -1,如果s應(yīng)該排在前面,就返回1,如果兩者相當(dāng),返回 0。

3、__len__():返回元素的個(gè)數(shù)

class Students(object):def __init__(self, *args):self.names = argsdef __len__(self):return len(self.names) ss = Students('Bob', 'Alice', 'Tim') print len(ss) #3

4、四則運(yùn)算:__add__(),__sub__(),__mul__(),__div__()

邏輯運(yùn)算 __or__(),__and__()

def gcd(a, b):if b == 0:return areturn gcd(b, a % b) class Rational(object):def __init__(self, p, q):self.p = pself.q = qdef __add__(self, r):return Rational(self.p * r.q + self.q * r.p, self.q * r.q)def __sub__(self, r):return Rational(self.p * r.q - self.q * r.p, self.q * r.q)def __mul__(self, r):return Rational(self.p * r.p, self.q * r.q)def __div__(self, r):return Rational(self.p * r.q, self.q * r.p)def __str__(self):g = gcd(self.p, self.q)return '%s/%s' % (self.p / g, self.q / g)__repr__ = __str__ r1 = Rational(1, 2) r2 = Rational(1, 4) print r1 + r2 #3/4 print r1 - r2 #1/4 print r1 * r2 #1/8 print r1 / r2 #2/1

我們也許還有希望覆蓋“原位”操作, 比如, __iadd__()。這是用來(lái)支持像 mon += tue 這樣的操作符,并把正確的結(jié)果賦給 mon。重載一個(gè)__i*__()方法的唯一秘密是它必須返回 self。把下面的片斷加到我們例子中,以修復(fù)上面的 repr()問(wèn)題,并支持增量賦值:

5、類型轉(zhuǎn)換:__int__(),__float__()

class Rational(object):def __init__(self, p, q):self.p = pself.q = qdef __int__(self):return self.p // self.qdef __float__(self):return float(self.p) / self.qprint int(Rational(7, 2)) #3 print int(Rational(1, 3)) #0 print float(Rational(7, 2)) #3.5 print float(Rational(1, 3)) #0.333333333333

6、__slots__():限制當(dāng)前類所能擁有的屬性,能節(jié)省內(nèi)存

class Person(object):__slots__ = ('name', 'gender')def __init__(self, name, gender):self.name = nameself.gender = gender p = Person('Bob', 'male') print p.name #Bob print p.gender #male print p.score #報(bào)錯(cuò)class Student(Person):__slots__ = ('score',)def __init__(self, name, gender, score):super(Student, self).__init__(name, gender)self.score = scores = Student('Bob', 'male', 59) print s.score # 59

__slots__定義的屬性僅對(duì)當(dāng)前類起作用,對(duì)繼承的子類是不起作用的。除非在子類中也定義__slots__

7、__call__():

在Python中,所有的函數(shù)都是可調(diào)用對(duì)象。

一個(gè)類實(shí)例也可以變成一個(gè)可調(diào)用對(duì)象,只需要實(shí)現(xiàn)一個(gè)特殊方法__call__()。

class Person(object):def __init__(self, name, gender):self.name = nameself.gender = genderdef __call__(self, friend):print 'My name is %s...' % self.nameprint 'My friend is %s...' % friendp = Person('Bob', 'male') p('Tim') # My name is Bob... # My friend is Tim...

單看p('Tim')你無(wú)法確定p是一個(gè)函數(shù)還是一個(gè)類實(shí)例,所以,在Python中,函數(shù)也是對(duì)象,對(duì)象和函數(shù)的區(qū)別并不顯著。

?

(10)日期和時(shí)間

1、time包基于C語(yǔ)言的庫(kù)函數(shù)(library functions)。Python的解釋器通常是用C編寫(xiě)的,Python的一些函數(shù)也會(huì)直接調(diào)用C語(yǔ)言的庫(kù)函數(shù)。

2、時(shí)間間隔是以秒為單位的浮點(diǎn)小數(shù)。

3、每個(gè)時(shí)間戳都以自從1970年1月1日午夜(歷元)經(jīng)過(guò)了多長(zhǎng)時(shí)間來(lái)表示。

import time; # 引入time模塊 ticks = time.time() print ticks

4、獲取當(dāng)前時(shí)間

import time localtime = time.localtime(time.time()) print "本地時(shí)間為 :", localtime #本地時(shí)間為 : time.struct_time(tm_year=2017, tm_mon=2, tm_mday=13, tm_hour=22, tm_min=20, tm_sec=59, tm_wday=0, tm_yday=44, tm_isdst=0) #時(shí)間元組struct_time:年,月,日,小時(shí),分鐘,秒,一周第幾天(0是周一),一年第幾天,夏令時(shí)

5、獲取格式化時(shí)間

最簡(jiǎn)單的獲取可讀的時(shí)間模式的函數(shù)是asctime():

import time localtime = time.asctime( time.localtime(time.time()) ) print "本地時(shí)間為 :", localtime #本地時(shí)間為 : Mon Feb 13 22:23:57 2017

我們可以使用 time 模塊的?strftime?方法來(lái)格式化日期:

import time # 格式化成2016-03-20 11:45:39形式 print time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) #2017-02-13 22:25:08 # 格式化成Sat Mar 28 22:24:24 2016形式 print time.strftime("%a %b %d %H:%M:%S %Y", time.localtime()) #Mon Feb 13 22:25:08 2017 # 將格式字符串轉(zhuǎn)換為時(shí)間戳 a = "Sat Mar 28 22:24:24 2016" print time.mktime(time.strptime(a, "%a %b %d %H:%M:%S %Y")) #1459175064.0

python中時(shí)間日期格式化符號(hào):

%y?兩位數(shù)的年份表示(00-99)

%Y?四位數(shù)的年份表示(000-9999)

%m?月份(01-12)

%d?月內(nèi)中的一天(0-31)

%H 24小時(shí)制小時(shí)數(shù)(0-23)

%I 12小時(shí)制小時(shí)數(shù)(01-12)

%M?分鐘數(shù)(00=59)

%S?秒(00-59)

%a?本地簡(jiǎn)化星期名稱

%A?本地完整星期名稱

%b?本地簡(jiǎn)化的月份名稱

%B?本地完整的月份名稱

%j?年內(nèi)的一天(001-366)

%U?一年中的星期數(shù)(00-53)星期天為星期的開(kāi)始

%w?星期(0-6),星期天為星期的開(kāi)始

%W?一年中的星期數(shù)(00-53)星期一為星期的開(kāi)始

6、獲取某月日歷

Calendar模塊有很廣泛的方法用來(lái)處理年歷和月歷,例如打印某月的月歷:

import calendar cal = calendar.month(2017, 2) print "以下輸出2017年2月份的日歷:" print cal 以下輸出2017年2月份的日歷: # February 2017 # Mo Tu We Th Fr Sa Su # 1 2 3 4 5 # 6 7 8 9 10 11 12 # 13 14 15 16 17 18 19 # 20 21 22 23 24 25 26 # 27 28

7time.sleep(secs)推遲調(diào)用線程的運(yùn)行,secs指秒數(shù)。

import time print('start') time.sleep(3) # sleep for 3 seconds print('wake up')

8、datetime包

datetime包是基于time包的一個(gè)高級(jí)包, 為我們提供了多一層的便利。

datetime可以理解為date和time兩個(gè)組成部分。date是指年月日構(gòu)成的日期(相當(dāng)于日歷),time是指時(shí)分秒微秒構(gòu)成的一天24小時(shí)中的具體時(shí)間(相當(dāng)于手表)

import datetime t = datetime.datetime(2017,2,13,21,30) print(t)#2017-02-13 21:30:00

datetime包還定義了時(shí)間間隔對(duì)象(timedelta)一個(gè)時(shí)間點(diǎn)(datetime)加上一個(gè)時(shí)間間隔(timedelta)可以得到一個(gè)新的時(shí)間點(diǎn)(datetime)。同理,兩個(gè)時(shí)間點(diǎn)相減會(huì)得到一個(gè)時(shí)間間隔。

import datetime t = datetime.datetime(2017,2,13,21,30) t_next = datetime.datetime(2017,2,13,23,30) delta1 = datetime.timedelta(seconds = 600) delta2 = datetime.timedelta(weeks = 3) print(t + delta1) #2017-02-13 21:40:00 print(t + delta2) #2017-03-06 21:30:00 print(t_next - t) #2:00:00

9、其他模塊:pytz模塊dateutil模塊

?

(11)數(shù)學(xué)與隨機(jī)數(shù)

1、math包主要處理數(shù)學(xué)相關(guān)的運(yùn)算。math包定義了兩個(gè)常數(shù):

math.e?? #?自然常數(shù)e??????

math.pi??#?圓周率pi

2、math包運(yùn)算

math.ceil(x)???? ? #?對(duì)x向上取整,比如x=1.2,返回2

math.floor(x)????? #?對(duì)x向下取整,比如x=1.2,返回1

math.pow(x,y)????? #?指數(shù)運(yùn)算,得到x的y次方

math.log(x)?????? #?對(duì)數(shù),默認(rèn)基底為e。可以使用base參數(shù),來(lái)改變對(duì)數(shù)的基地。

math.sqrt(x)?????? #?平方根

3、math包三角函數(shù):

math.sin(x), math.cos(x), math.tan(x), math.asin(x), math.acos(x), math.atan(x)

這些函數(shù)都接收一個(gè)弧度(radian)為單位的x作為參數(shù)。

角度和弧度互換:?math.degrees(x), math.radians(x)

4、random包

1)?隨機(jī)挑選和排序

random.choice(seq)???#?從序列的元素中隨機(jī)挑選一個(gè)元素

比如random.choice(range(10))?#從0到9中隨機(jī)挑選一個(gè)整數(shù)。

random.sample(seq,k)?#?從序列中隨機(jī)挑選k個(gè)元素

random.shuffle(seq)??#?將序列的所有元素隨機(jī)排序

2)隨機(jī)生成實(shí)數(shù)

random.random()??? ?? ?#?隨機(jī)生成下一個(gè)實(shí)數(shù),它在[0,1)范圍內(nèi)。

random.uniform(a,b)??? ??#?隨機(jī)生成下一個(gè)實(shí)數(shù),它在[a,b]范圍內(nèi)。

5、decimal 十進(jìn)制浮點(diǎn)運(yùn)算類 Decimal

?

(12)正則表達(dá)式

1、匹配字符串

str.startswith()和str.endswith()

一個(gè)句子結(jié)尾是\n來(lái)結(jié)束的,所以用endswith(‘’)方法匹配時(shí)要注意傳入的變量帶有\(zhòng)n

或者用切片操作,str[:-1].endswith()

def find(fname):f = open(fname,"r+")for line in f :if line.startswith("this")\ #一個(gè)句子太長(zhǎng)時(shí)使用 \ 符號(hào)來(lái)?yè)Q行or line[:-1].endswith("apple"):print linefind("test1.txt") # this is an apple # this is a pear # this is a banana # that is an apple

2、正則表達(dá)式概念

使用單個(gè)字符串來(lái)描述匹配一系列符合某個(gè)句法規(guī)則的字符串,是對(duì)字符串操作的一種邏輯公式,應(yīng)用場(chǎng)景在處理文本和數(shù)據(jù)

re?模塊使Python語(yǔ)言擁有全部的正則表達(dá)式功能。

3、導(dǎo)入re模塊? #import re

利用re.compile(正則表達(dá)式)返回pattern

利用pattern.match(待匹配字符串)返回match

match.group()返回子串

match.string()返回主串

match.span()返回子串在主串中的位置

import re str1 = "this is an apple" regex = re.compile(r"this") #r‘ ’內(nèi)的字符不轉(zhuǎn)義 print regex #<_sre.SRE_Pattern object at 0x0000000001D2DDD8> ma = regex.match(str1) print ma #<_sre.SRE_Match object at 0x0000000002075510> print ma.group() #this print ma.span() #(0, 4) print ma.string #this is an apple print ma.re #=regex

4re.match?嘗試從字符串的開(kāi)始匹配一個(gè)模式。

re.match(pattern, string, flags=0)

pattern ?匹配的正則表達(dá)式

string?要匹配的字符串

flags?標(biāo)志位,用于控制正則表達(dá)式的匹配方式,如:是否區(qū)分大小寫(xiě), 多行匹配等等

匹配成功re.match方法返回一個(gè)匹配的對(duì)象,否則返回None。

5group(num)groups()匹配對(duì)象函數(shù)來(lái)獲取匹配表達(dá)式。

group(num=0)匹配的整個(gè)表達(dá)式的字符串,group()可以一次輸入多個(gè)組號(hào),在這種情況下它將返回一個(gè)包含那些組所對(duì)應(yīng)值的元組。

groups()返回一個(gè)包含所有小組字符串的元組。

6基本匹配符

①. ?????匹配任意字符(除了\n),一個(gè)點(diǎn)只是一個(gè)字符

②[…] ??匹配字符集???如[a-z][A-Z][0-9][a-zA-Z0-9]

③[^…]??匹配不在[]中的任意字符

④\d ????匹配數(shù)字等價(jià)于[0-9]

⑤\D ????匹配非數(shù)字

⑥\s ????匹配空白,包括空格、制表符、換頁(yè)符等等。等價(jià)于[\f\n\r\t\v]

⑦\(yùn)S ????匹配非空白

⑧\w ????匹配單詞字符,匹配包括下劃線的任何單詞字符。等價(jià)于[A-Za-z0-9_]??

⑨\W ????匹配非單詞字符

import re ma = re.match(r'[\w]','0') print ma.group()#0 ma = re.match(r'\[[\w]\]','[0]') print ma.group()#[0]

7特殊匹配符

①*????? 匹配前一個(gè)字符0次或無(wú)限次

②+????? 匹配前一個(gè)字符1次或無(wú)限次

????? 匹配前一個(gè)字符0次或1次

④{m}? ??匹配前一個(gè)字符m

⑤{m,n}??匹配前一個(gè)字符m到n次

⑥*?或+?或?? 匹配模式變?yōu)榉秦澙?#xff08;盡可能減少匹配字符)

import re ma = re.match(r'[a-zA-Z0-9]*','SAFGAFG') print ma.group() #SAFGAFG ma = re.match(r'[a-zA-Z0-9]{3,6}@163.com','SAFGFG@163.com') print ma.group() #SAFGFG@163.com ma = re.match(r'[0-9][a-z]*','1bc') print ma.group() #1bc ma = re.match(r'[0-9][a-z]*?','1bc') print ma.group() #1

8高級(jí)匹配符

①^ ?????匹配字符串開(kāi)頭

②$ ?????匹配字符串結(jié)尾

③\A? ???指定的字符串必須出現(xiàn)在開(kāi)頭

④\Z ????指定的字符串必須出現(xiàn)在結(jié)尾

⑤| ?????,匹配左右任意一個(gè)表達(dá)式

⑥(ab) ??括號(hào)中表達(dá)式作為一個(gè)分組

⑦\(yùn)<number> ?引用編號(hào)為num的分組匹配到的字符串

⑧(?P<name>) 分組起一個(gè)別名

⑨(?P=name) ?引用別名為name的分組匹配字符串

import re ma = re.match(r'^[\w]{4,10}@163.com$',"abc123@163.com") print ma.group() #abc123@163.com ma = re.match(r'\Aabc[\w]*',"abc123") print ma.group() #abc123 ma = re.match(r'[1-9]?\d$',"99")#0-99 print ma.group() #99 ma = re.match(r'[1-9]?\d$|100',"100")#0-99 print ma.group() #100 ma = re.match(r'[\w]{4,6}@(163|126|qq).com',"abc123@qq.com") print ma.group() #abc123@qq.com ma = re.match(r'<([\w]+>)[\w]+</\1',"<book>python</book>") print ma.group() #<book>python</book> ma = re.match(r'<(?P<mark>[\w]+>)[\w]+</(?P=mark)',"<book>python</book>") print ma.group() #<book>python</book> ma = re.match(r'<(?P<ht>[\w]+>)<(?P<h>[\w]+>)<(?P<s>[\w]+>).+</(?P=s)</(?P=h)</(?P=ht)',"<html><head><script>javascript:alect('hello world')</script></head></html>") print ma.group() #<html><head><script>javascript:alect('hello world')</script></head></html> print ma.groups() #('html>', 'head>', 'script>')

9、其他方式

search(pattern,string,flags=0)

會(huì)在字符串內(nèi)查找模式匹配,直到找到第一個(gè)匹配

匹配成功re.search方法返回一個(gè)匹配的對(duì)象,否則返回None

findall(pattern,string,flags=0)

找到匹配,返回所有匹配部分的列表

sub(pattern,repl,string,count=0,flags=0)

將字符串中匹配正則表達(dá)式的部分替換為其他值

split(pattern,string,maxsplit=0,flags=0)

根據(jù)匹配分割字符串,返回分割字符串組成的列表

import re str1 = "abc = 100" info = re.search(r'\d+',str1) print info.group() #100 str2 = "c++=100,java=90,python=80" info = re.search(r'\d+',str2) print info.group() #100 info = re.findall(r'\d+',str2) print info #['100', '90', '80'] print sum([int(x) for x in info]) #270 #列表解析str3 = "python video = 1000" info = re.sub(r'\d+',"1001",str3) #sub是調(diào)用findall而不是search print info #python video = 1001def add3(match):val = match.group()num = int(val)+3return str(num) info = re.sub(r'\d+',add3,str3) print info #python video = 1001str4 = "class:C C++ JAVA Python C#" info = re.split(r':| |,',str4) print info #['class', 'C', 'C++', 'JAVA', 'Python', 'C#']

10修飾符

正則表達(dá)式可以包含一些可選標(biāo)志修飾符來(lái)控制匹配的模式。修飾符被指定為一個(gè)可選的標(biāo)志。多個(gè)標(biāo)志可以通過(guò)按位 OR(|) 它們來(lái)指定。

①re.I ????使匹配對(duì)大小寫(xiě)不敏感

②re.M ????多行匹配,影響 ^和$

③re.S ????使.匹配包括換行在內(nèi)的所有字符

11、抓取網(wǎng)頁(yè)中的圖片到本地

1:抓取網(wǎng)頁(yè)

2:獲取圖片地址

3:抓取圖片內(nèi)容并保存到本地

import urllib2,re req = urllib2.urlopen("http://www.imooc.com/course/list") buf = req.read() listurl = re.findall(r'http:.+\.jpg',buf)i = 0 for url in listurl:f = open(str(i)+".jpg","wb")req = urllib2.urlopen(url)buf = req.read()f.write(buf)i+=1print I #看看輸出了多少個(gè),此時(shí)也生成i個(gè).jpg

?

轉(zhuǎn)載于:https://www.cnblogs.com/111testing/p/6405429.html

總結(jié)

以上是生活随笔為你收集整理的python基础语法及知识点总结的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。