zoukankan      html  css  js  c++  java
  • 【原创翻译】理解python的with语句

    【原创翻译,转载请注明译者及原文链接】

    原文链接:

    http://effbot.org/zone/python-with-statement.htm

    从comp.lang.python和其他论坛来看,即使对于有经验的python程序员,Python 2.5的新with语句也让人有一些迷惑。

    但实质上,一旦你理解了它所想要解决的问题,相较于python的其他内容,with表达式其实是相当简单的。看下面的代码:

        set things up
        try:
            do something
        finally:
            tear things down

    在这里,“set things up”可以是打开一个文件,或者取得一些外部资源,而“tear things down”则将是关闭文件,或者释放,移除资源。try-finally的结构保证了“tear things down”这部分总会被执行,即使函数主体的代码不能正常结束。

    如果你需要经常干这件事,那么把“set things up”和“tear things down”的代码放到一个库函数中并让其可以重复使用将会带来许多方便。当然你可以像这么干:

        def controlled_execution(callback):
            set things up
            try:
                callback(thing)
            finally:
                tear things down
    
        def my_function(thing):
            do something
    
        controlled_execution(my_function)

    但这样有些罗嗦,尤其是当需要修改本地变量的时候。另外一种方法是使用仅一次的generator,并且使用for-in语句来“包装”代码:

        def controlled_execution():
            set things up
            try:
                yield thing
            finally:
                tear things down
    
        for thing in controlled_execution():
            do something with thing

    但是yield在2.4及更早先的版本中甚至不允许被放到try-finally中。尽管这在2.5中被修正了,但这仍然显得有些古怪——你知道你仅仅想要执行某段语句一次,但你却使用了循环。

    所以在尝试了很多方法之后,GvR和其python开发团队最终对后者进行了一个概括,使用对象而不是generator来控制外部代码的行为:

        class controlled_execution:
            def __enter__(self):
                set things up
                return thing
            def __exit__(self, type, value, traceback):
                tear things down
    
        with controlled_execution() as thing:
             some code

    现在,当“with”语句被执行时,Python会首先计算类实例化的表达式(controlled_execution()),并基于表达式的值调用__enter__方法(这也被称为“上下文保护”,"context guard"),并且把__enter__函数的返回值赋给as后面的变量。Python随后会执行代码主体,不管主体代码发生了什么,保护(guard)对象的__exit__方法都会被调用。

    作为额外的奖励,__exit__方法还可以监测异常,并且根据需要阻止异常或者对异常进行处理。要阻止异常,返回一个为true的值就可以。例如,如下的__exit_方法不会放过任何TypeError,但会让其他异常通过。

        def __exit__(self, type, value, traceback):
            return isinstance(value, TypeError)

    在Python2.5中,文件对象被包装了__enter____exit__方法;前者仅仅返回文件对象本身,后者则关闭文件:

        >>> f = open("x.txt")
        >>> f
        <open file 'x.txt', mode 'r' at 0x00AE82F0>
        >>> f.__enter__()
        <open file 'x.txt', mode 'r' at 0x00AE82F0>
        >>> f.read(1)
        'X'
        >>> f.__exit__(None, None, None)
        >>> f.read(1)
        Traceback (most recent call last):
          File "<stdin>", line 1, in <module>
        ValueError: I/O operation on closed file

    所以,打开一个文件,对其内容进行处理,并且确认关闭文件,你可以简单地这么干:

    with open("x.txt") as f:
        data = f.read()
        do something with data

    这并不是很难,不是吗?

    转载请注明译者及原文链接:)

  • 相关阅读:
    课程作业3
    课程作业一(改进)
    C语言中的几种常见排序算法
    PADS 导Gerber文件
    时钟信号线上串一小电阻的作用
    Allegro pcb -等长设计
    Allegro PCB -内层分割,比如电源层需要分割几种电源
    Allegro PCB -通孔焊盘制作 及Flash制作
    Allegro PCB -如何做自定义焊盘
    MFC中的NMHDR结构体和NMUPDOWN结构体
  • 原文地址:https://www.cnblogs.com/andy071001/p/2990194.html
Copyright © 2011-2022 走看看