1. 程式人生 > >【011】Python全棧日記-脫髮知識點合集

【011】Python全棧日記-脫髮知識點合集

在這裡插入圖片描述
一、常用魔術方法
1.init
初始化魔術方法
觸發時機:初始化物件時觸發(不是例項化觸發,但是和例項化在一個操作中)
引數:至少有一個self,接收物件
返回值:無
作用:初始化物件的成員
注意:使用該方式初始化的成員都是直接寫入物件當中,類中無法具有
在這裡插入圖片描述
結果:
在這裡插入圖片描述

2.new
例項化魔術方法
觸發時機: 在例項化對時觸發
引數:至少一個cls 接收當前類
返回值:必須返回一個物件例項
作用:例項化物件
注意:例項化物件是Object類底層實現,其他類繼承了Object的__new__才能夠實現例項化物件。
沒事別碰這個魔術方法,先觸發__new__才會觸發__init__
a、首先呼叫__new__得到一個物件
b、呼叫__init__為物件新增屬性
c、將物件賦值給變數
在這裡插入圖片描述


結果:
在這裡插入圖片描述

3.str
觸發時機:使用print(物件)或者str(物件)的時候觸發
引數:一個self接收物件
返回值:必須是字串型別
作用:print(物件時)進行操作,得到字串,通常用於快捷操作
注意:無
a本是一個實列物件,卻作為一個字串輸出,如果沒有魔方__str__是無法實現的。
在這裡插入圖片描述
結果:
在這裡插入圖片描述

4、add()
當傳入加法時,呼叫。被加數為other
在這裡插入圖片描述
結果:
在這裡插入圖片描述

  1. del()
    觸發時機:刪除物件成員時觸發
    引數:一個當前物件的self
    返回值:無
    作用:可以在刪除成員時進行驗證。
    在這裡插入圖片描述
    結果:
    在這裡插入圖片描述
    當我們刪除del a ,del b,del c,還會觸發麼?
    在這裡插入圖片描述
    結果:
    在這裡插入圖片描述
    你會發現還是觸發了__del__(),這是因為當你自己寫的時候是你主動觸發,而不寫是計算機程式在函式(方法)執行完後會自動回收沒用的引數,減少記憶體佔用。

6.slots
限制傳入的物件屬性,寫哪個允許哪個傳入。(不知道有個卵子用,自己限制自己麼)
使用__slots__要注意,__slots__定義的屬性僅對當前類起作用,對繼承的子類是不起作用的:
在這裡插入圖片描述
結果:
在這裡插入圖片描述
由於沒允許age傳入,所以類A找不到age這個屬性,所以報錯。

7、cell()
當物件當作函式時,呼叫__call__
在這裡插入圖片描述
結果:
在這裡插入圖片描述

8、類的專有方法:
init : 建構函式,在生成物件時呼叫
del : 解構函式,釋放物件時使用
repr : 列印,轉換
setitem : 按照索引賦值
getitem: 按照索引獲取值
len: 獲得長度
cmp: 比較運算
call

: 函式呼叫
add: 加運算
sub: 減運算
mul: 乘運算
div: 除運算
mod: 求餘運算
pow: 乘方

二、@ property、@self.setter
在設定屬性時,如果我們直接把屬性值暴露出去,雖然寫起來很簡單,但是,沒辦法檢查引數,導致可以把屬性值隨便改,這顯然不合邏輯。
有沒有一種既能檢查引數,又可以用直接改變屬性的方式來訪問類的變數呢?
Python內建的@property和@self.setter裝飾器就是負責把一個方法變成屬性呼叫的:
看一個例子:
在這裡插入圖片描述
@property就是告訴你下面這個方法,是可以當成屬性使用的,所以有a.age = 18,而方法age自身並沒有除了self以外的引數。
@age.setter 就是當你使用age屬性時,必須先經過@age.setter下的方法,對age進行設定。
上面的例子,如果輸入年齡大於100或者小於0,這明顯不符合邏輯,就會對年齡進行限制
輸出結果:
在這裡插入圖片描述
從輸出的結果我們也能看出來,設定age屬性等於18後,先傳入@age.setter進行檢查,所以首先輸出2,確認無誤後賦值給新的屬性_age(加下劃線只是為了區分age和_age),然後傳遞到@propertry下的方法,所以輸出1,返回_age的值給a.age 輸出18。

三、設計模式
設計模式(Design pattern)代表了最佳的實踐,通常被有經驗的面向物件的軟體開發人員所採用。設計模式是軟體開發人員在軟體開發過程中面臨的一般問題的解決方案。這些解決方案是眾多軟體開發人員經過相當長的一段時間的試驗和錯誤總結出來的。
設計模式是一套被反覆使用的、多數人知曉的、經過分類編目的、程式碼設計經驗的總結。使用設計模式是為了重用程式碼、讓程式碼更容易被他人理解、保證程式碼可靠性

工廠模式
設計模式涉及到建立類的幾種模式,共同的也是最根本的原則就是:不要new物件!!!既然如此,告訴我你最先想到的是如何得到物件呢?沒錯,“你不讓我new,那你給我個get物件的工具吧,別的我不管”。這就是工廠模式,工廠模式是一種簡單又實用的模式,在各大框架到處可見,比如Java世界大名鼎鼎的spring,其本身就是一個大工廠。
在這裡插入圖片描述
這個我也不太懂,老師就是介紹一下,舉了這個例子。

四、抽象類
具有抽象方法的類就是抽象類。
抽象方法就是沒有完成的方法。只有方法名稱和引數,沒有方法內容的方法。
作用:適合於領導指定開發規範及多人協作完成類。
Abc: abstract class 抽象類的縮寫
抽象類的語法
在這裡插入圖片描述

五、迭代器

1、概述
  迭代器是訪問集合元素的一種方式。迭代器物件從集合的第一個元素開始訪問,直到所有的元素被訪問完結束。迭代器只能往前不會後退。

迭代器不要求你事先準備好整個迭代過程中所有的元素。僅僅是在迭代至某個元素時才計算該元素,而在這之前或之後,元素可以不存在或者被銷燬。這個特點使得它特別適合用於遍歷一些巨大的或是無限的集合。
比如用for或者while進行從0到100000000000遍歷時,電腦會先把0到100000000000這些數先存在記憶體中,這會佔用大量的記憶體。而使用迭代器,讀取一個數存如記憶體一個,遍歷下一個數就會抹除上一個數,佔用記憶體始終很小。

2、可迭代物件
序列:字串、列表、元組
非序列:字典、檔案

3、建立迭代器物件
使用內建的工廠函式iter(iterable)可以獲取迭代器物件:
在這裡插入圖片描述
結果:
在這裡插入圖片描述
要使用迭代器就得使用iter()選擇要迭代的元素,例如例子中的b = iter(a),然後通過next(b)推動迭代。
For和while迴圈是你設定好,自動遍歷,而迭代器屬於踢一腳走一步。
如果不想每次踢著走,可以藉助迴圈結構來幫你踢
在這裡插入圖片描述

六、生成器
1、什麼是生成器
建立python迭代器的過程雖然強大,但是很多時候使用不方便。生成器是一個簡單的方式來完成迭代。簡單來說,Python的生成器是一個返回可以迭代物件的函式。

2、怎樣建立生成器
在一個一般函式中使用yield關鍵字,可以實現一個最簡單的生成器,此時這個函式變成一個生成器函式。yield與return返回相同的值,區別在於return返回後,函式狀態終止,而yield會儲存當前函式的執行狀態,在返回後,函式又回到之前儲存的狀態繼續執行。

3、生成器函式與一般函式的不同
一下是幾點不同:
生成器函式包含一個或者多個yield
當呼叫生成器函式時,函式將返回一個物件,但是不會立刻向下執行
我們可以通過next()方法對物件進行迭代
一旦函式被yield,函式會暫停,控制權返回呼叫者
區域性變數和它們的狀態會被儲存,直到下一次呼叫
函式終止的時候,StopIteraion會被自動丟擲(就是超出範圍就會報錯)
舉例:
在這裡插入圖片描述
結果:
在這裡插入圖片描述
解釋太難了,兩種方法,第一使用pycharm帶的debug來看程式執行流程,
第二種看我這張糙圖理解一下:
在這裡插入圖片描述
紅色是開頭:呼叫函式,進入迴圈,輸出第一次n=1,然後執行到yield暫停。
橙色:跳出迴圈,執行第一個print(next(b)),輸出1,然後跳回迴圈的yield位置,繼續往下輸出第二次n=1,然後n+1,回到迴圈頭。
黃色,輸出第一次n=2,然後執行到yield暫停,跳出迴圈,到第二個print(next(b)),輸出2,然後跳回迴圈的yield位置。
以此類推…………

4、生成器的表示式
我們之前學過列表解析
#產生1,2,3,4,5的一個列表
a = [x for x in range(5)]

然後就會把0到4遍歷出來。
如果換成[]換成(),那麼會成為生成器的表示式。
(x for x in range(5))
具體使用方式:
在這裡插入圖片描述
結果:
在這裡插入圖片描述

5、為什麼使用生成器

  • 更容易使用,程式碼量較小
  • 記憶體使用更加高效。比如列表是在建立的時候就分配所有的記憶體空間,而生成器僅僅是需要的時候才使用,更像一個記錄
  • 代表了一個無限的流。如果我們要讀取並使用的內容遠遠超過記憶體,但是需要對所有的流中的內容進行處理,那麼生成器是一個很好的選擇,比如可以讓生成器返回當前的處理狀態,由於它可以儲存狀態,那麼下一次直接處理即可。

七、裝飾器
我自己懂,說不明白啊,
所以我找了網上好多的關於裝飾器的教程,有一個簡單明瞭深得我心,原文連結:https://www.yiibai.com/python/decorator.html,接下來我引用他的教學過程,給大家講一下裝飾器。

1、裝飾器是啥
裝飾器,是給現有程式碼新增功能的一個功能。這也稱為超程式設計,作為程式的一部分,嘗試在編譯時修改程式的另一部分。裝飾器接收一個功能,新增一些功能並返回。

2、引入
為了瞭解裝飾器,我們首先在Python中瞭解一些基本的東西。Python中的一切(是的,甚至是類)都是物件。 我們定義的名稱只是繫結到這些物件的識別符號。 函式也不例外,它們也是物件(帶有屬性)。 各種不同的名稱可以繫結到同一個功能物件。
看一個例子:
在這裡插入圖片描述
答案是輸出兩個hello

當執行程式碼時,first和second函式都提供相同的輸出。 這裡名稱first和second引用相同的函式物件。函式可以作為引數傳遞給另一個函式。將其他函式作為引數的函式也稱為高階函式。下面是這樣子的一個函式的例子。
在這裡插入圖片描述
輸出結果為:
4
2

此外,一個函式可以返回另一個函式:
在這裡插入圖片描述
結果:
Hello

這裡,b是一個定義的巢狀函式,在每次呼叫a時返回。

3、裝飾器
實際上,實現魔術方法__call__()的任何物件都被稱為可呼叫。 因此,在最基本的意義上,裝飾器是可呼叫的,並且可以返回可呼叫。基本上,裝飾器接收一個函式,新增一些函式並返回。
在這裡插入圖片描述
執行結果為:
在這裡插入圖片描述
在上面的例子中,make_pretty()是一個裝飾器。 在分配步驟。

pretty = make_pretty(ordinary)
函式ordinary()得到了裝飾,返回函式的名字:pretty。可以看到裝飾函式為原始函式添加了一些新功能。這類似於包裝禮物。 裝飾器作為包裝紙。 裝飾物品的性質(裡面的實際禮物)不會改變。 但現在看起來很漂亮(因為裝飾了)。

一般來說,我們裝飾一個函式並重新分配它,
ordinary = make_pretty(ordinary).
這是一個常見的結構,Python有一個簡化的語法。
可以使用@符號和裝飾器函式的名稱,並將其放在要裝飾的函式的定義之上。 例如:
在這裡插入圖片描述
上面程式碼相當於:
在這裡插入圖片描述

[1]用引數裝飾函式
上面的裝飾器很簡單,只適用於沒有任何引數的函式。 如果有函式要接受如下的引數怎麼辦?
在這裡插入圖片描述
該函式有兩個引數a和b。 我們知道,如果將b的值設定為0並傳遞那麼是會出錯的。
現在使用一個裝飾器來檢查這個錯誤。
在這裡插入圖片描述
結果:
在這裡插入圖片描述
以這種方式就可以裝飾函式的引數了。

應該會注意到,裝飾器中巢狀的inner()函式的引數與其裝飾的函式的引數是一樣的。 考慮到這一點,現在可以讓一般裝飾器使用任何數量的引數。
在Python中,這個由function(* args,** kwargs)完成。 這樣,args將是位置引數的元組,kwargs將是關鍵字引數的字典。這樣的裝飾器的例子將是。
在這裡插入圖片描述
*args **kwargs在函式那個日記裡講述過的,忘了的可以去瞅瞅。

[2] 在Python中連結裝飾器
多個裝飾器可以在Python中連結。
這就是說,一個函式可以用不同(或相同)裝飾器多次裝飾。只需將裝飾器放置在所需函式之上。
在這裡插入圖片描述
結果:
在這裡插入圖片描述

以上語法:
在這裡插入圖片描述
相當於:
在這裡插入圖片描述

鏈裝飾器的順序是重要的。 所以如果把順序顛倒了執行結果就不一樣了,如下 :
在這裡插入圖片描述
結果就變成了:
在這裡插入圖片描述

八、閉包
閉包是函數語言程式設計的重要的語法結構,Python也支援這一特性,下面就開始介紹Python中的閉包。
1、Python建立閉包
下面看一個閉包的簡單的例子,例子中定義了一個可以配置打招呼的函式
”greeting_conf”,在這個函式中,內嵌了一個”greeting”的內嵌函式:
在這裡插入圖片描述
程式碼的結果為:
在這裡插入圖片描述
上面的程式碼有下面幾個注意點:

  • “greeting”函式訪問了non-local的變數”prefix”,根據前面namespace的介紹,這點是完全合法的。
  • 變數”prefix”並沒有隨著函式的退出而銷燬,反而是生命週期得到了延長 下面看看為什麼變數”prefix”生命週期得到了延長?

2、閉包和函式
閉包只是在表現形式上跟函式類似,但實際上不是函式。
在這裡插入圖片描述
結果:
在這裡插入圖片描述
從程式碼的結果中可以看到,閉包在執行時可以有多個例項,不同的引用環境(這裡就是prefix變數)和相同的函式(這裡就是greeting)組合可以產生不同的例項。

3、Python中怎麼建立閉包
在Python中建立一個閉包可以歸結為以下三點:

  • 閉包函式必須有內嵌函式
  • 內嵌函式需要引用該巢狀函式上一級namespace中的變數
  • 閉包函式必須返回內嵌函式