欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

包含python函數(shù)實現(xiàn)原理的詞條

Python函數(shù)和模塊的定義與使用,包括變量的類型及匿名函數(shù)用法

函數(shù)是組織好,可重復使用的,用來實現(xiàn)相關(guān)功能的代碼段

創(chuàng)新互聯(lián)網(wǎng)站建設(shè)公司,提供成都網(wǎng)站建設(shè)、網(wǎng)站建設(shè),網(wǎng)頁設(shè)計,建網(wǎng)站,PHP網(wǎng)站建設(shè)等專業(yè)做網(wǎng)站服務(wù);可快速的進行網(wǎng)站開發(fā)網(wǎng)頁制作和功能擴展;專業(yè)做搜索引擎喜愛的網(wǎng)站,是專業(yè)的做網(wǎng)站團隊,希望更多企業(yè)前來合作!

函數(shù)提高了代碼的重復利用率和應用的模塊性。

除Python自帶的函數(shù)之外,也可以自己創(chuàng)建函數(shù),叫做自定義函數(shù)

語法:

函數(shù)代碼塊以 def 開頭

參數(shù)為 輸入值 ,放于函數(shù)名后口號里面,

函數(shù)內(nèi)容以冒號:開始,函數(shù)體縮進, return 返回 輸出值

函數(shù)調(diào)用使用關(guān)鍵字參數(shù)來確定傳入的參數(shù)值,此時,如果多個函數(shù)則不需要按照指定順序。

在定義函數(shù)時,指定參數(shù)默認值。調(diào)用時如果不傳入?yún)?shù),則使用默認值

不定長部分如果沒有指定參數(shù),傳入是一個空元組

加了 兩個星號 ** 的參數(shù)會以字典的形式導入

/ 用來指明函數(shù)形參必須使用指定位置參數(shù),不能使用關(guān)鍵字參數(shù)的形式。

3.8版本之后的才能使用

不使用 def 定義函數(shù),沒有函數(shù)名

lamdba主體時一個表達式,而不是代碼塊,函數(shù)體比def簡單很多

定義在函數(shù)內(nèi)部的為局部變量,僅能在函數(shù)內(nèi)部使用

定義在函數(shù)外部的為全局變量,可在全局使用

模塊是將包含所有定義的函數(shù)和變量的文件,一般將同類功能的函數(shù)組和在一起稱為模塊。

模塊需要導入后,在調(diào)用相應函數(shù)進行使用

模塊導入的方法:

從模塊中導入一個指定的部分

把一個模塊的所有內(nèi)容全都導入

python中eval函數(shù)是怎么實現(xiàn)的?不要eval的作用,這我知道。求它的原理

eval類似exec,是使用python編譯器運行表達式和語句

兩者區(qū)別在于:eval是編譯表達式并返回值(如: eval("'hello'*2") 結(jié)果是 hellohello)

exec則是運行一部分代碼,并且不像eval那樣返回結(jié)果,exec的返回值永遠是None,且exec可運行多行代碼(如: exec("l=[1,2,3]\nfor i in l:\nprint(i,end=',')") 輸出為"1,2,3," 并且沒有返回值)

「低門檻 手把手」python 裝飾器(Decorators)原理說明

本文目的是由淺入深地介紹python裝飾器原理

裝飾器(Decorators)是 Python 的一個重要部分

其功能是, 在不修改原函數(shù)(類)定義代碼的情況下,增加新的功能

為了理解和實現(xiàn)裝飾器,我們先引入2個核心操作:

在這個例子中,函數(shù)hi的形參name,默認為'world'

在函數(shù)內(nèi)部,又定義了另一個函數(shù) howdoyoudo,定義這個函數(shù)時,將形參name作為新函數(shù)的形參name2的默認值。

因此,在函數(shù)內(nèi)部調(diào)用howdoyoudo()時,將以調(diào)用hi時的實參為默認值,但也可以給howdoyoudo輸入其他參數(shù)。

上面的例子運行后輸出結(jié)果為:

這里新定義的howdoyoudo可以稱作一個“閉包”。不少關(guān)于裝飾器的blog都提到了這個概念,但其實沒必要給它取一個多專業(yè)的名字。我們知道閉包是 函數(shù)內(nèi)的函數(shù) 就可以了

當我們進行 def 的時候,我們在做什么?

這時,hi函數(shù),打印一個字符串,同時返回一個字符串。

但hi函數(shù)本身也是一個對象,一個可以執(zhí)行的對象。執(zhí)行的方式是hi()。

這里hi和hi()有本質(zhì)區(qū)別,

hi 代表了這個函數(shù)對象本身

hi() 則是運行了函數(shù),得到函數(shù)的返回值。

作為對比,可以想象以下代碼

此時也是b存在,可以正常使用。

我們定義2個函數(shù),分別實現(xiàn)自加1, 自乘2,

再定義一個函數(shù)double_exec,內(nèi)容是將某個函數(shù)調(diào)用2次

在調(diào)用double_exec時,可以將函數(shù)作為輸入傳進來

輸出結(jié)果就是

7

27

同樣,也可以將函數(shù)作為輸出

輸出結(jié)果為

6

10

有了以上兩個核心操作,我們可以嘗試構(gòu)造裝飾器了。

裝飾器的目的: 在不修改原函數(shù)(類)定義代碼的情況下,增加新的功能

試想一下,現(xiàn)在有一個原函數(shù)

在不修改原函數(shù)定義代碼的情況下,如果想進行函數(shù)內(nèi)容的添加,可以將這個函數(shù)作為一個整體,添加到這樣的包裹中:

我們定義了一個my_decorator函數(shù),這個函數(shù)進行了一種操作:

對傳入的f,添加操作(運行前后增加打印),并把添加操作后的內(nèi)容連同運行原函數(shù)的內(nèi)容,一起傳出

這個my_decorator,定義了一種增加前后打印內(nèi)容的行為

調(diào)用my_decorator時,對這個行為進行了操作。

因此,new_function是一個在original_function上增加了前后打印行為的新函數(shù)

這個過程被可以被稱作裝飾。

這里已經(jīng)可以發(fā)現(xiàn),裝飾器本身對于被裝飾的函數(shù)是什么,是不需要考慮的。裝飾器本身只定義了一種裝飾行為,這個行為是通過裝飾器內(nèi)部的閉包函數(shù)()進行定義的。

運行裝飾前后的函數(shù),可以清晰看到裝飾的效果

我們復現(xiàn)一下實際要用裝飾器的情況,我們往往有一種裝飾器,想應用于很多個函數(shù),比如

此時,如果我們想給3個print函數(shù)都加上裝飾器,需要這么做

實際調(diào)用的時候,就需要調(diào)用添加裝飾器的函數(shù)名了

當然,也可以賦值給原函數(shù)名

這樣至少不需要管理一系列裝飾前后的函數(shù)。

同時,在不需要進行裝飾的時候,需要把

全部刪掉。

事實上,這樣并不方便,尤其對于更復雜的裝飾器來說

為此,python提供了一種簡寫方式

這個定義print1函數(shù)前的@my_decorator,相當于在定義完print1后,自動直接運行了

不論采用@my_decorator放在新函數(shù)前,還是顯示地重寫print1 = my_decorator(print1),都會存在一個問題:

裝飾后的函數(shù),名字改變了(其實不止名字,一系列的索引都改變了)

輸出結(jié)果為:

這個現(xiàn)象的原因是,裝飾行為本身,是通過構(gòu)造了一個新的函數(shù)(例子中是wrap_func函數(shù))來實現(xiàn)裝飾這個行為的,然后把這個修改后的函數(shù)賦給了原函數(shù)名。

這樣,會導致我們預期的被裝飾函數(shù)的一些系統(tǒng)變量(比如__name__)發(fā)生了變化。

對此,python提供了解決方案:

經(jīng)過這個行為后,被裝飾函數(shù)的系統(tǒng)變量問題被解決了

輸出結(jié)果為

剛才的例子都比較簡單,被裝飾的函數(shù)是沒有參數(shù)的。如果被裝飾的函數(shù)有參數(shù),只需要在定義裝飾行為時(事實上,這個才更通用),增加(*args, **kwargs)描述即可

之前的描述中可以感受到,對于例子中的裝飾行為(前后加打印),函數(shù)被裝飾后,本質(zhì)上是調(diào)用了新的裝飾函數(shù)wrap_func。

因此,如果原函數(shù)需要有輸入?yún)?shù)傳遞,只需要在wrap_func(或其他任意名字的裝飾函數(shù))定義時,也增加參數(shù)輸入(*args, **kwargs),并將這些參數(shù),原封不動地傳給待裝飾函數(shù)f。

這種定義裝飾行為的方式更具有普遍性,忘記之前的定義方式吧

我們試一下

輸出

這里需要注意的是,如果按照以下的方式定義裝飾器

那么以下語句將不會執(zhí)行

因為裝飾后實際的函數(shù)wrap_func(雖然名字被改成了原函數(shù),系統(tǒng)參數(shù)也改成了原函數(shù)),運行到return f(*args, **kwargs) 的時候已經(jīng)結(jié)束了

因為裝飾器my_decorator本身也是可以輸入的,因此,只需要在定義裝飾器時,增加參數(shù),并在后續(xù)函數(shù)中使用就可以了,比如

此時裝飾器已經(jīng)可以有輸入?yún)?shù)了

輸出

你可能發(fā)現(xiàn),為什么不用簡寫版的方法了

因為以上代碼會報錯??!

究其原因,雖然

等價于

但是,

并不等價于

這本身和@語法有關(guān),使用@my_decorator時,是系統(tǒng)在應用一個以單個函數(shù)作為參數(shù)的閉包函數(shù)。即,@是不能帶參數(shù)的。

但是你應該發(fā)現(xiàn)了,之前的@wraps(f)不是帶參數(shù)了嗎?請仔細觀察以下代碼

通過一層嵌套,my_decorator_with_parma本質(zhì)上是返回了一個參數(shù)僅為一個函數(shù)的函數(shù)(my_decorator),但因為my_decorator對my_decorator_with_parma來說是一個閉包,my_decorator_with_parma是可以帶參數(shù)的。(這句話真繞)

通過以上的定義,我們再來看

可以這么理解,my_decorator_with_parma(msg='yusheng')的結(jié)果是原來的my_decorator函數(shù),同時,因為my_decorator_with_parma可以傳參,參數(shù)實際上是參與了my_decorator的(因為my_decorator對my_decorator_with_parma是閉包), my_decorator_with_parma(msg='yusheng') 全等于 一個有參數(shù)參加的my_decorator

因此,以上代碼等價于有參數(shù)msg傳遞的

比較繞,需要理解一下,或者干脆強記這種范式:

以上范式包含函數(shù)的輸入輸出、裝飾器的輸入,可以應對大部分情況了。

實驗一下:

輸出

以上是一個log裝飾器,利用datetime統(tǒng)計了函數(shù)的耗時,

并且,裝飾器可以進行輸出文件操作,如果給出了文件路徑,則輸出文件,否則就打印。

利用這個裝飾器,可以靈活地進行耗時統(tǒng)計

不設(shè)置輸出文件地址,則打印。運行結(jié)果為:

也可以輸出到文件

輸出結(jié)果為

同時在當前目錄生成了一個test.log 文件,內(nèi)容為:

以上的裝飾器都是以函數(shù)形式出現(xiàn)的,但我們可以稍做改寫,將裝飾器以類的形式實現(xiàn)。

這個裝飾器類Log 上個例子里的裝飾器函數(shù)log功能是一樣的,同時,這個裝飾器類還可以作為基類被其他繼承,進一步增加功能。

原文

python dict 實現(xiàn)原理 2019-04-17

dict對象是Python中一個原始的數(shù)據(jù)類型,按照鍵值對的方式存儲,中文名為字典,其通過鍵名查找對應的值有很高的效率,時間復雜度在常數(shù)級別O(1)。Python dict的底層是依靠哈希表(Hash Table)進行實現(xiàn)的,使用開放地址法解決沖突。所以其查找的時間復雜度會是O(1),why?

哈希表是key-value類型的數(shù)據(jù)結(jié)構(gòu),通過關(guān)鍵碼值直接進行訪問。通過散列函數(shù)進行鍵和數(shù)組的下標映射從而決定該鍵值應該放在哪個位置,哈希表可以理解為一個鍵值需要按一定規(guī)則存放的數(shù)組,而哈希函數(shù)就是這個規(guī)則。

算法中時間和空間是不能兼得的,哈希表就是一種用合理的時間消耗去減少大量空間消耗的操作,這取決于具體的功能要求。

創(chuàng)建一個數(shù)組,數(shù)組下標是索引號,數(shù)組中的值是要獲得的數(shù)據(jù),這樣只需要O(1)的時間復雜度就可以完成操作,但是擴展性不強,有以下兩個方面的考慮:

-1- 新添加的元素超出數(shù)組索引范圍,這就需要重新申請數(shù)組進行遷移操作。

-2- 假設(shè)一種極端的情況:只存在兩個元素,索引號分別是1和100000000001,按照先前的設(shè)計思路,會浪費很大的存儲空間。

會不會存在一個方法,為已有的索引創(chuàng)建新的索引,通過壓縮位數(shù),讓新索引可以和原有的大范圍的稀疏索引進行一一對應,新索引所需要的存儲空間要大大減小,這就是哈希思想。

上面的例子中哈希函數(shù)的設(shè)計很隨意,但是從這個例子中我們也可以得到信息:

哈希函數(shù)就是一個映射,因此哈希函數(shù)的設(shè)定很靈活,只要使得任何關(guān)鍵字由此所得的哈希函數(shù)值都落在表長允許的范圍之內(nèi)即可;

因為新的索引對舊的索引進行了空間上的壓縮,所以不可能所有的輸入都只對應唯一一個輸出,也就是哈希函數(shù)式有可能發(fā)生沖突的,哈希函數(shù)不可能做成一對一的映射關(guān)系,其本質(zhì)是一個多對一的映射。

直接定址法:很容易理解,key=Value+C; 這個“C”是常量。Value+C其實就是一個簡單的哈希函數(shù)。

除法取余法: 很容易理解, key=value%C;解釋同上。

數(shù)字分析法:這種蠻有意思,比如有一組value1=112233,value2=112633,value3=119033,針對這樣的數(shù)我們分析數(shù)中間兩個數(shù)比較波動,其他數(shù)不變。那么我們?nèi)ey的值就可以是key1=22,key2=26,key3=90。

平方取中法。此處忽略,見名識意。

折疊法:這種蠻有意思,比如value=135790,要求key是2位數(shù)的散列值。那么我們將value變?yōu)?3+57+90=160,然后去掉高位“1”,此時key=60,哈哈,這就是他們的哈希關(guān)系,這樣做的目的就是key與每一位value都相關(guān),來做到“散列地址”盡可能分散的目地。

當兩個不同的數(shù)據(jù)元素的哈希值相同時,就會發(fā)生沖突。解決沖突常用的手法有2種:

開放地址法:

如果兩個數(shù)據(jù)元素的哈希值相同,則在哈希表中為后插入的數(shù)據(jù)元素另外選擇一個表項。當程序查找哈希表時,如果沒有在第一個對應的哈希表項中找到符合查找要求的數(shù)據(jù)元素,程序就會繼續(xù)往后查找,直到找到一個符合查找要求的數(shù)據(jù)元素,或者遇到一個空的表項。

鏈接法:

將哈希值相同的數(shù)據(jù)元素存放在一個鏈表中,在查找哈希表的過程中,當查找到這個鏈表時,必須采用線性查找方法。

python的dict采用了哈希表,最低能在 O(1)時間內(nèi)完成搜索,在發(fā)生哈希沖突的時候采用的是開放尋址法。java的HashMap也是采用了哈希表實現(xiàn),但是在發(fā)生哈希沖突的時候采用的是鏈接法。

文章題目:包含python函數(shù)實現(xiàn)原理的詞條
網(wǎng)頁網(wǎng)址:http://chinadenli.net/article16/hdodgg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供電子商務(wù)、靜態(tài)網(wǎng)站關(guān)鍵詞優(yōu)化、網(wǎng)站制作、網(wǎng)站收錄、網(wǎng)站策劃

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

小程序開發(fā)