Heim > Backend-Entwicklung > Python-Tutorial > Analyse von Funktionen höherer Ordnung und Funktionsdekoratoren in Python

Analyse von Funktionen höherer Ordnung und Funktionsdekoratoren in Python

黄舟
Freigeben: 2017-10-01 07:44:27
Original
1166 Leute haben es durchsucht

Der folgende Editor bietet Ihnen eine detaillierte Diskussion der höherwertigen Funktionen und Funktionsdekoratoren von Python (empfohlen). Der Herausgeber findet es ziemlich gut, deshalb teile ich es jetzt mit Ihnen und gebe es als Referenz. Schauen Sie sich den Editor an

1. Überprüfen Sie den vorherigen Abschnitt

Python2- und Python3-Zeichenkodierungsprobleme, egal ob Sie ein Anfänger oder ich kenne Python-Projekte bereits gut und werde einige Programmierfehler machen. Die Unterschiede zwischen Python3 und Python2 werde ich hier kurz zusammenfassen.

Zuallererst werden alle Python3-->Codedateien in utf-8 interpretiert. Wenn Codes und Dateien in den Speicher eingelesen werden, werden sie zu Unicode. Deshalb kodiert Python nur, dekodiert aber nicht, da die Zeichenkodierung im Speicher in Unicode geändert wird und Unicode ein universeller Code ist, der so „übersetzt“ werden kann Formatkodierungsformat. In Python3 sind str und Bytes zwei Formate, und Bytes können als Binärdarstellung verwendet werden.

Python2 verwendet die Standardzeichenkodierung des Systems, um den Code zu interpretieren. Wenn Sie also utf-8 zur Interpretation des Codes verwenden möchten, müssen Sie ihn im Header deklarieren. In Python2 gibt es jedoch eine Dekodierung und Kodierung Die Dekodierungsaktion ist erforderlich und die Kodierungsaktion kann ignoriert werden, da der in den Speicher geladene Python-Code Unicode ist, der mit Python3 identisch ist. In Python2 ist außerdem zu beachten, dass str und Bytes dieselbe Bedeutung haben. Der str in Python2 ist das Byteformat in Python3, und der str in Python3 ist eigentlich Unicode.

Funktionsgrundlagen (hier verwende ich die binäre Suche in der rekursiven Funktion)

Warum Funktionen verwenden? : Das Programm wird als Modul konzipiert

Es gibt drei Formen definierter Funktionen:

- Parameterlose Funktion

- Funktion mit Parametern

- Leere Funktion

PS: Wenn die Funktion mehrere Rückgabewerte hat, dann die zurückgegebenen Datenformat Ist ein Tupel

– So begrenzen Sie das Parameterdatenformat, wenn die Funktion Parameter übergibt.

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

pass

wobei x und y hier angegeben werden und vom Typ int sein müssen" -> ; " bedeutet, dass der Rückgabewert der Funktion auch vom Typ int sein muss

print(yan.__annotations__): zeigt das eingeschränkte Datenformat der formalen Parameter und das Format des Rückgabewerts an


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)
Nach dem Login kopieren

Anonyme Funktion


c = lambda x:x+1 #x就是形参,c就是这个匿名函数的对象

print(c(22))
Nach dem Login kopieren

Funktionsmerkmale höherer Ordnung

1. Übergeben Sie die Speicheradresse von eine Funktion an eine andere Funktion als Parameter

2. Eine Funktion gibt eine andere Funktion als Rückgabewert zurück


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

calc(-5,10,abs) #引用上一节的实例,将-5和10绝对值相加
Nach dem Login kopieren

2. Funktionen höherer Ordnung (ergänzend)

Funktion ist ein erstklassiges Objekt

Funktion kann ein Wert zugewiesen werden

kann als Parameter verwendet werden

kann als Rückgabewert verwendet werden

kann als Element des Containertyps verwendet werden


#函数可以被赋值
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这个函数并没有被执行
j() #运行 leon函数

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

leon_dict["leon"]() #这样也可以运行leon这个函数
Nach dem Login kopieren

3. Verschlussfunktion

1. Lassen Sie mich einen Blick darauf werfen und das Konzept auf der offiziellen Website vergleichen (dies ist nicht das, was ich auf der offiziellen Website gefunden habe, aber es spielt keine Rolle, Sie können es sowieso nicht verstehen):

Schließung ist lexikalisch Die Abkürzung von ist eine Funktion, die sich auf freie Variablen bezieht. Die referenzierte freie Variable verbleibt bei der Funktion, auch nachdem sie die Umgebung, in der sie erstellt wurde, verlassen hat. Daher ist ein Abschluss eine Entität, die aus einer Funktion und der zugehörigen Referenzumgebung besteht.

Verwirrt? Existiert nicht. Ich werde im Folgenden kurz darauf eingehen, aber eines ist sehr wichtig. Wenn Sie Abschlüsse nicht wirklich verstehen, werden Sie sie nach dem Erlernen von Dekorateuren schnell vergessen. Lassen Sie es uns anhand eines Beispiels veranschaulichen


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函数呢
Nach dem Login kopieren

PS: Hier können wir die Funktion als spezielle Variable behandeln, wenn der Code beginnt von Wenn beim Ausführen von Auf und Ab die Funktion nicht aufgerufen wird, wird der Code innerhalb der Funktion nicht ausgeführt. Nehmen Sie das obige Beispiel. Wenn wir die Funktion get ausführen, wird die Speicheradresse einer Wapper-Funktion zurückgegeben. Mit anderen Worten, der von g() zurückgegebene Status ist eigentlich der Wapper, das bedeutet, dass wir nur g ausführen müssen, was dem Ausführen des Codes im Wapper entspricht.

4. Verschachtelter Aufruf von Funktionen

Verschachtelter Aufruf ist eigentlich leicht zu verstehen, er ist das Ergebnis des Aufrufs einer anderen Funktion innerhalb einer Funktion. Schauen wir uns in ähnlicher Weise einen sehr einfachen Code an.


#嵌套调用,在一个函数中调用另一个函数的功能
#calc这个函数就是在对比两个数字的大小
def calc2(x,y):
 if x >y :
 return x
 else:
 return y

#我靠老板非常变态,然你直接计算四个数字的大小,擦。
def calc4(a,b,c,d):
 res1 = calc2(a,b) #res1的值,这里不就是calc2这个函数比较时最大的哪一个吗。
 res2 = calc2(res1,c)
 res3 = calc2(res2,d)
 return res3
Nach dem Login kopieren

Wir erstellen eine Erinnerung durch den obigen Code. Wann werden verschachtelte Aufrufe verwendet? Offensichtlich ist es unsere Funktion (calc4), die das Ausführungsergebnis einer anderen Funktion (Rückgabe y oder x) benötigt.

5. Decorator (erweiterte Verschlussfunktion)

Nehmen Sie den folgenden Code als Beispiel. So berechnen Sie die Laufzeit des Codes, ohne den Quellcode zu ändern


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

geturl(http://www.baidu.com)
Nach dem Login kopieren


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)
Nach dem Login kopieren

Illustrierter Code

装饰器必备:

@timer就是装饰器,意思是装饰它下面的函数,而装饰器和被装饰的都是一个函数。

timer(装饰器函数),首先它会有一个位置参数(func)名字随意,但是必须并且只能是一个位置参数

func参数就是被装饰的geturl这个函数

为什么func是geturl这个函数呢-->上面写了一个装饰器功能:geturl=timer(geturl),我们看到这里的timer中传入的其实就是func函数所以func = geturl(被装饰的函数)

分析geturl=timer(geturl),首先我们可以得知timer这是一个闭包函数,当我们执行这个闭包函数,会把里层的函数(wapper)返回,也就是说timer(geturl)其实就是返回的wapper,所以就可以这样理解了geturl==wapper,所以当我们运行geturl的时候就相当于在执行wapper()这样的一个操作;如果这里实在记不住,就这样。咱上面不是有一个闭包函数吗?你就把geturl=timer(geturl)中的geturl(执行函数的返回结果)当做上面g(函数调用的返回结果),然后在分别再执行了下"g"或者"geturl”这个对象。

如果被装饰者有位置参数的话,我们需要在wapper函数中加上对应的位置参数用来接收,如果长度是不固定的话还可以用*args和**kwargs

六、有参装饰器

听着名字顾名思义,就是在装饰器中还有位置参数。


#一个low得不能再low得验证脚本,如果是显示环境中所有数据必须是由数据库或者一个静态文件提供,并且登录成功时,需要保存用户的一个状态

def auth(auth_type): #有参装饰器名称
 def auth_deco(func): #定义第二层函数名称
 def wrapper(*args,**kwargs): #最里层函数,主要实现认证功能
  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(&#39;file&#39;)
def home():
 print("welcome")

home() #执行home-->wrapper
Nach dem Login kopieren

有参函数必备知识:

套路,通过上面无参装饰器,我们得出了geturl=timer(geturl)这个等式。回到有参装饰器,我们又会有什么样子的等式呢?首先@auth("file")是一个装饰器也就是一个函数,所以我们定义了一个auth(auth_type)这个函数,而这个函数返回的是什么呢?没有错就是第二层函数;到了这里我们就会发现@auth("file")其实就是@auth_deco,现在我们知道了现在装饰器其实就是auth_deco,那剩下的还不知道怎么写吗?

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

如果记不住?如果实在是记不住,其实就可以这样理解,有参装饰器无非就是在无参装饰器上面加了一层(三层),然后在第一层返回了第二层的函数,而到了第二层就和我们普通用的装饰器是一毛一样了

七、模块导入

import ,创建一个leonyan.py的模块文件,等待被导入


a = 10
b = 20
c = 30

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

def read2():
 print("in the read2")
Nach dem Login kopieren

导入leonyan.py文件(调用模块文件和模块文件在同一目录下)


import leonyan #Python IDE这行会爆红,但是不用管

leonyan.read1() #执行leonyan这个包中的read1函数

leonyan.read2() #执行leonyan这个包中read2函数

print(leonyan.a + leonyan.b + leonyan.c ) #输出60
Nach dem Login kopieren

总结:在Python中包的导入(import ***)会干三个事情:1:创建新的作用域;2:执行该作用域的顶级代码,比如你导入的那个包中有print执行后就会直接在屏幕中输出print的内容;3:得到一个模块名,绑定到该模块内的代码

在模块导入的时候给模块起别名


import leonyan as ly
import pandas as pd #这是一个第三方模块,以后的博客中会写到,这是一个用于做统计的
Nach dem Login kopieren

给模块起别名还是挺多的,在有些模块的官方文档中,还是比较推荐这种方法的,比如pandas的官方文档中就是起了一个pd别名,总之as就是一个模块起别名


from *** import ***

from leonyan import read1 #引入直接调用
read1()
Nach dem Login kopieren

如果在调用模块的函数作用域中有相同的同名的,会将调用过来的覆盖。

在form ** import ** 中控制需要引用的变量(函数其实在未被执行的时候也是一个存放在内存中的变量)


from leonyan import read1,read2 在同一行中可以引用多个,只需要用逗号隔开就行了

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

#需求我现在只需要导入read2

这时候我们就可以在leonyan这个函数中加上这么一行:

__all__ = ["read2"] #这里的意思就是别的文件调用为的时候用from ** import ** 只能拿到read2 这个函数的内存地址,也就是只有read2可以被调用
Nach dem Login kopieren

把模块当做一个脚本执行

我们可以通过模块的全局变量__name__来查看模块名:

当做脚本运行:

__name__ 等于'__main__'

作用:用来控制.py文件在不同的应用场景下执行不同的逻辑

if __name__ == '__main__':


#fib.py

def fib(n): # write Fibonacci series up to n
 a, b = 0, 1
 while b < n:
 print(b, end=&#39; &#39;)
 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]))
Nach dem Login kopieren

代码执行 Python flb.py 100

只需要简单了解的Python模块导入搜索路径

内建(build-in)  --> sys.path(sys.path是一个列表,而且第一个位置就是当前文件夹)

模块导入的重点-->包的导入

In einer tatsächlichen Entwicklungsumgebung können Sie den Code einer Datei nicht bis zum Ende schreiben. Natürlich können Sie auch auf andere Module im selben Ordner verweisen, aber haben Sie jemals gedacht, dass dieses Projekt nicht von Ihnen alleine geschrieben werden kann? werden von vielen Menschen gemeinsam entwickelt. Dies führt zu einem Problem: Es ist unmöglich, dass verschiedene Personen denselben Computer verwenden, und es ist unmöglich, Funktionen im selben Ordner zu schreiben. Sie haben auch ihre eigenen Codeordner, und dann ruft jeder die Funktionen über Schnittstellen auf. Derzeit stehen wir vor dem Problem, diese verschiedenen Ordner aufzurufen. Diese Art von Problem muss auch vom ** Import ** aufgerufen werden.

Im Bild oben führe ich den Ordner „module import.py“ aus. Zuerst importiere ich die Konfiguration aus Pythonscript.leonyan.command, da wir das Skript ausführen müssen und die Dinge, die importiert werden müssen, befinden sich alle im Pythonscript-Verzeichnis, also habe ich sie direkt über den absoluten Pfad importiert und bin dann Schicht für Schicht nach unten gegangen, bis ich schließlich die Konfigurationsdatei importiert habe Achten Sie auf eines: Wenn das Skript in der äußersten Ebene ausgeführt wird, ist der erste Parameter in der Pfadliste das Verzeichnis, in dem das Skript ausgeführt wird. Dies bedeutet, dass Sie andere Dinge aufgerufen haben Pakete. Meine config.py ruft beispielsweise die Datei bing.py auf. Sie müssen den absoluten Pfad schreiben, da sie nicht mehr im Ordner sys.path gefunden werden kann, was bedeutet, dass sie nicht importiert werden kann.

Zusammenfassung: Der Import von Paketen ist eigentlich sehr einfach. Sie müssen eines beachten: Wenn Sie das integrierte Python- oder heruntergeladene Modul eines Drittanbieters importieren , verwenden Sie es direkt import import. Wenn Sie es selbst schreiben, verwenden Sie einfach from ** import ** und verwenden Sie das absolute Verzeichnis zum Importieren, dh den Import aus dem übergeordneten Verzeichnis des aufrufenden Skripts. Dadurch wird sichergestellt, dass Modulimportfehler nicht gemeldet werden.

Das obige ist der detaillierte Inhalt vonAnalyse von Funktionen höherer Ordnung und Funktionsdekoratoren in Python. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage