python with statement

If you have some objects (such as a file, a network connection or lock), with the need to support the statement, the following describes two methods defined.

method 1):

First introduced to the works with
(1) keeping up with the following statements is evaluated, the returned object ' __enter__()' method is called, the return value of this method will be assigned to as the back of the variables;
(2) when the latter with after all of the code block is executed, the call returns an object in front, " __exit__()" method.

It works with code examples:

class Sample:
    def __enter__(self):
        print "in __enter__"
        return "Foo"
    def __exit__(self, exc_type, exc_val, exc_tb):
        print "in __exit__"
def get_sample():
    return Sample()
with get_sample() as sample:
    print "Sample: ", sample
  
  
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

Operation result code as follows:

in __enter__
Sample:  Foo
in __exit__
  
  
  
  
  • 1
  • 2
  • 3

Can be seen, the entire operation process is as follows:
(. 1) Enter () method is executed;
Return value (2) enter () method in this case is the "Foo", assigned to the variable Sample;
(. 3) block of code print sample value of the variable "Foo";
(. 4) Exit () method is called;

[NOTE:] exit () method has three parameters, exc_type, exc_val, exc_tb, these parameters are very useful in the exception process.
exc_type: the type of error
exc_val: the value corresponding to the error type
exc_tb: location code error occurs in
the sample code:

class Sample():
    def __enter__(self):
        print('in enter')
        return self
    def __exit__(self, exc_type, exc_val, exc_tb):
        print "type: ", exc_type
        print "val: ", exc_val
        print "tb: ", exc_tb
    def do_something(self):
        bar = 1 / 0
        return bar + 10
with Sample() as sample:
    sample.do_something()
  
  
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

Program output:

in enter
Traceback (most recent call last):
type:  <type 'exceptions.ZeroDivisionError'>
val:  integer division or modulo by zero
  File "/home/user/cltdevelop/Code/TF_Practice_2017_06_06/with_test.py", line 36, in <module>
tb:  <traceback object at 0x7f9e13fc6050>
    sample.do_something()
  File "/home/user/cltdevelop/Code/TF_Practice_2017_06_06/with_test.py", line 32, in do_something
    bar = 1 / 0
ZeroDivisionError: integer division or modulo by zero

Process finished with exit code 1
  
  
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

Method (2):

The easiest way to implement a new context manager is to use contexlib module @contextmanager decorator. Here's an example of a context manager code block timing functions:

import time
from contextlib import contextmanager

@contextmanager
def timethis(label):
    start = time.time()
    try:
        yield
    finally:
        end = time.time()
        print('{}: {}'.format(label, end - start))
  
  
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
# Example use
with timethis('counting'):
    n = 10000000
    while n > 0:
        n -= 1
  
  
  
  
  • 1
  • 2
  • 3
  • 4
  • 5

Timethis the function (), the code as to the yield in the context manager __enter__()method is performed, all the codes as would yield after __exit__()performing the method. If an exception occurs, an exception will be thrown in the yield statement there.

[Note]
1, @ contextmanager should only be used to write self-contained context management function.
2, if you have some objects (such as a file, a network connection or lock), the need to support with the statement, then you need to implement a separate __enter__()method and __exit__()method.

Guess you like

Origin blog.csdn.net/weixin_44090305/article/details/92170334