Heim > Backend-Entwicklung > Python-Tutorial > Ausführliche Erklärung der Verwendung des Schlüsselworts with in Python

Ausführliche Erklärung der Verwendung des Schlüsselworts with in Python

高洛峰
Freigeben: 2017-03-28 15:21:12
Original
1716 Leute haben es durchsucht

In diesem Artikel werden hauptsächlich relevante Informationen zur detaillierten Verwendung des Schlüsselworts with in Python vorgestellt. In Python ist das Schlüsselwort with eine gute Möglichkeit, die Implementierung von Kontextprotokollobjekten für Sie zu verwalten it Sie können auf Folgendes verweisen ">

In Python 2.5 wurde das Schlüsselwort with hinzugefügt. Es macht das häufig verwendete Muster try ... außer ... endlich ... Sehr praktisch Wiederverwendung. Schauen Sie sich das klassischste Beispiel an:

In diesem Code wird die Datei unabhängig davon, was während der Ausführung des Codeblocks passiert, irgendwann geschlossen Bei der Ausführung schließt das Programm die geöffnete Datei, bevor die Ausnahme ausgelöst wird. Sehen Sie sich vor dem Initiieren einer Datenbank einen ähnlichen Code an:

1

2

with open('file.txt'as f:

  content = f.read()

Nach dem Login kopieren

Wenn der Vorgang zum Initiieren einer Transaktionsanforderung geändert wird, um das Schlüsselwort with zu unterstützen, reicht ein Code wie dieser aus:

Der Ausführungsprozess von with wird ausführlich erläutert und der obige Code wird implementiert auf zwei gängige Arten.

1

2

3

4

5

6

7

8

db.begin()

try:

  do some actions

except:

  db.rollback()

  raise

finally:

  db.commit()

Nach dem Login kopieren

Der allgemeine Ausführungsprozess von with

1

2

with transaction(db):

  do some actions

Nach dem Login kopieren
Ein grundlegender mit

Ausdruck

, seine Struktur ist wie folgt:

wobei: EXPR ein beliebiger Ausdruck sein kann; da VAR für seine allgemeine Ausführung optional ist. Der Prozess ist wie folgt:

Berechnen Sie EXPR und erhalten Sie einen Kontextmanager

1

2

with EXPR as VAR:

  BLOCK

Nach dem Login kopieren

Die Methode „exit()“ des Kontextmanagers wird gespeichert.
  1. Rufen Sie die Methode „enter()“ des Kontextmanagers auf.
  2. Wenn der with-Ausdruck als VAR enthält, dann wird EXPR der Rückgabewert VAR zugewiesen.
  3. Führen Sie den Ausdruck in BLOCK aus. Wenn während der Ausführung von BLOCK eine Ausnahme auftritt und das Programm beendet wird, werden der Ausnahmetyp, der Wert und der Traceback (dh der Rückgabewert von sys.exc_info()) als Parameter an die Methode „exit()“ übergeben. drei Keine werden übergeben.
  4. Stellen Sie diesen Prozess wie folgt im Code dar:
  5. Dieser Prozess hat mehrere Details:

  6. Wenn in der Kontextmanager Ohne eine der Methoden enter() oder exit() löst der Interpreter einen AttributeError aus.
  7. Wenn nach dem Auftreten einer Ausnahme in BLOCK die Methode „exit()“ einen Wert zurückgibt, der als „True“ angesehen werden kann, wird die Ausnahme nicht ausgelöst und der nachfolgende Code wird weiterhin ausgeführt.

    Als nächstes verwenden wir zwei Methoden, um den obigen Prozess zu implementieren.
Implementieren Sie die Kontextmanagerklasse

Die erste Möglichkeit besteht darin, eine Klasse zu implementieren, die eine Instanz

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

mgr = (EXPR)

exit = type(mgr).exit # 这里没有执行

value = type(mgr).enter(mgr)

exc = True

try:

  try:

    VAR = value # 如果有 as VAR

    BLOCK

  except:

    exc = False

    if not exit(mgr, *sys.exc_info()):

      raise

finally:

  if exc:

    exit(mgr, None, None, None)

Nach dem Login kopieren
Attribute

db und die für den Kontextmanager erforderlichen Methoden enter() und exit enthält () .


Nachdem man den Ausführungsprozess von with verstanden hat, ist diese Implementierung leicht zu verstehen. Die unten vorgestellte Implementierungsmethode ist viel komplizierter zu verstehen.

Verwendung von

Generatoren

Dekoratoren

In der Standardbibliothek von Python gibt es einen Dekorator, der über einen Generator einen Kontextmanager erhalten kann. Der Implementierungsprozess mithilfe des Generator-Dekorators ist wie folgt:

1

2

3

4

5

6

7

8

9

10

class transaction(object):

  def init(self, db):

    self.db = db

  def enter(self):

    self.db.begin()

  def exit(self, type, value, traceback):

    if type is None:

      db.commit()

    else:

      db.rollback()

Nach dem Login kopieren

Auf den ersten Blick ist diese Implementierung einfacher, ihr Mechanismus ist jedoch komplexer. Werfen wir einen Blick auf den Ausführungsprozess:

Nachdem der Python-Interpreter das Schlüsselwort yield erkennt, erstellt def eine Generator-Funktion , um die reguläre Funktion zu ersetzen (im (Klassendefinition: Ich verwende gerne Funktionen anstelle von Methoden).

1

2

3

4

5

6

7

8

9

10

11

from contextlib import contextmanager

@contextmanager

def transaction(db):

  db.begin()

  try:

    yield db

  except:

    db.rollback()

    raise

  else:

    db.commit()

Nach dem Login kopieren
Der Decorator-Kontextmanager wird aufgerufen und gibt eine Hilfsmethode zurück, die nach dem Aufruf eine GeneratorContextManager-Instanz generiert. Schließlich ruft der EXPR im with-Ausdruck die vom Contentmanager-Dekorator zurückgegebene Hilfsfunktion auf. Der

  1. with-Ausdruck ruft die Transaktion(db) auf, die tatsächlich die Hilfsfunktion aufruft. Die Hilfsfunktion ruft die Generatorfunktion auf, die einen Generator erstellt.

    Die Hilfsfunktion übergibt diesen Generator an GeneratorContextManager und erstellt eine Instanz von GeneratorContextManager als Kontextmanager.
  2. with 表达式调用实例对象的上下文管理器的 enter() 方法。

  3. enter() 方法中会调用这个生成器的 next() 方法。这时候,生成器方法会执行到 yield db 处停止,并将 db 作为 next() 的返回值。如果有 as VAR ,那么它将会被赋值给 VAR 。

  4. with 中的 BLOCK 被执行。

  5. BLOCK 执行结束后,调用上下文管理器的 exit() 方法。 exit() 方法会再次调用生成器的 next() 方法。如果发生 StopIteration 异常,则 pass 。

  6. 如果没有发生异常生成器方法将会执行 db.commit() ,否则会执行 db.rollback() 。

再次看看上述过程的代码大致实现:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

def contextmanager(func):

  def helper(*args, **kwargs):

    return GeneratorContextManager(func(*args, **kwargs))

  return helper

class GeneratorContextManager(object):

  def init(self, gen):

    self.gen = gen

  def enter(self):

    try:

      return self.gen.next()

    except StopIteration:

      raise RuntimeError("generator didn't yield")

  def exit(self, type, value, traceback):

    if type is None:

      try:

        self.gen.next()

      except StopIteration:

        pass

      else:

        raise RuntimeError("generator didn't stop")

    else:

      try:

        self.gen.throw(type, value, traceback)

        raise RuntimeError("generator didn't stop after throw()")

      except StopIteration:

        return True

      except:

        if sys.exc_info()[1] is not value:

          raise

Nach dem Login kopieren

总结

Python的 with 表达式包含了很多Python特性。花点时间吃透 with 是一件非常值得的事情。

一些其他的例子

锁机制

1

2

3

4

5

6

7

@contextmanager

def locked(lock):

  lock.acquired()

  try:

    yield

  finally:

    lock.release()

Nach dem Login kopieren

标准输出重定向

1

2

3

4

5

6

7

8

9

10

11

@contextmanager

def stdout_redirect(new_stdout):

  old_stdout = sys.stdout

  sys.stdout = new_stdout

  try:

    yield

  finally:

    sys.stdout = old_stdout

with open("file.txt""w"as f:

  with stdout_redirect(f):

    print "hello world"

Nach dem Login kopieren

Das obige ist der detaillierte Inhalt vonAusführliche Erklärung der Verwendung des Schlüsselworts with in Python. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
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