亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

詳談Python高階函數與函數裝飾器(推薦)

 更新時間:2017年09月30日 08:25:52   作者:風中的人  
下面小編就為大家?guī)硪黄斦凱ython高階函數與函數裝飾器(推薦)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

一、上節(jié)回顧

Python2與Python3字符編碼問題,不管你是初學者還是已經對Python的項目了如指掌了,都會犯一些編碼上面的錯誤。我在這里簡單歸納Python3和Python2各自的區(qū)別。

首先是Python3-->代碼文件都是用utf-8來解釋的。將代碼和文件讀到內存中就變成了Unicode,這也就是為什么Python只有encode沒有decode了,因為內存中都將字符編碼變成了Unicode,而Unicode是萬國碼,可以“翻譯”所以格式編碼的格式。Python3中str和bytes是兩種格式,bytes可以當做二進制的表現(xiàn)形式。

Python2使用系統(tǒng)默認的字符編碼解釋代碼,所以要用utf-8解釋代碼,就必須在頭部申明;并且Python2中有解碼和編碼,但是解碼動作是必須的而編碼動作可以忽略,因為Python代碼加載到內存中就是Unicode,這一點和python3一樣;Python2中還需要注意的就是str和bytes是一個意思。Python2 里面的str就是Python3中的bytes格式,而Python3中的str其實就是Unicode.

函數基礎(這里我就是用遞歸函數中的二分查找)

為什么使用函數:將將程序進行模塊設計

定義函數有三種形式:

- 無參函數

- 有參函數

- 空函數

PS:如果函數有多個返回值,那么返回的來的數據格式是元組

- 如何在函數傳入參數時限定參數數據格式。

def leon(x:int,y:int)->int:

pass

其中這里指定了x,y都必須是int類型 " -> "的意思是函數返回值也必須是int類型

print(yan.__annotations__):顯示形參的限定數據格式以及返回值的格式

a = [1,2,3,4,5,7,9,10,11,12,14,15,16,17,19,21] #形參中的num
def calc(num,find_num):
 print(num)
 mid = int(len(num) / 2)   #中間數的下標
 if mid == 0: #遞歸函數非常重要的判斷條件
 if num[mid] == find_num:
  print("find it %s"%find_num)
 else:
  print("cannt find num")
 if num[mid] == find_num: #直接找到不用遞歸,結束函數
 print("find_num %s"%find_num)
 elif num[mid] > find_num: #find_num應該在左邊,向下遞歸
 calc(num[0:mid],find_num)

 elif num[mid] < find_num: #find_num應該在右邊,向下遞歸
 calc(num[mid+1:],find_num)
calc(a,12)

匿名函數

c = lambda x:x+1 #x就是形參,c就是這個匿名函數的對象

print(c(22)) 

高階函數-特性

1. 把一個函數的內存地址傳給另外一個函數,當做參數

2.一個函數把另外一個函數的當做返回值返回

def calc(a,b,c):
print(c(a) + c(b))

calc(-5,10,abs) #引用上一節(jié)的實例,將-5和10絕對值相加

 

二、高階函數(補充)

函數是第一類對象

函數可以被賦值

可以被當做參數

可以當做返回值

可以作為容器類型的元素

#函數可以被賦值
def leon():
 print("in the leon")

l = leon
l()

#函數可以被當做參數
def yan(x): #這里x形參,其實就是我們調用實參的函數名
 x() #運行函數

y = yan(leon)


#函數當做返回值
def jian(x): 和上面一樣這這也必須傳入一個函數
 return x
j = jian(leon) #這里需要注意一點就是這里的意思是運行jian這個函數而這個函數返回的是x 也就是leon這個函數的內存地址,也就是說這時候leon這個函數并沒有被執(zhí)行
j() #運行 leon函數

#可以做為容器類型的元素
leon_dict = {"leon":leon}

leon_dict["leon"]() #這樣也可以運行l(wèi)eon這個函數

三、閉包函數

1.什么是閉包?我來看一下,比較官網的概念(這不是我在官網上面找的,不過沒有關系,反正你們也看不懂):

閉包(Closure)是詞法閉包(Lexical Closure)的簡稱,是引用了自由變量的函數。這個被引用的自由變量將和這個函數一同存在,即使已經離開了創(chuàng)造它的環(huán)境也不例外。所以,閉包是由函數和與其相關的引用環(huán)境組合而成的實體。

懵逼了?不存在的。下面我用簡潔的說一下,但是有一點很重要,閉包是裝飾器中的重點,如果沒有把閉包正真理解,那么學完裝飾器之后會很快忘記。我們通過一個列子來說明下

import requests #首先導入一個模塊,這個可以不用記

def get(url): #定義一個get函數里面需要傳一個url的位置參數
 def wapper(): #在定義一個wapper函數
 res = requests.get(url) #這一步就是打開一個網頁
 return res.text #將網頁以文字的形式返回
 return wapper #返回最里層的wapper函數

g = get("http://www.baidu.com") #調用:首先因為作用域的原因,我們無法訪問到里層的wapper函數,所以我們直接調用get函數這里返回了一個wapper函數
print(g()) # 然后我在調用g(get函數)的對象,這樣是不是就訪問到里層的wapper函數呢

PS:這里我們可以把函數當做一個特殊的變量,當代碼從上向下執(zhí)行的時候,如果函數不被調用話,函數內的代碼是不會被執(zhí)行的。就拿上面的上面的舉例,當我們執(zhí)行get函數的時候,這時候會返回一個wapper函數的內存地址,但是這個時候wapper函數并沒有被執(zhí)行也就是說g()這時候返回的狀態(tài)其實就是wapper,這是我們只需要將g運行,就等于運行了wapper內的代碼。

四、函數的嵌套調用

嵌套調用其實很好理解,就是在一個函數中調用另一個函數的結果,也就是return的東西,同樣的我們看一段非常簡單的代碼來看一下。

#嵌套調用,在一個函數中調用另一個函數的功能
#calc這個函數就是在對比兩個數字的大小
def calc2(x,y):
 if x >y :
 return x
 else:
 return y

#我靠老板非常變態(tài),然你直接計算四個數字的大小,擦。
def calc4(a,b,c,d):
 res1 = calc2(a,b) #res1的值,這里不就是calc2這個函數比較時最大的哪一個嗎。
 res2 = calc2(res1,c)
 res3 = calc2(res2,d)
 return res3

通過上面的代碼我們做一記憶。什么時候會用到嵌套調用呢?很顯然,就是我們這個函數(calc4)需要另外一個函數的實行結果(return的y或者x)。

五、裝飾器(高級的閉包函數)

就拿下面的這段代碼來說。如何在不改源代碼的情況下實現(xiàn)計算代碼的運行時間

def geturl(url):
 response = requests.get(url)
 print(response.status_code)

geturl(http://www.baidu.com)
def timer(func):
 def wapper(url):
 start_time = time.time()
 func(url)
 stop_time = time.time()
 so_time_is = stop_time - start_time
 print("運行時間%s"%so_time_is)
 return wapper


@timer
def geturl(url):
 response = requests.get(url)
 print(response.status_code)

python = geturl(http://www.baidu.com)

圖解代碼

裝飾器必備:

@timer就是裝飾器,意思是裝飾它下面的函數,而裝飾器和被裝飾的都是一個函數。

timer(裝飾器函數),首先它會有一個位置參數(func)名字隨意,但是必須并且只能是一個位置參數

func參數就是被裝飾的geturl這個函數

為什么func是geturl這個函數呢-->上面寫了一個裝飾器功能:geturl=timer(geturl),我們看到這里的timer中傳入的其實就是func函數所以func = geturl(被裝飾的函數)

分析geturl=timer(geturl),首先我們可以得知timer這是一個閉包函數,當我們執(zhí)行這個閉包函數,會把里層的函數(wapper)返回,也就是說timer(geturl)其實就是返回的wapper,所以就可以這樣理解了geturl==wapper,所以當我們運行geturl的時候就相當于在執(zhí)行wapper()這樣的一個操作;如果這里實在記不住,就這樣。咱上面不是有一個閉包函數嗎?你就把geturl=timer(geturl)中的geturl(執(zhí)行函數的返回結果)當做上面g(函數調用的返回結果),然后在分別再執(zhí)行了下"g"或者"geturl”這個對象。

如果被裝飾者有位置參數的話,我們需要在wapper函數中加上對應的位置參數用來接收,如果長度是不固定的話還可以用*args和**kwargs

六、有參裝飾器

聽著名字顧名思義,就是在裝飾器中還有位置參數。

#一個low得不能再low得驗證腳本,如果是顯示環(huán)境中所有數據必須是由數據庫或者一個靜態(tài)文件提供,并且登錄成功時,需要保存用戶的一個狀態(tài)

def auth(auth_type): #有參裝飾器名稱
 def auth_deco(func): #定義第二層函數名稱
 def wrapper(*args,**kwargs): #最里層函數,主要實現(xiàn)認證功能
  if auth_type == "file":
  username = input("username>>:").strip()
  password = input("username>>").strip()
  if username == "leon" and password == "loveleon":
   res = func(*args,**kwargs)
   return res
  elif auth_type == "mysql_auth":
  print("mysql_auth...")
  return func(*args,**kwargs)
 return wrapper #第二層返回的是wrapper函數,其實就是home
 return auth_deco #第一層返回的結果等于第二層函數的名稱

@auth('file')
def home():
 print("welcome")

home() #執(zhí)行home-->wrapper

有參函數必備知識:

套路,通過上面無參裝飾器,我們得出了geturl=timer(geturl)這個等式?;氐接袇⒀b飾器,我們又會有什么樣子的等式呢?首先@auth("file")是一個裝飾器也就是一個函數,所以我們定義了一個auth(auth_type)這個函數,而這個函數返回的是什么呢?沒有錯就是第二層函數;到了這里我們就會發(fā)現(xiàn)@auth("file")其實就是@auth_deco,現(xiàn)在我們知道了現(xiàn)在裝飾器其實就是auth_deco,那剩下的還不知道怎么寫嗎?

整理公式,auth('file')-----------(return)> auth_deco----->@auth_deco ->home=auth_deco(home)

如果記不住?如果實在是記不住,其實就可以這樣理解,有參裝飾器無非就是在無參裝飾器上面加了一層(三層),然后在第一層返回了第二層的函數,而到了第二層就和我們普通用的裝飾器是一毛一樣了

七、模塊導入

import ,創(chuàng)建一個leonyan.py的模塊文件,等待被導入

a = 10
b = 20
c = 30

def read1():
 print("in the read1")

def read2():
 print("in the read2")

導入leonyan.py文件(調用模塊文件和模塊文件在同一目錄下)

import leonyan #Python IDE這行會爆紅,但是不用管

leonyan.read1() #執(zhí)行l(wèi)eonyan這個包中的read1函數

leonyan.read2() #執(zhí)行l(wèi)eonyan這個包中read2函數

print(leonyan.a + leonyan.b + leonyan.c ) #輸出60

總結:在Python中包的導入(import ***)會干三個事情:1:創(chuàng)建新的作用域;2:執(zhí)行該作用域的頂級代碼,比如你導入的那個包中有print執(zhí)行后就會直接在屏幕中輸出print的內容;3:得到一個模塊名,綁定到該模塊內的代碼

在模塊導入的時候給模塊起別名

import leonyan as ly
import pandas as pd #這是一個第三方模塊,以后的博客中會寫到,這是一個用于做統(tǒng)計的

 

給模塊起別名還是挺多的,在有些模塊的官方文檔中,還是比較推薦這種方法的,比如pandas的官方文檔中就是起了一個pd別名,總之as就是一個模塊起別名

from *** import ***

from leonyan import read1 #引入直接調用
read1() 

 

如果在調用模塊的函數作用域中有相同的同名的,會將調用過來的覆蓋。

在form ** import ** 中控制需要引用的變量(函數其實在未被執(zhí)行的時候也是一個存放在內存中的變量)

from leonyan import read1,read2 在同一行中可以引用多個,只需要用逗號隔開就行了

print(read1)
print(read2)
#這里打印的就是read1和read2的內存地址

#需求我現(xiàn)在只需要導入read2

這時候我們就可以在leonyan這個函數中加上這么一行:

__all__ = ["read2"] #這里的意思就是別的文件調用為的時候用from ** import ** 只能拿到read2 這個函數的內存地址,也就是只有read2可以被調用

把模塊當做一個腳本執(zhí)行

我們可以通過模塊的全局變量__name__來查看模塊名:

當做腳本運行:

__name__ 等于'__main__'

作用:用來控制.py文件在不同的應用場景下執(zhí)行不同的邏輯

if __name__ == '__main__':

#fib.py

def fib(n): # write Fibonacci series up to n
 a, b = 0, 1
 while b < n:
 print(b, end=' ')
 a, b = b, a+b
 print()

def fib2(n): # return Fibonacci series up to n
 result = []
 a, b = 0, 1
 while b < n:
 result.append(b)
 a, b = b, a+b
 return result

if __name__ == "__main__":
 import sys
 fib(int(sys.argv[1]))

代碼執(zhí)行 Python flb.py 100

只需要簡單了解的Python模塊導入搜索路徑

內建(build-in)  --> sys.path(sys.path是一個列表,而且第一個位置就是當前文件夾)

模塊導入的重點-->包的導入

在實際的開發(fā)環(huán)境中,你不可能一個文件的代碼寫到底,當然你也有可能會引用同文件夾中的其他模塊,但是你有沒有想過這一個項目不可能是你一個寫的,都是很多人協(xié)作開發(fā)。這樣就存在這樣的一個問題了;不同的人不可能用一臺電腦,也不可能在一個文件夾下面寫寫功能。他們也有自己的代碼文件夾,然后大家把功能通過接口的方式,提供調用。這時候就面臨這不同文件夾的調用問題。而這種問題也需要通過from ** import ** 調用。

上圖中我運行“模塊導入.py”這個文件夾,首先我from Pythonscript.leonyan.command import config,因為我們得運行腳本和需要導入的包都在Pythonscript的目錄下面所以我直接通過絕對路徑導入,然后一層一層“.”下去,知道最后import了這個config文件,這里我們需要注意一點:當腳本在最外層運行的時候sys.path 列表中的第一個參數就是運行腳本的目錄,這是什么意思,這代表著你在別的包中有調用了其他的東西比如說我的config.py是調用了bing.py文件,這時候就必須寫絕對路徑,因為這在sys.path文件夾中已經找不到了,也就是導入不進來。

總結:包的導入其實都是很簡單的,你需要記住一點:當你導入Python內建或者下載的第三方模塊直接用import 導入,如果是自己寫的就用from ** import ** 使用絕對目錄導入就行了,也就是從調用腳本的上級目錄開始導入。這樣可以保證不會報模塊導入的錯誤了。

以上這篇詳談Python高階函數與函數裝飾器(推薦)就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

  • Python使用Redis實現(xiàn)作業(yè)調度系統(tǒng)(超簡單)

    Python使用Redis實現(xiàn)作業(yè)調度系統(tǒng)(超簡單)

    Redis作為內存數據庫的一個典型代表,已經在很多應用場景中被使用,這里僅就Redis的pub/sub功能來說說怎樣通過此功能來實現(xiàn)一個簡單的作業(yè)調度系統(tǒng)。這里只是想展現(xiàn)一個簡單的想法,所以還是有很多需要考慮的東西沒有包括在這個例子中,比如錯誤處理,持久化等
    2016-03-03
  • 使用matplotlib實現(xiàn)在同一個窗口繪制多個圖形

    使用matplotlib實現(xiàn)在同一個窗口繪制多個圖形

    這篇文章主要介紹了使用matplotlib實現(xiàn)在同一個窗口繪制多個圖形問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • pytorch實現(xiàn)mnist數據集的圖像可視化及保存

    pytorch實現(xiàn)mnist數據集的圖像可視化及保存

    今天小編就為大家分享一篇pytorch實現(xiàn)mnist數據集的圖像可視化及保存,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-01-01
  • Python如何將CSV文件轉JSON文件

    Python如何將CSV文件轉JSON文件

    這篇文章主要給大家介紹了關于Python如何將CSV文件轉JSON文件的相關資料,可以使用Python內置的csv和json模塊來實現(xiàn)將csv文件轉為json的操作,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2023-11-11
  • Python使用窮舉法求兩個數的最大公約數問題

    Python使用窮舉法求兩個數的最大公約數問題

    這篇文章主要介紹了Python使用窮舉法求兩個數的最大公約數問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • Python定制類你不知道的魔術方法

    Python定制類你不知道的魔術方法

    你知道什么是定制類?Python中包含很多內置的(Built-in)函數,異常,對象。分別有不同的作用,我們可以重寫這些功能,希望對大家有所幫助。一起跟隨小編過來看看吧
    2022-07-07
  • python修改字典鍵(key)的方法

    python修改字典鍵(key)的方法

    在本篇文章里小編給大家整理的是關于python修改字典鍵(key)的方法以及相關知識點,需要的朋友們參考下。
    2019-08-08
  • 用Python編寫一個簡單的俄羅斯方塊游戲的教程

    用Python編寫一個簡單的俄羅斯方塊游戲的教程

    這篇文章主要介紹了用Python編寫一個簡單的俄羅斯方塊游戲的教程,編寫俄羅斯方塊幾乎是每門編程語言基礎學習后的必備實踐,需要的朋友可以參考下
    2015-04-04
  • 網絡瀏覽器中運行Python腳本PyScript剖析

    網絡瀏覽器中運行Python腳本PyScript剖析

    這篇文章主要為大家介紹了網絡瀏覽器中運行Python腳本PyScript剖析詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-08-08
  • Python?queue模塊功能大全

    Python?queue模塊功能大全

    queue模塊是Python內置的標準模塊,可以直接通過import?queue引用,這篇文章主要介紹了Python?queue模塊都具有哪些功能,需要的朋友可以參考下
    2023-04-04

最新評論