內(nèi)容全部都是手動(dòng)整理,里邊避免不了有錯(cuò)誤,歡迎指出,歡迎討論!
__repr__
方法是將對(duì)象用字符串的形式表達(dá)出來,repr()函數(shù)實(shí)際調(diào)用的就是這個(gè)模仿方法, 在控制臺(tái)中打印實(shí)例對(duì)象的信息就是用的這個(gè)方法.__str__
是在str()函數(shù)中被調(diào)用,或者用print()時(shí)被調(diào)用. 如果類中沒有實(shí)現(xiàn)__str__
時(shí),解釋器會(huì)用__repr__
作為替代.python2中列表推導(dǎo)式中的變量會(huì)覆蓋推導(dǎo)式以外的變量,python3中不會(huì).(for循環(huán)中還是會(huì)污染for循環(huán)以外的變量屠橄。)
元組中的每個(gè)元素都存放了記錄中一個(gè)字段的數(shù)據(jù),因?yàn)槠洳豢勺冃?其字段的位置信息給數(shù)據(jù)有了其他意義.(如果在任何的表達(dá)式里我們?cè)谠M內(nèi)對(duì)元素排序,這些元素的位置信息就會(huì)丟失)
不要把可變類型放到元組里邊.不然改動(dòng)可變類型的時(shí)候會(huì)有奇跡出現(xiàn)
list.sort 方法是列表就地排序,不會(huì)創(chuàng)建新的list. sorted()方法不管接受的是什么參數(shù),排序結(jié)束都會(huì)返回一個(gè)list.
原子不可變數(shù)據(jù)類型都是可散列類型, frozenset也是可散列的.
不可變類型里包含的數(shù)據(jù)必須都是不可變類型才可以被散列(這里說的還是元組里邊包含可變類型).
字典的變種: collection.OrderedDict 保序詞典 collections.ChainMap 可以包含多個(gè)dict, 在查找的時(shí)候可以挨個(gè)字典查找,直到找到為止. collections.Counter 統(tǒng)計(jì)鍵的次數(shù),返回的也是字典.
collections.UserDict 用戶繼承的字典類型,用于自己構(gòu)建自己的字典類型.set是不可散列的數(shù)據(jù)類型. frozenset是可以散列的類型.
高階函數(shù):接受函數(shù)為參數(shù),或者把函數(shù)作為結(jié)果返回的函數(shù).
python種的可調(diào)用對(duì)象: 函數(shù)、內(nèi)置函數(shù)膝昆、類嘱兼、方法神汹、內(nèi)置方法粥血、類的實(shí)例、生成器函數(shù). 判斷對(duì)象是否可以調(diào)用,最安全的方式是使用內(nèi)置的callable()函數(shù).
用戶定義可調(diào)用類型 需要實(shí)現(xiàn)實(shí)例方法
__call__
實(shí)現(xiàn)__call__
方法的類是創(chuàng)建函數(shù)類對(duì)象的簡(jiǎn)便方法.形參放到*后邊,必須以關(guān)鍵字參數(shù)傳參. 如 def a(b, *, c) , 形參c必須以關(guān)鍵字參數(shù)傳參,不然會(huì)報(bào)錯(cuò).
函數(shù)對(duì)象有個(gè)
__defaults__
屬性,值為一個(gè)元組,里邊保存著定位參數(shù)和關(guān)鍵字參數(shù)的默認(rèn)值,關(guān)鍵字參數(shù)的默認(rèn)值在__kwdefaults__
屬性中.參數(shù)的名稱在__code__.co_varname
的屬性中,不過里面還有函數(shù)定義體中創(chuàng)建的局部變量.因此,參數(shù)名稱只是__code__.co_varname
中的前N個(gè)字符串,N的值由__code__.co_argcount
確定,然而之這里邊不包括或者*的不定長(zhǎng)參數(shù).參數(shù)的默認(rèn)值只能通過他們的__defaults__
元組中的位置確定, 因此要從后向前掃描才能把參數(shù)和默認(rèn)值對(duì)應(yīng)起來(指定了默認(rèn)值的形參一般放在普通形參的后邊,所以從后往前掃描才能對(duì)應(yīng)起來).inspect模塊 模塊提供了一些有用的函數(shù)幫助獲取對(duì)象的信息,例如模塊滴须、類台猴、方法朽合、函數(shù)俱两、回溯、幀對(duì)象以及代碼對(duì)象.
注解: python對(duì)注解不做檢查曹步、不做強(qiáng)制宪彩、不做驗(yàn)證. 唯一做的事情是把它們存儲(chǔ)在函數(shù)的
__annotations__
屬性里.函數(shù)式編程重要的兩個(gè)模塊:operator 和 functools. operator主要提供了計(jì)算的一些函數(shù).attrgetter 可以提取具名元組屬性的值. itemgetter 根據(jù)下標(biāo)提取值,還支持映射和任何實(shí)現(xiàn)
__getitem__
方法的類.多用于排序時(shí)key參數(shù)的實(shí)參.methodcaller 函數(shù)可以自行創(chuàng)建函數(shù).將方法當(dāng)作methodcaller函數(shù)的參數(shù).
functools.partial 固定函數(shù)某些參數(shù)的值 這個(gè)可以需要花時(shí)間了解.
裝飾器是可調(diào)用對(duì)象.
裝飾器的一大特性是能把被裝飾的函數(shù)替換成其他函數(shù).第二個(gè)特性是 裝飾器在加載模塊時(shí)立即執(zhí)行(即加載模塊時(shí)被裝飾的函數(shù)即被替換成裝飾器返回的函數(shù)對(duì)象),被裝飾的函數(shù)旨在明確調(diào)用的時(shí)候運(yùn)行.
閉包指延伸了作用域的函數(shù),關(guān)鍵是能訪問定義體之外定義的非全局變量.(只有嵌套在其他函數(shù)中的函數(shù)才有可能需要處理不在全局作用與中的外部變量)
自由變量: 指未在本地作用域中綁定的變量.(閉包中函數(shù)體之外的變量)
當(dāng)閉包中的自由變量為不可變類型時(shí),閉包中的函數(shù)無法對(duì)其修改.如果需要修改需要使用nonlocal進(jìn)行聲明.
裝飾器的行為: 把被裝飾的函數(shù)替換成新函數(shù),二者接受相同的參數(shù),而且返回被裝飾的函數(shù)本該返回的值.同時(shí)還會(huì)做些額外的操作.
@functools.wraps(func) 可以保證裝飾器不會(huì)對(duì)被裝飾函數(shù)造成影響.能把被裝飾的函數(shù)的屬性復(fù)制到替換函數(shù)上.
函數(shù)的注解只存在于函數(shù)的
__annotations__
屬性中.函數(shù)的默認(rèn)參數(shù)的值在函數(shù)僅僅在函數(shù)定義的時(shí)候賦值一次. 其次函數(shù)的默認(rèn)參數(shù)的默認(rèn)值應(yīng)該是不可變對(duì)象,否則在函數(shù)多次調(diào)用的時(shí)候結(jié)果不可控. 再次 默認(rèn)值為None的時(shí)候,判斷時(shí)好用is,而不是直接判斷,因?yàn)?空字符串、空列表等都會(huì)被當(dāng)作None處理.
匿名函數(shù)lambda表達(dá)式中的x是一個(gè)自由比變量,在運(yùn)行時(shí)綁定.而不是在定義時(shí)綁定,這是跟普通函數(shù)的區(qū)別.(即lambda表達(dá)式中的值只是運(yùn)行時(shí)當(dāng)下的值.)
匿名函數(shù)如何在定義時(shí)捕獲到定義的值的原理讲婚?(如:a = lambda y, x=x: x + y)
== 運(yùn)算符比較兩個(gè)對(duì)象的值(對(duì)象中保存的數(shù)據(jù)),而is比比較對(duì)象的標(biāo)識(shí).
元組的不可性其實(shí)是指tuple數(shù)據(jù)結(jié)構(gòu)的物理內(nèi)容(即保存的引用)不可變,與引用的對(duì)象是否可變無關(guān)(而str,bytes和array.array等單一類型序列是扁平的,它們保存的不是引用,而是連續(xù)內(nèi)存中保存數(shù)據(jù)本身.
原子不可變數(shù)據(jù)類型(str毯焕、bytes 和數(shù)值類型)都是可散列類 型,frozenset 也是可散列的,因?yàn)楦鶕?jù)其定義,frozenset 里只能容納可散列類型.元組的話,只有當(dāng)一個(gè)元組包含的所有元素都是可散列類型的情況下,它才是可散列的.
python唯一支持的參數(shù)傳遞模式是共享傳參.(共享傳參指的是函數(shù)的各個(gè)形式參數(shù)獲得實(shí)參中各個(gè)引用的副本,參數(shù)中可以修改變量的值,但是不會(huì)修改變量的標(biāo)識(shí)(ID))
del 不刪除對(duì)象,而是刪除對(duì)象的引用.
弱引用不會(huì)增加對(duì)象的引用數(shù)量.引用的目標(biāo)對(duì)象稱為所指對(duì)象.因此,弱引用不會(huì)妨礙所指對(duì)象被當(dāng)作垃圾回收.
每個(gè)python對(duì)象都有標(biāo)識(shí)、類型和值.只有對(duì)象的值會(huì)不時(shí)的變化.(對(duì)象的類型也可以變,方法只有一種:為
__class__
屬性指定其他類.但這是在作 惡,我后悔加上這個(gè)腳注了.)弱引用 和 深淺復(fù)制仔細(xì)研究一下.
__repr__()
方法返回一個(gè)實(shí)例的代碼表示形式.內(nèi)置的repr()和磺樱!r或%r都是調(diào)用的這個(gè)方法.這個(gè)跟交互是加濕器顯示的值一樣. str()纳猫、print()、%s調(diào)用的是__str__()
這個(gè)方法.__format__(self, format_spec)
方法是format()函數(shù)竹捉、str.format()以及f"{}"語法糖調(diào)用的方法.format_spec默認(rèn)是空字符串.其類型根據(jù)value的值進(jìn)行判斷(format(value)),它是1.format(value, format_spec)的第二個(gè)參數(shù)芜辕;2.str.format()方法的格式字符串,{}里代換字段中冒號(hào)后面的部分.python3中,
__repr__、__str__和__format__
都必須返回unicode字符串,只有__bytes__
方法應(yīng)該返回字節(jié)序列.
實(shí)現(xiàn)上下文管理協(xié)議(with),要實(shí)現(xiàn)兩個(gè)方法:
__enter__()
和__exit__()
.當(dāng)出現(xiàn)with語句的時(shí)候,__enter__()
方法被觸發(fā),它的返回值會(huì)被賦值給as后的變量.然后with語句塊的代碼開始執(zhí)行,結(jié)束后,__exit__()
方法被處罰,進(jìn)行資源回收,垃圾清理.值得注意的是不管代碼塊中是否產(chǎn)生異常,控制流都會(huì)執(zhí)行完,__exit__()
中的三個(gè)參數(shù)exc_type, exc_value, traceback在沒有異常的情況下都是None, 如有異常產(chǎn)生,中的三個(gè)參數(shù)exc_type表示錯(cuò)誤類型,exc_value表示信息,traceback表示追溯信息.產(chǎn)生異常時(shí),該方法希望抑制異常(即,防止它被傳播),則它應(yīng)該返回一個(gè)True.否則,在退出此方法時(shí)將正常處理異常.__slots__
類屬性的主要作用是通過替換實(shí)例中dict(a._class.dict)中屬性默認(rèn)的字典替換成__slots__
執(zhí)行的數(shù)據(jù)結(jié)構(gòu).有一個(gè)副作用就是:實(shí)例不能再有__slots__
之外的其他屬性.也就是說__slots__
作用是用來優(yōu)化,而不是用來限制屬性的個(gè)數(shù).在實(shí)現(xiàn)實(shí)例的弱引用,需要實(shí)現(xiàn)__weakref__
方法,并且需要將'__weakref__'
加入到__slots__
中,否則實(shí)例就不能作為弱引用的目標(biāo).雙下劃線的實(shí)例屬性以及方法都會(huì)被重命名,導(dǎo)致實(shí)例屬性以及方法無法被繼承以及無法被子類覆蓋,python這個(gè)語言特性叫做==名稱改寫==.名稱改寫只是一種保護(hù)措施,目的是避免意外訪問.
@classmethod
裝飾器修飾符對(duì)應(yīng)的函數(shù)不需要實(shí)例化,不需要self參數(shù),第一個(gè)參數(shù)需要表式類自身的cls參數(shù),可以用來調(diào)用類屬性,類方法,實(shí)例化對(duì)象等.classmethod
最常見的用途式定義備選構(gòu)造方法.staticmethod
裝飾器也會(huì)改變方法的調(diào)用方式,但是第一個(gè)參數(shù)不是特殊的值,簡(jiǎn)單的講,就是一個(gè)普通的函數(shù)封裝到類里邊了.一個(gè)類要實(shí)現(xiàn)
__hash__
方法,需要考慮的地方:1.屬性不可變 2.要是現(xiàn)__eq__
方法,因?yàn)橄嗟鹊膶?duì)象應(yīng)該具有相同的散列值..@property
裝飾器,一般是將一個(gè)獲取值的方法變成屬性.訪問property裝飾器的時(shí)候會(huì)自動(dòng)觸發(fā)getter块差、setter侵续、deleter方法.只需要將setter、deleter所裝飾的方法跟property所裝飾的實(shí)例方法的名稱相同就可以.類屬性可用于為實(shí)例屬性提供默認(rèn)值(實(shí)例可以訪問類屬性).類屬性可以繼承,子類的同名類屬性會(huì)覆蓋父類中的同名類屬性.
reprlib.repr 會(huì)將超過6個(gè)分量的數(shù)據(jù),repr()生成的字符串就會(huì)使用...省略一部分.
在面向?qū)ο缶幊讨?協(xié)議是非正式的接口,只在文檔中定義,在代碼中不定義.
indices 方法開放了內(nèi)置序列實(shí)現(xiàn)的棘手邏輯,用于優(yōu)雅地處理缺失索引和負(fù) 數(shù)索引,以及長(zhǎng)度超過目標(biāo)序列的切片.這個(gè)方法會(huì)“整頓”元組,把 start憨闰、stop 和 stride 都變成非負(fù)數(shù),而且都落在指定長(zhǎng)度序列的邊界內(nèi).
__getitem__
是實(shí)現(xiàn)序列下標(biāo)取值状蜗、切片的必要實(shí)現(xiàn)的方法.其參數(shù)item可以是數(shù)字或者切片對(duì)象slice.__getattr__
是實(shí)例獲取實(shí)例屬性所調(diào)用的方法.__setattr__
是對(duì)實(shí)例屬性設(shè)置值所調(diào)用的方法.多數(shù)情況下,在類中實(shí)現(xiàn)了__getattr__
方法的同時(shí),那么也要實(shí)現(xiàn)__setattr__
方法,以防讀取以及賦值的行為不一致.itertools.zip_longes 函數(shù),使用可選的fillvalue(默認(rèn)值為None)填充缺失值.因此可以繼續(xù)產(chǎn)出,直到最長(zhǎng)的可迭代對(duì)象耗盡.
super()
函數(shù),可以在子類中調(diào)用父類(超類)中某個(gè)已經(jīng)被覆蓋的方法.super()
函數(shù)的一個(gè)常見的用法是在__init__()
方法中取保父類被正確的初始化.另一個(gè)常見的用法出現(xiàn)在覆蓋python特殊方法(魔術(shù)方法)的代碼中.關(guān)于類的
__mro__
MRO表(方法解析順序表)表.這個(gè)列表就是一個(gè)簡(jiǎn)單的所有基類順序列表.為了實(shí)現(xiàn)繼承, Python會(huì)在MRO列表上從左到右開始查找基類,直到找到第一個(gè)匹配這個(gè)屬性的類為止.MRO列表遵循三條準(zhǔn)則:1. 子類會(huì)先于父類被檢查 2. 多個(gè)父類會(huì)根據(jù)它們?cè)诹斜碇械捻樞虮粰z查. 3.如果對(duì)下一個(gè)類存在的兩個(gè)合法的選擇,選擇第一個(gè)父類. 簡(jiǎn)單的講,super() 方法會(huì)順序線性的從MRO表中查找制定的基類.如果找到的基類中同樣調(diào)用了super()方法,那么會(huì)接著順序的往下查找,直到所選擇的基類中不再調(diào)用super() 為止.
迭代器和可迭代對(duì)象的區(qū)別:1.迭代對(duì)象中需要實(shí)現(xiàn)
__iter__()
或者__getitem__()
方法,當(dāng)使用item()內(nèi)置函數(shù)調(diào)用時(shí),默認(rèn)使用__iter__()
,如果不存在會(huì)調(diào)用__getitem__()
,返回一個(gè)迭代器.2. 迭代器中需要實(shí)現(xiàn)__next__()
和__iter__()
方法,也就是說迭代器需要可以用next()函數(shù)進(jìn)行取值.可變類型必須實(shí)現(xiàn)
__setitem__()
方法.猴子補(bǔ)丁:在運(yùn)行時(shí)修改類或模塊,而不改動(dòng)源碼.
抽象基類提供了一種要求子類實(shí)現(xiàn)指定協(xié)議的方式,如果一個(gè)抽象基類要求實(shí)現(xiàn)指定的方法,而子類沒有實(shí)現(xiàn)的話,當(dāng)試圖創(chuàng)建子類或者執(zhí)行子類代碼時(shí)會(huì)拋出異常.
抽象類的作用:抽象類是不能(至少是不應(yīng)該)實(shí)例化的類,其職責(zé)是定義子類應(yīng)實(shí)現(xiàn)的一組抽象方法.抽象類不能實(shí)例化,從抽象類派生出一個(gè)子類,如果沒有重寫所有抽象方法,則這個(gè)類也是抽象的,不能實(shí)例化. 抽象類提供了邏輯和實(shí)現(xiàn)解耦的能力,即抽象類定義模塊提供的功能,在具體實(shí)現(xiàn)類來提供實(shí)現(xiàn),這樣在不同的模塊中通過抽象類來調(diào)用,可以用最精簡(jiǎn)的方式展示出代碼之間的邏輯關(guān)系,讓模塊之間的依賴清晰簡(jiǎn)單.同時(shí),一個(gè)抽象類可以有多個(gè)實(shí)現(xiàn),讓系統(tǒng)的運(yùn)轉(zhuǎn)更加靈活.而針對(duì)抽象類的編程,讓每個(gè)人可以關(guān)注當(dāng)前抽象類,只關(guān)注其方法和描述,而不需要考慮過多的其他邏輯,這對(duì)協(xié)同開發(fā)有很大意義.極簡(jiǎn)版的抽象類實(shí)現(xiàn),也讓代碼可讀性更高.
抽象類的實(shí)現(xiàn):Python為了實(shí)現(xiàn)抽象類的支持,支持定義抽象基類(Abstract Base Class),Python使用模塊abc提供了抽象基類的支撐能力.抽象基類用于指定子類必須提供哪些功能,卻不實(shí)現(xiàn)這些功能.抽象基類提供基本類和最基本的抽象方法,可以為子類定義共有的方法,但不需要具體實(shí)現(xiàn),但子類中必須實(shí)現(xiàn)抽象方法,否則會(huì)報(bào)錯(cuò).
抽像類的真實(shí)子類和虛擬子類:==真實(shí)子類==就是直接從抽象基類中派生,抽象基類中可以定義”抽象方法“和“抽象屬性”, 抽象基類可以不實(shí)現(xiàn)具體的方法,也可以實(shí)現(xiàn)部分,子類繼承抽象基類的抽象內(nèi)容并實(shí)現(xiàn),只有完全重寫了抽象基類中的“抽象”內(nèi)容后,才能被實(shí)例化,如果有個(gè)抽象內(nèi)容沒有重寫則子類本身也是抽象類,不能實(shí)例化.==虛擬子類==是將其他的不是從抽象基類派生的類”注冊(cè)“到抽象基類,讓Python解釋器將該類作為抽象基類的子類使用,因此稱為虛擬子類,這樣第三方類不需要直接繼承自抽象基類.注冊(cè)的虛擬子類不論是否實(shí)現(xiàn)抽象基類中的抽象內(nèi)容,Python都認(rèn)為它是抽象基類的子類,調(diào)用 issubclass(子類,抽象基類),isinstance (子類對(duì)象,抽象基類)都會(huì)返回True.
這種通過注冊(cè)增加虛擬子類是抽象基類動(dòng)態(tài)性的體現(xiàn),也是符合Python風(fēng)格的方式.它允許我們動(dòng)態(tài)地,清晰地改變類的屬別關(guān)系.當(dāng)一個(gè)類繼承自抽象基類時(shí),該類必須完成抽象基類定義的語義鹉动;當(dāng)一個(gè)類注冊(cè)為虛擬子類時(shí),這種限制則不再有約束力,可以由程序開發(fā)人員自己約束自己,因此提供了更好的靈活性與擴(kuò)展性(當(dāng)然也帶來了一些意外的問題).這種能力在框架程序使用第三方插件時(shí),采用虛擬子類即可以明晰接口,只要第三方插件能夠提供框架程序要求的接口,不管其類型是什么,都可以使用抽象基類去調(diào)用相關(guān)能力,又不會(huì)影響框架程序去兼容外部接口的內(nèi)部實(shí)現(xiàn).老猿認(rèn)為,從某種程度上講,虛擬子類這種模式,是在繼承這種模式下的一種多態(tài)實(shí)現(xiàn).參考真實(shí)子類和虛擬子類的文章
迭代器模式:一種惰性獲取數(shù)據(jù)項(xiàng)的方式,即按需一次獲取一個(gè)數(shù)據(jù)項(xiàng).
所有的生成器都是迭代器,因?yàn)樯善魍耆珜?shí)現(xiàn)了迭代器接口.
在python中,所有的集合都可以迭代. 迭代器用于支持:1. for循環(huán).2.構(gòu)建和拓展結(jié)合類型.3:逐行遍歷文本文件.4:列表推導(dǎo)轧坎、字典推導(dǎo)和集合推導(dǎo).5.元組拆包.6.使用*進(jìn)行拆包.
內(nèi)置
iter()
函數(shù)的作用:1.檢查對(duì)象是否實(shí)現(xiàn)了__iter__
方法,如果實(shí)現(xiàn)了就調(diào)用,并返回一個(gè)迭代器.2.如果沒有實(shí)現(xiàn)__iter__
方法,但是實(shí)現(xiàn)了__getitem__
,python會(huì)創(chuàng)建一個(gè)迭代器,嘗試使用下標(biāo)(從0開始)獲取元素.3. 如果嘗試失敗,Python 拋出 TypeError 異常.任何 Python 序列都可迭代的原因是,它們都實(shí)現(xiàn)了
__getitem__
方法.其實(shí),標(biāo)準(zhǔn)的序 列也都實(shí)現(xiàn)了__iter__
方法,因此你也應(yīng)該這么做.之所以對(duì)__getitem__
方法做特殊處 理,是為了向后兼容.可迭代對(duì)象不一定能通過issubclass測(cè)試,只有實(shí)現(xiàn)了
__iter__
方法的對(duì)象才能通過測(cè)試.只實(shí)現(xiàn)了__getitem__
方法的可迭代對(duì)象無法通過測(cè)試.檢查==對(duì)象x能否迭代(這里說的不是迭代器,而是能否迭代)==,最準(zhǔn)確的方法是iter()函數(shù),如果不可迭代,再處理TypeError異常.這比使用isinstance(x, abc.Iterable)更準(zhǔn)確,因?yàn)閕ter(x)會(huì)考慮遺留的__getitem__
方法.標(biāo)準(zhǔn)的迭代器接口有兩個(gè)方法:
__next__()
(返回下一個(gè)可用的元素,如果沒有元素了,拋出 StopIteration 異常.)和__iter__()
(返回實(shí)例self本身).迭代器是這樣的對(duì)象:實(shí)現(xiàn)了無參數(shù)的
__next__
方法,返回下序列中的下一個(gè)元素;如果沒有元素了,那么拋出StopIteration異常.迭代器中還實(shí)現(xiàn)了__iter__
方法,因此迭代器也可以迭代.迭代器可以迭代,但是可迭代對(duì)象不是迭代器.
可迭代對(duì)象有個(gè)
__iter__
方法,每次實(shí)例化得到一個(gè)一個(gè)新得迭代器泽示;而實(shí)現(xiàn)迭代器需要實(shí)現(xiàn)__next__
方法,返回序列中得下一個(gè)元素,此外還要實(shí)現(xiàn)__iter__
,返回迭代器本身.可迭代得對(duì)象一能是自身得迭代器.也就是說,可迭代對(duì)象必須實(shí)現(xiàn)
__iter__
方法,但不能實(shí)現(xiàn)__next__
方法.另一方面,迭代器應(yīng)該一直可以迭代.迭代器的__iter__
應(yīng)該返回自身.
- iter()函數(shù),傳入兩個(gè)參數(shù)時(shí),使用常規(guī)的函數(shù)或任何可調(diào) 用的對(duì)象創(chuàng)建迭代器.這樣使用時(shí),第一個(gè)參數(shù)必須是可調(diào)用的對(duì)象,用于不斷調(diào)用(沒 有參數(shù)),產(chǎn)出各個(gè)值;第二個(gè)值是哨符,這是個(gè)標(biāo)記值,當(dāng)可調(diào)用的對(duì)象返回這個(gè)值時(shí), 觸發(fā)迭代器拋出 StopIteration 異常,而不產(chǎn)出哨符.
.throw(...) 作用是讓調(diào)用方法拋出異常,在生成器中處理..close(...)的作用是終止生成器.
協(xié)程的四個(gè)狀態(tài):
GEN_CREATED
:等待開始執(zhí)行(未激活狀態(tài))GEN_RUNNING
:正在執(zhí)行GEN_SUSPENDED
在yield處暫停狀態(tài)GEN_CLOSED
執(zhí)行結(jié)束.協(xié)程需要用next()或者用.send(None)進(jìn)行預(yù)激活,如果用send()激活,傳入None之外的值,會(huì)報(bào)錯(cuò).
使用yield from時(shí)會(huì)自動(dòng)預(yù)激子協(xié)程,而不會(huì)預(yù)激委派生成器,需要手動(dòng)預(yù)激委派生成器. 在python3.4+版本中的 asyncio.coroutine 不會(huì)預(yù)激攜程,所以能與yield from 兼容.
值得注意的是:1.子生成器產(chǎn)出的值都直接傳給委派生成器的調(diào)用方. 2.使用send()方法發(fā)給委派生成器的值都直接傳給子生成器.如果發(fā)送的值為None,那么調(diào)用子生成器的
__next__()
方法.如果發(fā)送的值不是None,那么會(huì)調(diào)用子生成器的send()
方法.如果調(diào)用的方法拋出StopIteration異常,那么委派生成器恢復(fù)運(yùn)行,其他的錯(cuò)誤會(huì)向上冒泡,傳給委派生成.3.生成器退出時(shí),生成器(或子生成器)中的 return expr 表達(dá)式會(huì)觸發(fā) StopIteration(expr)
異常拋出.4.yield from 表達(dá)式的值是子生成器終止時(shí)傳給 StopIteration 異常的第一個(gè)參數(shù).
可以在生成器對(duì)象上調(diào)用兩個(gè)方法,顯示地把異常發(fā)給協(xié)程:
generator.throw(exc_type[, exc_value[, traceback]])
致使生成器在暫停的 yield 表達(dá)式處拋出指定的異常.如果生成器處理了拋出的異常, 代碼會(huì)向前執(zhí)行到下一個(gè) yield 表達(dá)式,而產(chǎn)出的值會(huì)成為調(diào)用 generator.throw 方法 得到的返回值.如果生成器沒有處理拋出的異常,異常會(huì)向上冒泡,傳到調(diào)用方的上下 文中.
generator.close()
致使生成器在暫停的 yield 表達(dá)式處拋出 GeneratorExit 異常.如果生成器沒有處 理這個(gè)異常,或者拋出了 StopIteration 異常(通常是指運(yùn)行到結(jié)尾),調(diào)用方不會(huì) 報(bào)錯(cuò).如果收到 GeneratorExit 異常,生成器一定不能產(chǎn)出值,否則解釋器會(huì)拋出 RuntimeError 異常.生成器拋出的其他異常會(huì)向上冒泡,傳給調(diào)用方.如果子生成器不終止,委派生成器會(huì)一直在yield from表達(dá)式處永遠(yuǎn)暫停.委派生成器的程序不會(huì)向前執(zhí)行,因?yàn)閥ield from把控制權(quán)交給委派成生成器的調(diào)用方了,這樣直接導(dǎo)致了委派生成器中有任務(wù)無法完成.
傳入委派生成器的異常,除了 GeneratorExit 之外都傳給子生成器的 throw() 方法.如 果調(diào)用 throw() 方法時(shí)拋出 StopIteration 異常,委派生成器恢復(fù)運(yùn)行.StopIteration 之外的異常會(huì)向上冒泡,傳給委派生成器.
如果把 GeneratorExit 異常傳入委派生成器,或者在委派生成器上調(diào)用 close() 方法, 那么在子生成器上調(diào)用 close() 方法,如果它有的話.如果調(diào)用 close() 方法導(dǎo)致異常 拋出,那么異常會(huì)向上冒泡,傳給委派生成器;否則,委派生成器拋出 GeneratorExit 異常.
數(shù)據(jù)的屬性和處理數(shù)據(jù)的方法統(tǒng)稱屬性.
不管服務(wù)是由存儲(chǔ)還是計(jì)算實(shí)現(xiàn)的,一個(gè)模塊提供所有服務(wù)都應(yīng)該通過統(tǒng)一的方式使用.
用于構(gòu)建實(shí)例的特殊方法市
__new__
:這是個(gè)特殊的類方法,不需要用@classmethod處理,必須返回一個(gè)實(shí)例.
+-__new__
方法返回的實(shí)例回作為__init__
方法的第一個(gè)參數(shù),即self.調(diào)用
__init__
方法時(shí)要傳入實(shí)例,而且禁止返回任何值,__init__
方法時(shí)實(shí)例的初始化方法.構(gòu)造實(shí)例的方法實(shí)際上是__new__
.
對(duì)象的
__dict__
屬性中存儲(chǔ)著對(duì)象的屬性(前提是類中沒有聲明__slots__
屬性),更新實(shí)例的__dict__
屬性,把值設(shè)為一個(gè)映射,能夠快速地再那個(gè)實(shí)例中創(chuàng)建一堆屬性.特性會(huì)覆蓋實(shí)例屬性, 特性都是類屬性,特性管理的其實(shí)就是實(shí)例屬性的讀取.
描述符是實(shí)現(xiàn)了特定協(xié)議的類,這個(gè)協(xié)議包括
__get__
缸血、__set__
和__delete__
方法.property類實(shí)現(xiàn)了完整的描述符協(xié)議.
實(shí)現(xiàn)
__set__
方法的描述符,稱之為"覆蓋型描述符":實(shí)現(xiàn)了__set__
方法的話,會(huì)覆蓋對(duì)實(shí)例屬性的賦值操作.沒有實(shí)現(xiàn)
__set__
方法的描述符,都成為"非覆蓋型描述符":對(duì)實(shí)例屬性的操作都會(huì)在實(shí)例上完成,不會(huì)通過描述符處理.依附在類上的描述符無法控制為類屬性賦值的操作(除非自己創(chuàng)建元類):讀類屬性的操作可以由依附在托管類上定義的
__get__
方法的描述符處理;但是寫類屬性的操作不由依附在托管類上定義有__set__
方法的描述符處理.
在類中定義的函數(shù)屬于綁定方法,用的定義的函數(shù)都有
__get__
方法,依附到類上是,相當(dāng)于非覆蓋型描述符.(綁定方法:1.類中的方法和函數(shù)都是綁定給對(duì)象使用的(除了@classmethod和@staticmethod)2.綁定方法都是有自動(dòng)傳值的功能, 通過實(shí)例訪問時(shí),函數(shù)的__get__
方法返回的時(shí)綁定方法對(duì)象:一種可調(diào)用對(duì)象,里邊包裝著函數(shù),并把托管實(shí)例綁定給函數(shù)的第一個(gè)參數(shù).3.如果類想調(diào)用綁定方法,就必須遵循函數(shù)的參數(shù)規(guī)則,有幾個(gè)參數(shù)傳幾個(gè)參數(shù),包括self在內(nèi). )type是一個(gè)類. type()當(dāng)函數(shù)用時(shí)返回獲取對(duì)象所屬的類.當(dāng)類使用時(shí),傳入三個(gè)參數(shù)name械筛、bases捎泻、和dict可以創(chuàng)建一個(gè)類,也就是說,type() 的實(shí)例是一個(gè)類.
類裝飾器只對(duì)直接依附的類有效(如果用super()方法調(diào)用父類的方法也會(huì)調(diào)用父類的裝飾器).
頂層代碼: 在python中用縮進(jìn)來表示代碼層次的,所謂頂層代碼,表示沒有縮進(jìn)的代碼:即在導(dǎo)入時(shí)會(huì)執(zhí)行.但是類的定義體在導(dǎo)入時(shí)也會(huì)執(zhí)行,所以類的定義體也屬于頂層代碼.
在導(dǎo)入時(shí),解釋器會(huì)從上到下一次性解析完.py模塊的源碼,然后生成用于執(zhí)行的字節(jié)碼.句法錯(cuò)誤就地報(bào)告.本地的
__pycache__
文件夾中有最新的.pyc文件,解釋器會(huì)跳過上述步驟.在進(jìn)程中首次導(dǎo)入模塊時(shí),還會(huì)運(yùn)行所導(dǎo)入模塊中的全部頂層代碼(再次倒入相同的模塊則使用緩存,只做名稱綁定.)
導(dǎo)入模塊時(shí),解釋器會(huì)執(zhí)行頂層的def語句,首次導(dǎo)入時(shí)解釋器會(huì)編譯函數(shù)的定義體,把函數(shù)對(duì)象綁定導(dǎo)對(duì)應(yīng)的全局名稱上,解釋器不會(huì)執(zhí)行函數(shù)的定義體.對(duì)于類來講,解釋器會(huì)執(zhí)行每個(gè)類的定一體,甚至?xí)?zhí)行嵌套類(類中類)的定義體.執(zhí)行類定義體的結(jié)果時(shí)定義了類的屬性和方法,并構(gòu)建了類對(duì)象.在有類裝飾器的情況下,先執(zhí)行被裝飾的類的定義體,然后再運(yùn)行裝飾器函數(shù).(必須先構(gòu)建類對(duì)象,裝飾器才有類對(duì)象可處理.)
object類和type類之際嗯的關(guān)系很獨(dú)特:object是type的實(shí)例(type的實(shí)例是類),而type是object的子類.type是自身的實(shí)例.
所有類都是type的實(shí)例,元類還是type的子類,可以作為制造類的工廠.
類都是type的實(shí)例,所以元類可以通過實(shí)現(xiàn)
__init__
方法定制實(shí)例.元類的__init__
方法可以做到類裝飾器能做的任何事情,作用更大.通常,編寫元類時(shí),__init__
的方法中,self的參數(shù)名替換為cls,能清楚的表明構(gòu)建的實(shí)例是類.如果父類中的metaclass指定了元類,那么子類中也會(huì)受到元類的影響,在導(dǎo)入或者執(zhí)行的時(shí)候,會(huì)先執(zhí)行元類中的
__init__
.