zoukankan      html  css  js  c++  java
  • python的with语法的深入理解

    如果你有一些对象(比如一个文件、网络连接或锁),需要支持 with 语句,下面介绍两种定义方法。

    方法(1):

    首先介绍下with 工作原理
    (1)紧跟with后面的语句被求值后,返回对象的“__enter__()”方法被调用,这个方法的返回值将被赋值给as后面的变量;
    (2)当with后面的代码块全部被执行完之后,将调用前面返回对象的“__exit__()”方法。

    with工作原理代码示例:

    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
    

      代码的运行结果如下:

    in __enter__
    Sample:  Foo
    in __exit__
    

      

    可以看到,整个运行过程如下:
    (1)enter()方法被执行;
    (2)enter()方法的返回值,在这个例子中是”Foo”,赋值给变量sample;
    (3)执行代码块,打印sample变量的值为”Foo”;
    (4)exit()方法被调用;

    【注:】exit()方法中有3个参数, exc_type, exc_val, exc_tb,这些参数在异常处理中相当有用。
    exc_type: 错误的类型
    exc_val: 错误类型对应的值
    exc_tb: 代码中错误发生的位置
    示例代码:

    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()
    

      程序输出结果:

    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
    

      

    方法(2):

    实现一个新的上下文管理器的最简单的方法就是使用 contexlib 模块中的 @contextmanager 装饰器。 下面是一个实现了代码块计时功能的上下文管理器例子:

    import time
    from contextlib import contextmanager
    
    @contextmanager
    def timethis(label):
        start = time.time()
        try:
            yield
        finally:
            end = time.time()
            print('{}: {}'.format(label, end - start))
    

      

    # Example use
    with timethis('counting'):
        n = 10000000
        while n > 0:
            n -= 1
    

      

    在函数 timethis() 中,yield 之前的代码会在上下文管理器中作为 __enter__() 方法执行, 所有在 yield 之后的代码会作为 __exit__() 方法执行。 如果出现了异常,异常会在yield语句那里抛出。

    【注】
    1、@contextmanager 应该仅仅用来写自包含的上下文管理函数。
    2、如果你有一些对象(比如一个文件、网络连接或锁),需要支持 with 语句,那么你就需要单独实现 __enter__() 方法和 __exit__() 方法。

  • 相关阅读:
    uva10129 PlayOnWords(并查集,欧拉回路)
    UVA439 knightMoves (A*启发搜索)
    uva297 Quadtrees (线段树思想,区间操作)
    [uva]AncientMessages象形文字识别 (dfs求连通块)
    [uva816]AbbottsRevenge Abbott的复仇(经典迷宫BFS)
    [dp][uestc]L
    [dp][uestc oj]J
    [uestc oj]H
    [dp uestc oj] G
    [dp]uestc oj 邱老师看电影
  • 原文地址:https://www.cnblogs.com/feifeifeisir/p/11475732.html
Copyright © 2011-2022 走看看