What is a “runtime context”?
(为了更清晰地编辑)
我在读Python书(Beazley的Python基本参考),他说:
The
with statement allows a series of statements to execute inside a
runtime context that is controlled by an object that serves as a context manager.Here is an example:
1
2
3
4
5
6 with open("debuglog","a") as f:
f.write("Debugging
")
statements
f.write("Done
")
他接着说:
The with obj statement accepts an optional as var specifier. If given, the value
returned by obj._ enter _() is placed into var. It is important to emphasize
that obj is not necessarily the value assigned to var.
我理解"with"关键字的作用机制:文件对象通过open返回,并且该对象可以通过块体中的f访问。我还了解将调用enter()和exit()。
但是什么是运行时上下文呢?一些低层次的细节会很好——或者,在C.的一个例子,有人能弄清什么是"语境",以及它可能如何与其他语言(C,C++)相关。我对上下文的理解是环境,例如:bash shell在所有(env显示的)shell变量的上下文中执行ls。with the with关键字-yes f对块体是可访问的,但这不只是作用域吗?例如:对于y中的x:这里x在块内没有作用域,并且在块外保留它的值-这是Beazley在谈到"运行时上下文"时的意思吗?f只在块内作用域,并在with块外失去所有的意义?他为什么说语句"在运行时上下文中执行"????这像是一个"逃避"??
我知道
简单地说,"上下文管理器"是一个具有特殊方法函数
http://www.python.org/dev/peps/pep-0343/好的。
http://docs.python.org/2/reference/datamodel.html?highlight=context%20管理器带语句上下文管理器好的。
1 2 | with open(file_name) as f: # do something with file |
你知道文件会在你完成后正确关闭。好的。
另一个很好的例子是资源锁:好的。
1 2 | with acquire_lock(my_lock): # do something |
你知道在你拿到锁之前代码不会运行,一旦代码完成,锁就会被释放。我不经常在python中进行多线程编码,但是当我这样做时,这个语句确保锁总是被释放,即使在遇到异常时也是如此。好的。
另外,我在谷歌网上搜索了一个上下文管理器的例子,我发现了一个很漂亮的例子:一个在特定目录中执行python块的上下文管理器。好的。
http://ralsina.me/weblog/posts/bb963.html网站好的。
编辑:好的。
运行时上下文是由对
Python内部没有任何秘密魔法。解析器中没有特殊的作用域,没有内部堆栈,也没有特殊的内容。您只需编写两个方法函数:
再看一下政治公众人物的这一部分:好的。
记住,PEP310大致提出了这种语法("var="部分是可选的):好的。
1 2 | with VAR = EXPR: BLOCK |
大致翻译为:好的。
1 2 3 4 5 6 | VAR = EXPR VAR.__enter__() try: BLOCK finally: VAR.__exit__() |
在这两个示例中,
更具体的好处是它是"句法糖"。我更愿意写一个两行的
更抽象的好处是,这给了我们一种新的方式来思考设计我们的程序。Raymond Hettinger在Pycon 2013的一次演讲中这样说:当我们编写程序时,我们会寻找可以分解为函数的公共部分。如果我们有这样的代码:好的。
1 2 3 4 5 6 7 8 9 10 11 | A B C D E F B C D G |
我们可以很容易地创建一个函数:好的。
1 2 3 4 5 6 7 8 9 10 11 12 | def BCD(): B C D A BCD() E F BCD() G |
但我们从未有过一个真正干净的方法来进行设置/拆卸。当我们有很多这样的代码时:好的。
1 2 3 4 5 6 7 8 9 10 11 | A BCD() E A XYZ() E A PDQ() E |
现在我们可以定义一个上下文管理器并重写上面的内容:好的。
1 2 3 4 5 6 7 8 | with contextA: BCD() with contextA: XYZ() with contextA: PDQ() |
所以现在我们可以考虑我们的程序,寻找可以抽象为"上下文管理器"的设置/拆卸。RaymondHettinger展示了他发明的几个新的"上下文管理器"食谱(我绞尽脑汁想给你记住一两个例子)。好的。
编辑:好的,我刚记起一个。RaymondHettinger展示了一个配方,该配方将内置于Python3.4中,用于使用
另外,我尽了最大努力让他明白他在说什么……如果我犯了任何错误或错报了什么,那都是我的错,而不是他。(他有时会在stackoverflow上发帖,这样他就可以看到这个消息,如果我弄错了,他可以纠正我。)好的。
编辑:您已用更多文本更新了问题。我也会具体回答。好的。
这就是Beazley在谈到"运行时上下文"时的意思吗?F只在块内作用域,并在WITH块外失去所有意义?他为什么说语句"在运行时上下文中执行"????这像是一个"逃避"??好的。
实际上,
"运行时上下文"是一个非正式的概念,它的意思是"由
我知道open返回的对象是"not…分配给var"??为什么不分配给VaR?比兹利这样说是什么意思?好的。
好吧,假设我们有一个物体,我们称它为
1 2 | with k as x: # do something |
大卫比兹利想让你知道的是,江户十一〔10〕不一定要和江户十一〔6〕绑定。
1 2 | with open(some_file) as f: # do something |
对
我认为大多数上下文管理器都会返回到self。因为它是一个对象,它可以有任意数量的成员变量,所以它可以方便地返回任意数量的值。但这不是必需的。好的。
例如,可能有一个上下文管理器启动在
1 2 3 4 | with start_daemon("parrot") as pid: print("Parrot daemon running as PID {}".format(pid)) daemon = lookup_daemon_by_pid(pid) daemon.send_message("test") |
但您也可以返回上下文管理器对象本身,其中包含您需要的任何值:好的。
1 2 3 | with start_daemon("parrot") as daemon: print("Parrot daemon running as PID {}".format(daemon.pid)) daemon.send_message("test") |
如果我们需要守护进程的PID,我们可以将它放在对象的
WITH上下文会注意到,在输入时调用
在大多数情况下,这是以前处理过的对象—在文件情况下,它是—但例如,在数据库上,不是连接对象,而是返回一个光标对象。
文件示例可以这样扩展:
1 2 3 | f1 = open("debuglog","a") with f1 as f2: print f1 is f2 |
它将打印
数据库的工作方式
1 2 3 4 | d = connect(...) with d as c: print d is c # False print d, c |
这里,
在文件示例中,无论是否有错误,都将关闭文件。
在数据库示例中,事务通常在成功时提交,在失败时回滚。
上下文管理器可以方便地初始化和清理文件、数据库等内容。
我没有意识到C或C++中的直接对应关系。
C不知道例外的概念,所以没有例外可以在