Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/325.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
试图通过语句和上下文管理器理解python_Python_Contextmanager - Fatal编程技术网

试图通过语句和上下文管理器理解python

试图通过语句和上下文管理器理解python,python,contextmanager,Python,Contextmanager,我不熟悉这一点,我只是想用语句来理解。我知道它应该替换try/块,但块除外 现在假设我这样做: 试试看: name='rubicon'/2#引发异常 例外情况除外,如e: 打印“不可能” 最后: 打印“好的,我抓到你了” 如何用上下文管理器替换它?与不会真正替换尝试/,除了,而是最终尝试。不过,您可以让上下文管理器在异常情况下执行与非异常情况下不同的操作: class Mgr(object): def __enter__(self): pass def __exit__(sel

我不熟悉这一点,我只是想用语句来理解
。我知道它应该替换
try
/
块,但
块除外

现在假设我这样做:

试试看:
name='rubicon'/2#引发异常
例外情况除外,如e:
打印“不可能”
最后:
打印“好的,我抓到你了”

如何用上下文管理器替换它?

不会真正替换
尝试
/
,除了
,而是最终尝试
。不过,您可以让上下文管理器在异常情况下执行与非异常情况下不同的操作:

class Mgr(object):
    def __enter__(self): pass
    def __exit__(self, ext, exv, trb):
        if ext is not None: print "no not possible"
        print "OK I caught you"
        return True

with Mgr():
    name='rubicon'/2 #to raise an exception

return True
部分是上下文管理器决定抑制异常的部分(就像您在
except
子句中不重新引发异常一样)。

Python中的
with
用于包装一组语句,您应该在其中设置、销毁或关闭资源。在这方面,它类似于
try…finally
,因为finally子句将在异常之后执行

上下文管理器是一个实现两种方法的对象:
\uuuuuuuuuuuuuuu进入
\uuuuuuuuuuu退出
。在
with
块之前和之后(分别)调用这些函数

例如,看看经典的
open()
示例:

with open('temp.txt', 'w') as f:
    f.write("Hi!")
Open返回一个
文件
对象,该对象实现了
\uuuuuuuuuuuuuuuuu
或多或少类似于
返回self
\uuuuuuuuuuuuuuu
类似于
self.close()

函数装饰器提供了一种提供上下文管理器的简便方法,无需编写自己的完整
上下文管理器
类(使用
\uuuuuuuuuuuuuuuuuuu
\uuuuuuuuuuuuuuu
方法,因此您不必记住
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu退出
方法的参数,或者
方法必须
返回True才能抑制异常)。相反,您可以在希望
with
块运行的点使用单个
yield
编写函数,并像通常一样捕获任何异常(实际上来自
yield

from contextlib import contextmanager
@contextmanager
def handler():
    # Put here what would ordinarily go in the `__enter__` method
    # In this case, there's nothing to do
    try:
        yield # You can return something if you want, that gets picked up in the 'as'
    except Exception as e:
        print "no not possible"
    finally:
        print "Ok I caught you"

with handler():
    name='rubicon'/2 #to raise an exception

为什么要额外麻烦编写上下文管理器?代码重复使用。您可以在多个位置使用相同的上下文管理器,而不必重复异常处理。如果异常处理是这种情况下特有的,那么就不用麻烦使用上下文管理器。但是如果相同的模式一次又一次出现(或者,如果可能对您的用户来说,例如关闭文件、解锁互斥锁),那么这是值得的。如果异常处理有点复杂,这也是一种整洁的模式,因为它将异常处理从代码流的主线中分离出来。

with
语句或上下文管理器可以帮助您使用资源(尽管可能用于更多用途)

假设您打开了一个要写入的文件:

f = open(path, "w")
您现在有一个打开的文件句柄。在处理您的文件期间,没有其他程序可以对其进行写入。为了让其他程序对其进行写入,您必须关闭文件句柄:

f.close()
with open(path, "w") as f:
    data = 3/0  # Tried dividing by zero. Raised ZeroDivisionError
    f.write(data)
# In here the file is already closed automatically, no matter what happened.
但是,在关闭文件之前,发生了一个错误:

f = open(path, "w")
data = 3/0  # Tried dividing by zero. Raised ZeroDivisionError
f.write(data)
f.close()
现在将要发生的是,函数或整个程序将退出,而您的文件将保留一个打开的句柄。(CPython在终止时清理句柄,句柄将与程序一起释放,但您不应该指望这一点)

with语句确保您一离开缩进,它就会关闭文件句柄:

f.close()
with open(path, "w") as f:
    data = 3/0  # Tried dividing by zero. Raised ZeroDivisionError
    f.write(data)
# In here the file is already closed automatically, no matter what happened.


with
语句可以用于更多的事情。例如:
threading.Lock()

几乎所有使用上下文管理器完成的事情都可以通过
尝试:…最后:…
完成,但是上下文管理器使用起来更方便、更舒适、更可读,并且通过实现
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu


通过在普通类中实现和来创建上下文管理器

\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

可以在中找到创建上下文管理器的快捷方式。它将生成器包装为上下文管理器。

上下文管理器的组件
  • 您应该实现一个返回对象的\uuu\uuu\uuu方法
  • 实施\uuuu退出\uuu方法
  • 例子 我将举一个简单的例子来说明为什么我们需要一个上下文管理器。在中国新疆的冬天,当你开门时,你应该立即关门。如果你忘记关门,你会感冒

     class Door:
         def __init__(self):
             self.doorstatus='the door was closed when you are not at home'
             print(self.doorstatus)
         def __enter__(self):
             print('I have opened the door')
             return self
         def __exit__(self,*args):
             print('pong!the door has closed')
         def fetchsomethings(self):
             print('I have fetched somethings')
    
    在家拿东西时,你应该打开门,拿东西,关上门

     with Door() as dr:
         dr.fetchsomethings()
    
    输出为:

    the door was closed when you are not at home
    I have opened the door
    I have fetched somethings
    pong!the door has closed
    
    解释 当您启动一个Door类时,它将调用将打印的\uuu init\uuu方法 “当您不在家时门已关闭”和\u enter\u\u方法,该方法将打印“我已打开门”,并在调用self.fetchsomethings时返回名为dr。当块完成时。上下文管理器将调用 方法,它将打印“砰!门已关闭”。当您不使用时
    关键字,\uuuuuuuuuuu进入和\uuuuu退出将不会被调用!!!!

    上下文管理器仅替换try/finally块。