流暢的python筆記

鴨子類型協議不徹底總結
序列:len,getitem
切片:getitem
v[0]份量的取值和寫值:getitem和setitem
v.x屬性的取值和寫值:getattr和setattr
迭代:1)iter,2)getitem
上下文管理器:enter,exit
+=:1)iadd,2)add
可散列:hash,eq
in測試:1)contains,2)iter,3)getitempython

 

第一章,python數據模型
__repr__獲得對象的字符串表現形式
if obj,實際執行的是bool(obj),python解釋器調用obj.__bool__,若是沒有__bool__,會調用__len__看是否爲0
len(obj),python解釋器調用obj.__len__()
obj[key],python解釋器調用obj.__getitem__(key)
'hello world %s' % x, 'hello world %r' % x ,對於x=123二者輸出都同樣,x='abc'前者輸出hello world abc,後者輸出hellow world 'abc' 編程

 

第二章,序列構成的數組
容器序列:引用,list、tuple、collections.deque
扁平序列:值,str、bytes、array.array
可變序列:list、array.array
不可變序列:tuple、str
*args :序列中的值
args:序列
列表推導再也不會有變量泄漏的問題
元組拆包:_,a, b, *args = [1, 2, 3, 4, 5, 6],不要的能夠用_或者*args
切片實際操做步驟:首先生成切片對象slice(a, b, c),再使用__getitem__方法取值
序列使用 + 和 * 時,原序列都不會被修改,而是新建序列
建立3個空列表:應該使用[[] for i in range(3)],而不是使用[[]] * 3
array.array:浮點數效率高
set:in測試效率高設計模式

 

第三章,字典和集合
用戶自定義類型的對象都是可散列的,散列值就是id()返回的值
dict.get(k, w):查找key時,設置默認
dict.setdefault(k, w):更新key時,設置默認
defaultdict(type):能夠設置字典value的缺省類型,例如list
__missing__:找不到key時會調用__missing__特殊方法
集合沒有getitem,可是有iter數組

 

第四章,文本和字節序列
待補充多線程

 

第五章,一等函數
函數本質上就是定義了__call__的類,此外還有些函數特有的屬性,例如__kwdefaults__,__defaults__,__get__等等
建議用生成器表達式取代map,filter
匿名函數lambda,主要適用於傳參,能夠省略函數名
operator:提供了一些算數運算符函數,例如相乘mul
functools.partial(func, arg):用於凍結參數,func是可調用對象,arg是凍結的參數閉包

 

第六章,使用一等函數實現設計模式
用類實現策略模式:用類實現具體策略,相同部分做爲基類,不一樣部分做爲子類
用函數實現策略模式:用函數實現具體的策略,函數做爲參數傳遞給類的實例併發

 

第七章,函數裝飾器和閉包
自由變量:未在本地做用域中綁定的變量,能夠被內部嵌套函數訪問,並能保留下來的
nonlocal:聲明變量爲自由變量
基本裝飾器(2層嵌套):必須return2次,若是隻return wrapper,則被裝飾函數有返回值時會永遠返回None
參數化裝飾器(3層嵌套):支持裝飾器傳參app

基本裝飾器代碼實現:異步

def clock(fn):
    @functools.wraps()
    def wrapper(*arg, **kwargs):
        ret = fn(*arg, **kwargs)
        return ret
    return wrapper    

 

第八章,對象引用、可變性和垃圾回收
變量是標註,不是盒子:引用式變量(例如列表、字典)能夠同時有多個不一樣的變量名
引用性變量的不一樣變量名,值/id都是相等的
python的'==':只判斷值是否相等,id能夠不等。有點相似js的'==='
能夠用is判斷id是否相同,沒必要使用id()函數
元組的不可變性:保存的引用不可變,可是引用的對象能夠變
建立別名:b = lista
淺複製:b = lista[:],b = lista.copy(),b= copy.copy(lista)
深複製:b= copy.deepcopy(lista)
若是lista列表內部有「可變的引用對象」(例如字典、集合、列表,元組算不可變的引用對象),發生改變時,會影響到淺拷貝,但不會影響到深拷貝。
防護可變參數:函數傳參時,可變參數的默認值必須使用None。若是使用可變參數做爲默認值,則不傳參時,多個函數調用方會共享同一個可變參數。
python是按引用傳參的,對參數修改後:1)不可變參數會從新開闢內存,實質至關於傳統的按值傳參;2)可變參數會就地修改,實質至關於傳統的按引用傳參。async

 

第九章,符合python風格的對象
儘早捕獲錯誤:若是涉及到參數轉換,在__init__中完成能夠儘早捕獲錯誤
classmethod:靜態函數,第一個參數是類,能夠調用類屬性/類方法
staticmethod:靜態函數,沒有特殊參數,本質上就是放在類中的全局函數
格式化:format
私有屬性:__x能夠經過「object_classname__x」來訪問,因此本質上單下劃線和雙下劃線沒什麼區別
屬性設置爲只讀:私有屬性 + @property
__slots__屬性:節省空間,使用後沒法新增屬性

 

第十章,序列的修改、散片和切片
獲取類的引用方法:type(self),self.__class__,被@classmethod裝飾的函數的第一個參數。要訪問類變量,必須先獲取類的引用。
實現了一個多維向量類(序列):
  v1:兼容2d,一些基本的序列方法
  v2:實現getitem,支持份量訪問、切片訪問。沒有實現setitem,因此不支持份量設值、切片設值。
  v3:實現getattr和setattr,支持屬性訪問,setattr必須同時實現,不然對屬性進行設值後(v.x)會與份量值(v[0])產生衝突
  v4:實現eq和hash,可散列
  v5:格式化

 

第十一章,從協議到抽象基類
鴨子類型:協議是非正式的接口
白鵝類型:使用抽象基類正式明確接口
abc:自定義抽象基類,抽象方法
collections.abc:提供一些內置的抽象基類
numbers:抽象基類數字塔。包括Number,Complex,Real,Rational,Intergral。
抽象基類(abc.ABC):抽象基類必須繼承abc.ABC,才能約束子類必須實現抽象方法,抽象基類不能被實例化
抽象方法(@abc.abstractmethod):抽象基類的抽象方法,不用實現,子類繼承抽象基類時必須實現抽象方法,才能被實例化
抽象基類主要做用:做爲超類;isinstance檢查;註冊(xx.register);自動識別(不用註冊或繼承也能經過isinstance檢查)
isinstance檢查舉例:collections.abc.Sequence抽象基類包含的方法有__contains__,__iter__,__len__,__getitem__,__reversed__,index,count,其中抽象方法是__len__,__getitem__。若是某對象想經過isinstance(obj, collections.abc.Sequence)檢查,方法一是繼承Sequence並實現2個抽象方法,方法二是本身實現全部的方法,並註冊Sequence.register。
猴子補丁:直接給類(注意不是類的實例)添加新的方法。這樣能夠在運行時修改類或模塊,而不改動源碼。
python是動態強類型語言:動態指運行時檢查類型,強類型指不多隱式轉換類型。

 

第十二章,繼承的優缺點
內置類型字典更新值的方法:
DoppeDict(one=1):調用__init__()
DoppeDict['two'] = 2:設置時調用__setitem__(),獲取時調用__getitem__()
DoppeDict.update('three', 3):調用update(),
子類化內置類型時,不會調用用戶定義的類覆蓋的特殊方法
多重繼承:廣度優先,深度優先,python3是廣度優先
委託給父類執行:super().func(),多重繼承時能夠指定由哪一個父類執行xx.func()
繼承UserDict, UserList, UseString:速度慢,以擴展
繼承Dict, List, String:速度快,難擴展

 

第十三章,正確重載運算符
一元: -neg,+pos,~invert
算術: +add,
比較: ==eq,!=ne
增量賦值: +=iadd
運算時,先正向,後反向,比較運算還會比較id,經過返回NotImplemented切換
python3.5新引入@作點積運算

 

第十四章,可迭代的對象、迭代器和生成器
iterable具備可調用的iterator,能夠經過iter(iterable)從iterable中得到iterator。
iterator的實現方法:1)iter + next,其中iter方法中return self,next方法中逐個返回值。2)iter,iter方法中使用yield生成器返回值。
generator屬於iterator。
Sequence實現了getitem和len特殊方法就能夠被迭代,由於解釋器在嘗試迭代對象x時,會執行以下步驟:1)調用iter(x);2)沒有iter就調用getitem;
StopIteration表示迭代器到頭。
典型的迭代器:2個類,iterable和iterator做爲2個類分開實現,iterable中的iter返回iterator;iterator中的iter返回self,next逐個返回值。
糟糕的迭代器:1個類,同時在iterable中實現了iterator,即iterable中的iter返回self,同時具備next方法逐個返回值。
生成器:1個類,iterable的iter返回yield生成器。
惰性生成器:1個類,iterable的iter返回yield生成器,可是生成器的內容是惰性獲取,例如獲取文本時由finditer替代findall。
生成器表達式:1個類,iterable的iter返回一個生成器表達式。
多層for循環時,能夠用yield from替代內層for循環

 

第十五章,上下文管理器和else塊
用法:with xxx as yyy
支持同時打開兩個對象:with xxx as yyy, aaa as bbb
上下文管理器協議:__enter__方法中返回yyy(沒有提供內容時直接返回None),__exit__方法中作好退出釋放資源操做

 

第十六章,協程
進程:有獨立內存空間。
線程:CPU調度最小單位,共享內存。
協程:用戶態的輕量級線程,上下文切換塊,CPU感知不到協程,只使用一個線程。
在其餘語言中,協程意義不大,能夠經過多線程解決I/O,可是python有GIL多線程也是僞多線程,同一時間只能有一個線程,同步編程I/O阻塞稱爲瓶頸,能夠用協程處理高I/O操做。
同步編程併發:單純經過多進程和多進程進行同步編程,切換線程和切換進程有開銷,還須要解決進程間/線程間資源交互問題。
異步編程併發:協程,回調。
協程: a = yield b,先執行b產出值;再執行a賦值;能夠沒有a,即只產出不賦值(生成器);能夠沒有b,即只賦值不產出值(最後一塊兒返回)。
協程流程:
1)預激:手動next; 裝飾器; yield from;
2)發送至:send;
3)關閉:發送哨符值; close(); throw()輸入未捕捉的異常
4)異常處理:throw()輸入except捕捉的異常
5) 獲取協程返回值:PEP380定義; yield from;

 

第十七章,使用future處理併發
I/O密集型:多線程threading —> futures.ThreadPoolExecutor
CPU密集型:多進程multiprocessing —> futures.ProcessExecutor
python有GIL,同一時間只能容許一個線程執行python字節碼,而線程是調度CPU的最小單位,所以多線程沒法知足CPU密集型操做。其餘語言開啓多線程能夠調度多個CPU的能夠知足CPU密集型操做。
futures多進程/多線程處理方法:
map:所有完成後獲取結果,再執行後續代碼,只能處理相同的函數(函數參數能夠不一樣)
submit + as_completed:有完成的就先獲取結果,可處理不一樣函數

 

第十八章,使用asyncio包處理併發
asyncio用於異步IO
python3.5開始引入了新語法async和await:@asyncio.coroutine替換爲async def …,yield from替換爲await



第十九章,動態屬性和特性
若是想把屬性x變成只讀:能夠經過@property完成,特性名稱須要與init中靜態屬性名稱不一樣,由於若是相同沒有提供setter方法沒法完成賦值。
若是想限制靜態屬性:能夠增長@x.setter裝飾同名函數,靜態屬性名稱self.x,@property特性名稱x,@x.setter裝飾的名稱x三者相同,這時setter中的函數能夠實現一些限制和驗證操做,若是不作這些操做那就能夠不用property和setter。



第二十章,屬性描述符
限制靜態屬性的方法:
1)init函數中判斷並raise error,缺點是隻有實例化時有效,實例化後沒法限制對屬性進行更改
2)@property + @xx.setter,缺點是不能重複使用,有多個屬性想限制時代碼量會很是大
3)描述符

 

第二十一章,元類編程待補充

相關文章
相關標籤/搜索