教程總綱:http://www.runoob.com/python/python-tutorial.html
進階教程:http://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000
基本概念:(按照Python3標準來開發)
按照縮進來區分代碼塊
python默認不支持中文,采用 ASCII 編碼,如果需要使用中文(特別要小心中文的標點等,也會引起運行時錯誤),那么可以參考文章:http://www.jb51.net/article/26298.htm
python是順序執行的腳本,它不在乎變量的聲明位置,只要在使用這個變量之前,之前的代碼執行過這個變量的初始化,那么這個變量的使用就是合法的。
局部變量:以函數調用為分界線,函數內聲明的變量是不能在函數外使用的 。
全局變量:在函數外聲明的全局變量,是可以在任意地方被訪問到的。但是在函數內會默認創建一個同名的局部變量,我們可以使用 global 變量名 表示這個變量來自于全局變量,請不要創建局部變量而直接使用即可。
在定義模塊時,所有的文件都不應該有全局變量和全局執行代碼(即不在 def 和 class 中的代碼),如果有,那么這些代碼被import后將會被執行運行。
PYTHONPATH 用于指定 python庫的搜索路徑,在 pyCharm中會在開始前自動執行一段腳本,將當前的工程目錄加入到搜索列表中去。
多版本python管理軟件:多版本python管理工具:pyenv的使用
可以在交互式命令行中使用help( ?查詢的類名或者函數名 ?)來獲得幫助信息
python內置函數:https://docs.python.org/3/library/functions.html
打包教程:
python的import語句會將文件加載到當前文件中,在該文件首次加載時,會執行文件內部的頂層代碼。
import語句默認是調用 __import__( ?"xxxx" )來加載模塊,該函數返回一個集合名,之后需要以這個集合名為對象名,訪問模塊內的各種屬性。
導入模塊(包和模塊是一樣的)的兩種形式:
import <模塊名>:將會包含所有的xxx模塊內的元素,在使用時,有命名空間限制,需要加上模塊名 xxx 才能調用模塊內的內容。(在最終文件使用時,推薦這種方式,避免大范圍的命名沖突)
form ?<模塊名> import ?<內容>:從模塊中導入一個指定的部分到當前命名空間中。不需要再加上前綴,可以直接使用。(可能導致大范圍的命名沖突,但是在 __init__.py 中建議使用中這種方式,以避免復雜的模塊內命名空間)
form <模塊名> import * :可以完整的導入模塊內的所有內容(函數、全局變量名等),并且不需要使用命名空間,但是非常容易引起沖突,
前面的內容均可以使用 as 為導入內容生成別名。例如 import CJFKit as CJFXXX.
建議在編寫自己模塊的時候,少用全局變量,避免沖突。
python的包組織形式是文件夾形式,文件夾名字即是包名。然后其內一定有一個 __init__.py 文件,其內包含所有的文件引用。
總之,使用 import引入包或者模塊時,都需要加上前綴對象名才可以訪問內容。
數據類型相關:
None是一種類對象,是NoneType類型。如果沒有return語句,函數執行完畢也會返回結果,只是結果為None。
Python標準數據類型:
Numbers(數字) :
int(有符號整型):位數是64位,最長能顯示 [ -922 3372 0368 5477 5808, 922 3372 0368 5477 5808 ]。
long(長整型[也可以代表八進制和十六進制],后面加L):起碼128位
float(浮點型)
complex(復數,表示為 a + bj 或者是 complex(a,b))
String(字符串) :
可以使用 單引號、雙引號 和 三引號(期間包含的內容將不經過轉碼直接顯示,可以直接包含換行、引號等內容) 表示字符串字面量。
支持下標操作,且支持負數下標。
使用 == 比較內容(注意在python3中 cmp函數被移除)
List(列表/序列) :
【】: 列表,即可變數組。支持下標操作,且支持負數下標。
打印時顯示為 【 xx,xx,xx....】,且字符串類型會帶上單引號。
Tuple(元組) :
():元組,即只讀數組。支持下標操作,且支持負數下標。
打印時顯示為 (?xx,xx,xx.... ),且字符串類型會帶上單引號。
Dictionary(字典):
{ xxx:xxx, } : 字典。內容可變。鍵可以為任意的不可變類型,值則可任意類型。
dic.keys()會返回一個鍵列表,dic.values()會返回一個值列表。
打印時顯示為 { xx:xx,xx.... },且字符串類型會帶上單引號。
使用 in 檢測是否存在key。比如 “xxxx” in dic ,返回值是個BOOL值。
Set(集合):
使用list或者是tuple來初始化set,會去重后生成set集合。表示為 { ?1,2,3,………… } 這種類型
可以使用集合操作符:| 表示合集,& 表示交集,- 表示A相對于B的補集,^ 表示雙方的差集
set要求傳入的元素均為不可變對象,否則會直接報錯。
不支持下標操作,會直接報錯。
類型轉換:
int(x [,base])將x轉換為一個整數
long(x [,base] )
將x轉換為一個長整數
float(x)
將x轉換到一個浮點數
complex(real [,imag])
創建一個復數
str(x)
將對象 x 轉換為字符串
repr(x)
將對象 x 轉換為表達式字符串
eval(str)
用來計算在字符串中的有效Python表達式,并返回一個對象
tuple(s)
將序列 s 轉換為一個元組
list(s)
將序列 s 轉換為一個列表
set(s)
轉換為可變集合
dict(d)
創建一個字典。d 必須是一個序列 (key,value)元組。
frozenset(s)
轉換為不可變集合
chr(x)將一個整數轉換為一個字符,只支持ASCII字符
unichr(x)
將一個整數轉換為Unicode字符
ord(x)
將一個字符轉換為它的整數值,只支持ASCII字符,直接以字符串的形式放入即可
hex(x)
將一個整數轉換為一個十六進制字符串
oct(x)
將一個整數轉換為一個八進制字符串
使用到變量[頭下標:尾下標]可以截取 字符串、列表 和 元組的子元素。使用這種方式截取的子元素,其類型與原類型相同。且這是個半閉包(前包后不包)取值。
range(x1,x2):這也是一個半閉包,前包后不包。
Python不支持單字符類型,單字符也在Python也是作為一個字符串使用。
元組中只包含一個元素時,需要在元素后面添加逗號: tup1 = (50,)
變量的類型是可以變的,即一個變量在上一個語句指向一個str對象,接下來你還可以將它指向int對象。即所有指針都是通用的。(懷疑是存在一個通用的基類)
函數相關:
默認參數:
函數可以使用默認參數(必選參數在前,可選參數在后),例如 person ( name , age = 19 , city = "SH" )
可以選擇性使用參數(即可跳過一定的中間可選參數),但對于選擇性使用的參數需要強制指明變量名,類似于 city="xcasca"。例如 person( "jack" , city = "BJ" ).
由于函數默認參數是采用靜態對象的方式保存的,一旦被定義就維持著這一個對象,因此函數默認參數對象必須采用不可變對象。
可變參數:
使用 calc(*number ) 這樣的形似就可以了一個可變參數函數。它可以接受多個參數傳入,會將它們自動組合成為以number為變量名的tuple。
其允許傳入0到多個參數
我們可以使用一個list或者tuple傳入多個參數,那么需要在對象前加上*,表示解析為多個參數。
關鍵字參數:
我們可以使用 person( name, age, **dic),這個 **kw就表示可變參數。然后調用時使用 person( "jack" , ?19 , "city" = "SH" , "job" = "fuck" ),這樣的類型來調用,后面的兩個參數會組裝成字典 dic的元素,然后我們可以通過讀取 dic來獲取這些參數。
可以直接將一個字典 例如 extraDic ,使用?person( "jack" , ?19 , **extraDic ) 的方式傳入。
命名關鍵字參數:(主要是為保證我們不傳錯參數)
定義類似于?person(name, age, *, city, job) ,正常情況下中間的 * 不可忽略。
如果?person(name, age, *args, city, job) ,存在可變參數,那么 * 必須忽略。注意,此時在可變參數之后的參數,都是命名關鍵字參數,需要使用鍵值對的形式才能賦值。
其在調用時,必須 使用 person( “jack” , 19 , city = “SH” , job = “enginner” ).必須指明命名關鍵字標志后面的參數的名字 和 值,否則會報錯。
這5種參數都可以組合使用。但是請注意,參數定義的順序必須是:必選參數、默認參數、可變參數、命名關鍵字參數和關鍵字參數。例如:
deff1(a,b,c=0,*args,ddd,eee?=19,**kw):
print(a);print(b);print(c)
print("change”);forninargs:print(n);
print("key”);print(ddd);print(eee)
print("kw”);print(kw)
f1(1,2,3,4,5,6,7,8,9,ddd=1)
結果為:1、2、3、change、4、5、6、7、8、9、key、1、19、kw、{}
遞歸函數的尾遞歸優化:
函數的堆棧層級是受限制的 ,一般肯定小于1000(在本機測試的結果是 998為極限)。
尾遞歸優化技術的條件:在return語句中,只返回本函數的調用,不包含任何的其他計算。(當然參數上可以計算),例如 return fact_iter( num -1 , num * product ) 這是符合尾遞歸優化的函數。但是 return n * fact( n -1 ) 這是不符合尾遞歸優化。
當符合尾遞歸優化時,編譯器會優化調用,是其始終只占用一層調用堆棧。
并沒有什么鳥用!!!因為Python標準的解釋器沒有針對尾遞歸做優化,任何遞歸函數都存在棧溢出的問題!
基礎語法相關:
變量不需要聲明類型,直接使用即可,但Python依然是強類型語言,必要時需要類型轉換語句。注意此處的轉化并不是指指針上的轉化,因為python中的指針是萬能指針,可以指向任何對象。這里的轉化是指對實際對象的轉化工作,否則在運行時相應對象如果調用了它不存在的屬性或者方法將會引起運行時錯誤。
print 自帶了換行符,print后面接任何東西都會以string的形式打印出來
賦值語法:
a, b = b, a + b 表示 ?a = b ; b = a + b
s1,s2 = sss.split(".”) :表示 將函數返回的list值,依次組裝到等號左邊的元素中去。注意,如果此處參數個數不相等,會產生運行時錯誤。
沒有++ 或者 - - 語句,需要采用原始的 i = i+ 1來完成
語句后面不需要分號,if \ else \ for 語句后面需要 冒號
成員運算符:用于在容器類中包含判斷包含元素。
in如果在指定的序列中找到值返回 True,否則返回 False。x 在 y 序列中 , 如果 x 在 y 序列中返回 True。
not in如果在指定的序列中沒有找到值返回 True,否則返回 False。x 不在 y 序列中 , 如果 x 不在 y 序列中返回 True。
身份運算符:用于判斷兩個變量的存儲單元是否一致。
isis是判斷兩個標識符是不是引用自一個對象x is y, 如果 id(x) 等于 id(y) ,is返回結果 1
is notis not是判斷兩個標識符是不是引用自不同對象x is not y, 如果 id(x) 不等于 id(y).is not返回結果 1
邏輯運算符:
andx and y布爾"與" - 如果 x 為 False,x and y 返回 False,否則它返回 y 的計算值。(a and b) 返回 20。
orx or y布爾"或" - 如果 x 是 True,它返回 True,否則它返回 y 的計算值。(a or b) 返回 10。
notnot x布爾"非" - 如果 x 為 True,返回 False 。如果 x 為 False,它返回 True。not(a and b) 返回 False
pass 語句pass是空語句,是為了保持程序結構的完整性。
for … else表示這樣的意思,for 中的語句和普通的沒有區別,else 中的語句會在循環正常執行結束(即for 不是通過 break 跳出而中斷的)的情況下執行,while … else也是一樣。
基本數學相關方法:http://www.runoob.com/python/python-numbers.html
隨機數 與 隨機方法
三角函數
類型轉換
數學常量,使用 math庫,math.pi 常量。
字符串相關所有操作符:
+字符串連接a + b 輸出結果: HelloPython
*重復輸出字符串a*2 輸出結果:HelloHello
[]通過索引獲取字符串中字符a[1] 輸出結果e
[ : ]截取字符串中的一部分a[1:4] 輸出結果ell
in成員運算符 - 如果字符串中包含給定的字符返回 TrueH in a輸出結果 1
not in成員運算符 - 如果字符串中不包含給定的字符返回 TrueM not in a輸出結果 1
r/R原始字符串 - 原始字符串:所有的字符串都是直接按照字面的意思來使用,沒有轉義特殊或不能打印的字符。 原始字符串除在字符串的第一個引號前加上字母"r"(可以大小寫)以外,與普通字符串有著幾乎完全相同的語法。print r'\n'輸出 \n 和print R'\n'輸出 \n
%格式字符串請看下一章節
字典值可以沒有限制地取任何python對象,既可以是標準的對象,也可以是用戶定義的,但鍵不行,鍵必須不可變,所以可以用數字,字符串或元組充當,所以用列表就不行。
類型判斷:type( xxx )可以返回類對象,該思想與OC一致,且每種類對象都全局單例唯一。可以使用 type( xx ) is xClass 來判斷(但不建議使用,已經不適用于類族的情況)。建議使用: isinstance( var , class ?)來判斷。
如果需要判斷一個函數類型可以用這種方法。也可以使用:
或者是 使用 callable( xxx ?),如果返回true則表示可以,否則就表示不可以。(推薦這一種)
所有參數(自變量)在Python里都是按引用傳遞,所有變量在python中都是對象,python沒有內置類型。如果你在函數里修改了參數,那么在調用這個函數的函數里,原始的參數也被改變了。
python支持可變參數傳值,加了星號(*)的變量名會存放所有未命名的變量參數。選擇不多傳參數也可。可變參數變量在內部表現為元組形式使用。
python中的 lamdba 可以持續的捕捉變量的數據,同時追蹤它在 lamdba表達式之外是否發生變化,內部變量也同步發生變化。可以認為,其捕捉的變量和外部變量是同一個變量。
python變量的作用域,只有全局和局部的區別。且局部變量只出現在函數調用內部,語句塊不影響變量的可見性。
Python會智能地猜測一個變量是局部的還是全局的,它假設任何在函數內賦值的變量都是局部的。因此,如果要給全局變量在一個函數里賦值,必須使用global語句。 global VarName的表達式會告訴Python, VarName是一個全局變量,這樣Python就不會在局部命名空間里尋找這個變量了,否則結果就是會出現一個UnboundLocalError的錯誤。
使用__init__.py 形成包的組織形式。
File 對象方法: file對象提供了操作文件的一系列方法;OS 對象方法: 提供了處理文件及目錄的一系列方法。
全局變量是全局可見的,且與定義位置無關。
自定義類相關:
# 例子:
classEmployee:
'所有員工的基類’ ? # 可以使用類的幫助信息可以通過ClassName.__doc__查看
empCount=0 ? ? # 算是靜態變量
def__init__(self,name,salary): ? ? #成員函數的第一個參數一定是 self
self.name=name ? ? #成員變量不需要聲明,直接使用即可
self.salary=salary
Employee.empCount+=1
在類定義中,與方法同級的變量是 static變量,歸屬于類對象。類對象最好使用類名.變量名去訪問,直接使用 對象.變量名去訪問,可能訪問的是對象的動態屬性。
對象的屬性可以動態變更(不僅是類的實例變量的屬性可以動態增刪,連類對象的static變量都可以支持動態增刪),使用如下方法,當我們使用 .屬性訪問時,其實默認內部調用的就是這些方法。目測在類內部維持有一個屬性字典,以支持動態的增刪屬性:
getattr(obj, name[, default]) : 訪問對象的屬性。如果不存在該屬性,將會處罰exception。
hasattr(obj,name) : 檢查是否存在一個屬性。
setattr(obj,name,value) : 設置一個屬性。如果屬性不存在,會創建一個新屬性。
delattr(obj, name) : 刪除屬性,刪除后屬性整個就不存在了。
如果我們想要限制實例的屬性怎么辦?比如,只允許對Student實例添加name和age屬性。為了達到限制的目的,Python允許在定義class的時候,定義一個特殊的__slots__變量,來限制該class實例能添加的屬性:
classStudent(object):
__slots__?=?('name','age')#?用tuple定義允許綁定的屬性名稱
使用__slots__要注意,__slots__定義的屬性僅對當前類實例起作用,對繼承的子類是不起作用的
類的實例方法的參數,第一個一定是 self。
類的屬性獲取都應該先使用 hasattr 判斷是否存在,然后再進行下一步操作。
使用 self.__class__ 或者 實例變量.__class__ 可以返回該實例變量的類對象。
類對象的內置屬性:(注意是類對象的,而不是實例變量的,其實也是靜態變量)
__dict__ : 類的屬性(包含一個字典,由類的數據屬性組成)【其中包含了所有的靜態變量、方法(靜態或非靜態)、類的內置屬性】
__doc__ :類的文檔字符串
__name__: 類名
__module__: 類定義所在的模塊(類的全名是'__main__.className',如果類位于一個導入模塊mymod中,那么className.__module__ 等于 mymod)
__bases__ : 類的所有父類構成元素(包含了以個由所有父類組成的元組)
id( xxx ?) 可以返回一個對象的內存地址。可以用 id( xx ) == id( xxx ) 來判斷是否是同一個對象。
類繼承的寫法以及特性:
實例:http://blog.chinaunix.net/uid-22920230-id-3070742.html
在繼承中基類的構造(__init__()方法)不會被自動調用,它需要在其派生類的構造中親自專門調用。
在調用基類的方法時,需要加上基類的類名前綴,且需要帶上self參數變量。區別于在類中調用普通函數時并不需要帶上self參數(在類外調用的話,是都不需要的)。
Python總是首先查找對應類型的方法,如果它不能在派生類中找到對應的方法,它才開始到基類中逐個查找。(先在本類中查找調用的方法,找不到才去基類中找)。
類的方法可以可以動態的添加和刪除。
在類對象上添加方法:className.method_name = method; 。在添加完成后,所有的該類的實例對象都可以使用該方法。
在實例對象上添加:
需要先導入fromtypesimportMethodType
然后使用 instanceName.method_name = MethodType( method ,instanceName? )
這樣的設置方法,該方法只有被設置的對象可以使用,其他對象不能不能使用。
動態設置屬性方法。
使用屬性名作為設置和獲取的方法名。
使用@propety修飾獲取方法
使用@屬性名.setter 來修飾設置方法
內部的實際存取變量或者運算還是由自己控制的。屬性方法不會自動生成關聯變量。
可以設置只讀屬性和只寫屬性。
示例:
定制化類:(內置方法的實現)
使用 __init__ 實現自己的定制化初始化方法。
使用__slots__ 賦值為元組,限制屬性
實現 __len__ 函數可以在外部調用len()函數時,打印自己的長度。
打印相關:__str__ 方法,在print instance時被調用。__repr__ 在debug輸出時被調用
成為Iterable對象:實現__iter__函數,返回相應的可迭代對象。如果是自己的話,那么再繼續實現__next__函數,來支持 for-in循環。
支持下標和切片操作:實現 __getitem__ 函數,返回相應的list 或者 tuple。(要注意的是,切片有多種形式,需要覆蓋完全才可,切片的類型是slice)
動態屬性生成:__getattr__函數,可以支持返回變量和方法,如果是后者,那么外部需要加上調用式。
注意,此方法只有在無法找到合法屬性時才會調用,且最好在尾部raise出異常
此方法與鏈式語法結合可以達到很好的效果
編程可調用對象:實現 __callable__ 函數,即可使對象可被調用
枚舉類:
使用 Enum生成簡易枚舉對象:
導入頭文件:from enum import Enum
生成類對象:Month = Enum('Month', ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'))
繼承于Enum類對象,實現高度定制化枚舉類:
導入頭文件:from enum import Enum,unique
定義類:
@unique
classWeekday(Enum):
Sun?=0#?Sun的value被設定為0
Mon?=1
Tue?=2
Wed?=3
Thu?=4
Fri?=5
Sat?=6
高級語法特性:
切邊:即快速選取部分元素,這在上面有提到過,范圍是個半閉包。
只能用于list和tuple
以下標作為截取范圍標記
切邊產生的元素類型與原類型一致
有多重表現形式:
【startIndex:endIndex】不包含末位
【:length】默認從0開始
【:】完整的賦值
【-a:-b】從倒數第b位開始,到倒數第a位,不包含第a位。注意,此時list末尾的依然是0開始,然后向左遞減。注意,此時截取的list內元素順序依然是之前的順序,這個范圍只決定截取范圍。
【-a:】表示倒數第0位到倒數第a位,不包含倒數第a位。
【a:b:c】表示截取[a,b)范圍元素,并且在這些元素中,每c個取一個,都取第一個,末位的分組也會被取一個。
迭代:符合迭代對象的,都可以使用 for-in遍歷
包含 from collections import Iterable,使用 isinstance('abc', Iterable) 可以判斷一個對象是否是可迭代對象Iterable,如果是的話,那么就可以直接使用 for-in遍歷。
常見的迭代器對象:range 、dict、list、tuple、set、str
其中dict的迭代方式最多:
for key in d : 默認遍歷key
for value in d.values() :遍歷value
for k, v in d.items() : 遍歷key 和 value
使用?enumerate 實現下標循環: for i, value in enumerate(['A', 'B', 'C'])
使用tuple可以獲取多個變量:for x, y ,z in [(1, 1,1), (2, 4,6), (3, 9,27)]: ,但必須保證 變量個數與tuple內單個元素的length相同。
列表生成式:
用于快速生成列表的表達式(且僅能用于list),基本規則為:【 生成表達式 for - in 語句 ?】
舉例說明:[x * x for x in range(1, 11) if x % 2 == 0],這一段代碼等價于 L = list() ; for x in range(1,11): if x % 2 == 0: L.append( x * x )
即 生成表達式最終會被放入 append 函數中,但只有符合前置條件,才能到達這個位置。
支持多種循環嵌套使用,且在中括號內的函數不需要使用 : 和 ;
生成器:
是generator類型,該類型表示一個生成器對象,generator保存的是算法,每次調用next(g),就計算出g的下一個元素的值,直到計算到最后一個元素,沒有更多的元素時,拋出StopIteration的錯誤,正統函數的返回值包含在StopIteration對象的value中。
這樣可以有效的減少內存壓力
generator也是一個迭代器對象,可以用于 for-in中,且這樣遍歷更為安全,不會產生越界錯誤。
generator有兩種方式定義:
一種使用函數的方式來定義的,例如:
deffib(max):
n,?a,?b?=0,0,1
whilen?<?max:
yieldb
a,?b?=?b,?a?+?b
n?=?n?+1
return'done'
如果一個函數定義中包含yield關鍵字,那么這個函數就不再是一個普通函數,而是一個generator,generator和函數的執行流程不一樣。函數是順序執行,遇到return語句或者最后一行函數語句就返回。而變成generator的函數,在每次調用next()的時候執行,遇到yield語句返回,再次執行時從上次返回的yield語句處繼續執行。
一種是只要把一個列表生成式的[]改成(),就創建了一個generator。
迭代器:
主要分為兩種類型:
一類是集合數據類型,如list、tuple、dict、set、str等,這些都是Iterable對象,可以通過iter()函數轉化一個Iterator對象。
一類是generator,包括生成器和帶yield的generator function,這些本身就是Iterator對象;
Iterable類型:可以用于for循環
Iterator類型:不止可以用于for循環,還可以用你next 獲取下一個元素。
Python的for-in循環本質上就是通過不斷調用next()函數實現的,在遇到exception時break。
函數式編程:
函數式編程簡介:https://github.com/justinyhuang/Functional-Programming-For-The-Rest-of-Us-Cn/blob/master/FunctionalProgrammingForTheRestOfUs.cn.md
函數式編程的特點:
其與數學公式是相對應的,特別是當我們使用generator的時候,他可能就是一組符合公式的無窮數組。
它是惰性求值的,我們不需要擔心內存問題。
它的函數也是對象,是一等公民。我們可以把函數作為對象傳入或輸出,更可以結合 lambda表達式創造可變函數返回對象:(例如)
def_not_divisible(n):
returnlambdax:?x?%?n?>0
函數本身也是變量,即變量可以指向函數。函數名也是變量,一旦被重新賦值,就不再指向原來的函數,而是指向新的變量。其類型為。
一個函數就可以接收另一個函數作為參數,這種函數就稱之為高階函數。
常用系統高階函數:
map( func, iterable )
將func 應用于iterable中的每一個元素,并返回一個 iterator。
注意,由于返回的是?iterator,因此是惰性求值的,如果我們希望等到一個已運算完成的數據集合,需要使用 list(?iterator ),即將?iterator list化。
reduce( func,?iterable ):
表示 func( x,y ) ,其中x是上次運算的結果,y為下一個元素,首次時x,y分別為前兩個元素。這是一種歸納求值的操作。
注意,reduce() 需要包含?from functools import reduce ,方能使用。
注意,由于返回的是?iterator,因此是惰性求值的,如果我們希望等到一個已運算完成的數據集合,需要使用 list(?iterator ),即將?iterator list化。
filter( func , iterable ):
filter()函數用于過濾序列
filter()也接收一個函數和一個序列。和map()不同的是,filter()把傳入的函數依次作用于每個元素,然后根據返回值是True還是False決定保留還是丟棄該元素.
注意,由于返回的是?iterator,因此是惰性求值的,如果我們希望等到一個已運算完成的數據集合,需要使用 list(?iterator ),即將?iterator list化。
請參見:http://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/001431821084171d2e0f22e7cc24305ae03aa0214d0ef29000里面關于素數篩選的例子非常好的詮釋了函數式編程的特點和優勢,雖然我還不明白它編譯器要怎么做,但確實是很不一樣的編程思路。
sorted(….):
這是一個排序函數,且支持傳入預操作函數和排序順序。
有兩類sorted函數:(在python3中 cmp函數被移除)
sorted(iterable, key=None, reverse=False)
L.sort( key=None, reverse=False)
其中的key可以使用 lambda表達式: 比如 key= lambda x:x["xxx"] ,即 x表示一個元素, 冒號后面返回參與比較的元素
iterableb表示迭代器對象,key函數確定作為排序依據的key值,將會在排序前作用于每一個元素并取得這個元素的key值,然后根據這個key值進行排序,reverse表示是否反序。
需要注意的是,sorted函數不會影響list中元素的值,只會影響其排序關系。
內部函數與返回函數:
通常返回函數都是內部函數,這些內部函數可以捕獲外部變量被自己使用。這些特性稱為閉包。
返回的函數并沒有立刻執行,而是直到調用了f()才執行
這些捕獲的變量通常會指向同一塊內存地址,因此會導致外部變量變化時,捕獲變量也一起變化。
返回函數不要引用任何循環變量,或者后續會發生變化的變量。否則會導致函數難以維護以及內存泄露。
如果一定要引用循環變量:方法是再創建一個函數,用該函數的參數綁定循環變量當前的值,無論該循環變量后續如何更改,已綁定到函數參數的值不變:
匿名函數:
python對lambda提供有限的支持。
匿名函數有個限制,就是只能有一句表達式,不用寫return,返回值就是該表達式的結果
可以把匿名函數作為返回值返回
形式:lambda 【paramter】: 【表達式】
裝飾器:
這種在代碼運行期間動態增加功能的方式,稱之為“裝飾器”(Decorator)
wrapper()函數的參數定義是(*args, **kw),因此,wrapper()函數可以接受任意參數的調用。
decorator()函數的參數定義是(func),不能附加其他參數,這是規范。如果希望傳入外界變量給裝飾器函數使用,那么就需要外界再套一個函數,這樣避免循環引用。
裝飾器函數根據是否需要捕獲外界變量分為兩種:
不捕獲外界變量:
捕獲外界變量:它所能捕獲的參數僅限于log函數的傳入參數。這里需要使用三層的原因,是由于@的展開式導致的,可以看一下下面關于@展開格式的論述。(注意,@展開式是固定的)
函數也是對象,它有__name__等屬性,但你去看經過decorator裝飾之后的函數,它們的__name__已經從原來的'now'變成了'wrapper'。因為返回的那個wrapper()函數名字 就是'wrapper', 所以,需要把原始函 數的__name__等屬 性復制到 wrapper()函數中,否則,有些依賴函數簽名的代碼執行就會出錯。
這句話的本質其實就是def now ….; now = log(now)。其實就是對@xxx做了一次調用。如果是@log(“asa”)則變成 now = log(“asa”)( now ) 的調用形式。最后結果一定要是返回 wrapper函數。
更多內容可以參考:pycharm/python3/LearnDecorator.
裝飾器的用法:
先在前面定義相應的裝飾器函數,根據是否需要使用額外的外部變量,采取上面兩張寫法中的一種。
使用@裝飾器函數名字,如果有參數的話,在此處還有傳入參數。
緊接著上面這行代碼,定義需要使用到函數
為裝飾器函數改名:只需記住在定義wrapper()的前面加上@functools.wraps(func)即可。需要預先
importfunctools.
偏函數:
當函數的參數個數太多,需要簡化時,使用functools.partial可以創建一個新的函數,這個新函數可以固定住原函數的部分參數,從而在調用時更簡單。
int2 = functools.partial(int, base=2)? --- int2('1000000') => int2('1000000', base=2)
被設置的默認參數依然可以繼續被覆蓋
代碼調試:
if __name__=='__main__’:?test() ? 。?當我們在命令行運行hello模塊文件時,Python解釋器把一個特殊變量__name__置為__main__,而如果在其他地方導入該hello模塊時,if判斷將失敗,因此,這種if測試可以讓一個模塊通過命令行運行時執行一些額外的代碼,最常見的就是運行測試。
命名規范:
變量命名:
全局變量:一定要在前面加上”G_" 前綴
不可變變量:一定要加上 “C_” 前綴
全局不可變變量:加上 “GC_” 前綴
臨時變量:可以隨意命名,采用駝峰命名法
函數命名:
本地函數:
外部可見引用函數: