Heim  >  Artikel  >  Backend-Entwicklung  >  Vertiefendes Verständnis des Python-Schließmechanismus

Vertiefendes Verständnis des Python-Schließmechanismus

零到壹度
零到壹度Original
2018-04-14 10:28:062928Durchsuche

Dieser Artikel verwendet Python als Beispiel, um Abschlüsse in einfachen Worten zu erklären. Laut Baidu Encyclopedia ist ein Abschluss eine Funktion, die die internen Variablen anderer Funktionen lesen kann. In JavaScript sind es beispielsweise nur Unterfunktionen innerhalb der Funktion kann lokale Variablen lesen. Daher kann der Abschluss als „eine innerhalb einer Funktion definierte Funktion“ verstanden werden. Der Abschluss ist im Wesentlichen die Brücke, die das Innere der Funktion mit dem Äußeren der Funktion verbindet

Verstehen Sie die Definition des Abschlusses


Definition: Ein Abschluss ist eine Funktion, die die internen Variablen anderer lesen kann Funktionen

Verstehen: Gemäß der Split-Statement-Analyse ist der Abschluss ... eine Funktion Die Details, um zu sehen, um welche Art von Funktion es sich handelt, können auch gelesen werden. Holen Sie sich die internen Variablen anderer Funktionen. Mit anderen Worten, die Abschlussfunktion kann die Informationen der internen Variablen anderer Funktionen abrufen Informationen werden wie ein Paket gekapselt, was anschaulicher ist

Beispiel:

def make_averager():
    series = []    def averager(new_value):
        series.append(new_value)
        total = sum(series)        return total/len(series)    return averager
>>> avg = make_averager()>>> avg(10)10.0>>> avg(11)10.5>>> avg(12)11.0

Hinweis: „Closure“ ist die Abkürzung für lexikalische Schließung. Es handelt sich um eine wichtige grammatikalische Struktur der funktionalen Programmierung.


Pythons Namespace und Umfang Regeln

In C++ gibt es ein spezielles Schlüsselwort namespace (Namespace in Englisch)

Ohne C++ zu reden, in Python gibt es vier Namespaces:

1) local namespace: lokale Variablen

2) nonlocal namespace: Variablen äußerer Funktionen in verschachtelten Funktionen (Python3.x)

3) global namespace: Globale Variablen

4) build-in namespace: Integrierte Variablen

Namespace ist eine Zuordnung von Variablennamen zu tatsächlichen Objekten. Die meisten Namespaces werden als Wörterbücher in Python implementiert. Das Schlüsselwort

wurde in Python 3.0 eingeführt Dieses Schlüsselwort ermöglicht den einfachen Zugriff und die Änderung der äußeren Variablen verschachtelter Funktionen (wenn Sie nur ohne Änderung darauf zugreifen, benötigen Sie das nicht lokale Schlüsselwort nicht) nonlocal

Wenn Sie Ändern Sie die äußeren Variablen. Wenn Sie jedoch das Schlüsselwort nicht verwenden, wird ein Fehler gemeldet: nonlocal

def make_averager():
    count = 0
    total = 0

    def averager(new_value):
        count += 1    # Same as: count = count + 1
        total += new_value        return total/count    return average
>>> avg = make_averager()
>>> avg(10)
Traceback (most recent call last):...UnboundLocalError: Local variable 'count' referened before assignment
>>>

So ändern Sie die Für die äußere Variable müssen Sie das Schlüsselwort verwenden: nonlocal

def make_averager():
    count = 0
    total = 0

    def averager(new_value):
        nonlocal count, total    # Declaration of namespace.
        count += 1
        total += new_value        return total/count    return average
>>> avg = make_averager()>>> avg(10)10.0>>> avg(11)10.5>>> avg(12)12

Erläuterung: In der Durchschnittsfunktion sind Anzahl und Gesamtmenge freie Variablen ( Freie Variablen beziehen sich auf solche, die nicht lokal gebunden sind. Variable ), freie Variablen werden häufig in einem Bereich deklariert und in einem anderen Bereich verwendet (z. B. Reihe, Anzahl, Summe oben)

Warum kann dann im Beispiel „Die Definition des Abschlusses verstehen“ die Reihenvariable zwar auch eine freie Variable für die innere Funktion sein, sie aber direkt geändert werden? Hier müssen wir die Bedeutung von „Änderung“ zwischen veränderlichen Typen und unveränderlichen Typen unterscheiden. Die -Methode besteht darin, den Wert der Liste an Ort und Stelle zu ändern append() Nur Die Listenfunktion „Listenvariable“ wird verwendet , aber für unveränderliche digitale Objekte Anzahl, Gesamtmenge, , eine solche Operation generiert tatsächlich ein neues Objekt count += 1

Vertiefendes Verständnis des Python-Schließmechanismus

Vertiefendes Verständnis des Python-Schließmechanismus

Denken Sie immer daran, dass freie Variablen nur referenziert und nicht geändert werden können (es sei denn, veränderbare Objekte können tatsächlich an Ort und Stelle geändert werden). Wie Abschlüsse in Python2 implementiert werden gleich sein

Zu Demonstrationszwecken ist die Verwendung einer for-Schleife oder eines Pythonic-Listenverständnisses eine gute Wahl:



Abschlüsse und DekoratorenVertiefendes Verständnis des Python-Schließmechanismus

Vertiefendes Verständnis des Python-Schließmechanismus

Um Ihren eigenen Dekorator in Python zu implementieren, müssen Sie das Wissen beherrschen: 1) Abschluss + verschachtelte Funktion, 2) nicht lokales Schlüsselwort (eingeführt in Python3.x) Vertiefendes Verständnis des Python-Schließmechanismus

""" Implement a decorator, which return the runtime of the program. """import timedef clock(func):
    def clocked(*args):
        t0 = time.pref_counter()
        result = func(*args)
        elapsed = time.pref_counter() - t0
        name = func.__name__
        arg_str = ', '.join(repr(arg) for arg in args)
        print('[%0.8fs] %s(%s) -> %r' %(elpased, name, arg_str, result))        return result    return clocked

Vertiefendes Verständnis des Python-Schließmechanismus

本文以Python为例,深入浅出讲解闭包;根据百度百科的解释,闭包就是能够读取其他函数内部变量的函数,例如在JavaScript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成『定义在一个函数内部的函数』;在本质上,闭包是将函数内部和函数外部连接起来的桥梁


理解闭包的定义

定义:闭包(closure)是能够读取其它函数内部变量的函数

理解:根据拆分语句分析,闭包是……函数,原来闭包是函数,再看细节部分,闭包是怎样的函数,闭包还能够读取其它函数内部变量,换句话说,闭包函数可以获取其它函数内部变量的信息——这样信息就被封装起来了,像一个包一样,比较形象

实例:

def make_averager():
    series = []    def averager(new_value):
        series.append(new_value)
        total = sum(series)        return total/len(series)    return averager
>>> avg = make_averager()>>> avg(10)10.0>>> avg(11)10.5>>> avg(12)11.0

备注:闭包(closure)是词法闭包(lexical closure)的简称,是函数式编程的重要的语法结构


Python的命名空间、作用域规则

在C++中,有个专门的关键字namespace(命名空间的英文)

不扯C++,在Python中,存在四种命名空间:

1)local namespace:本地变量

2)nonlocal namespace:嵌套函数中外层函数的变量(Python3.x)

3)global namespace:全局变量

4)build-in namespace:内置变量

namespace是变量名到实际对象的一个映射,大部分namespace都是按Python中的字典来实现的

nonlocal关键字在Python3.0中被引入,使用这个关键字可以轻松的访问并修改嵌套函数的较外层变量(如果仅仅是访问而不修改可以不用nonlocal关键字)

如果修改外层变量却不使用nonlocal关键字会报错:

def make_averager():
    count = 0
    total = 0

    def averager(new_value):
        count += 1    # Same as: count = count + 1
        total += new_value        return total/count    return average
>>> avg = make_averager()
>>> avg(10)
Traceback (most recent call last):...UnboundLocalError: Local variable 'count' referened before assignment
>>>

要修改外层变量就必须使用nonlocal关键字:

def make_averager():
    count = 0
    total = 0

    def averager(new_value):
        nonlocal count, total    # Declaration of namespace.
        count += 1
        total += new_value        return total/count    return average
>>> avg = make_averager()>>> avg(10)10.0>>> avg(11)10.5>>> avg(12)12

解释:在averager函数中,count、total是自由变量(自由变量是指未在本地绑定的变量),自由变量往往是在一个作用域中声明,并在另一个作用域中使用(比如上面的series、count、total)

那为什么在『理解闭包的定义』的实例中,series变量虽然对于内层函数也是自由变量但是却可以直接修改?这里要区分开可变类型和不可变类型的『修改』的含义,series列表是可变序列,append()方法于在原地修改列表的值,这里我们只用到了『列表可变』这一列表的特性,但是对于不可变的数字对象count、total,count += 1,这样的操作实际上生成了新的对象

Vertiefendes Verständnis des Python-Schließmechanismus

Vertiefendes Verständnis des Python-Schließmechanismus

始终记住,自由变量只能引用不能修改(除非可变对象可以原地修改,事实上Python2.x中就是这样实现闭包的),要修改就必须使用nonlocal关键字




闭包和lambda表达式

Python的lambda表达式就是匿名函数,二者可以划等号

出于演示考虑,用for循环或者Pythonic的列表推导是个不错的选择:

Vertiefendes Verständnis des Python-Schließmechanismus

Vertiefendes Verständnis des Python-Schließmechanismus

Vertiefendes Verständnis des Python-Schließmechanismus

Vertiefendes Verständnis des Python-Schließmechanismus




闭包和装饰器

要在Python中实现自己的装饰器(decorator),必须掌握的知识:1)闭包+嵌套函数,2)nonlocal关键字(Python3.x引入)

""" Implement a decorator, which return the runtime of the program. """import timedef clock(func):
    def clocked(*args):
        t0 = time.pref_counter()
        result = func(*args)
        elapsed = time.pref_counter() - t0
        name = func.__name__
        arg_str = ', '.join(repr(arg) for arg in args)
        print('[%0.8fs] %s(%s) -> %r' %(elpased, name, arg_str, result))        return result    return clocked

Das obige ist der detaillierte Inhalt vonVertiefendes Verständnis des Python-Schließmechanismus. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
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