【问题标题】:Assigning to a member with `as` in context-manager (with) and exception handler在上下文管理器(with)和异常处理程序中使用“as”分配给成员
【发布时间】:2019-11-30 05:11:34
【问题描述】:

首先,如果我没有使用正确的名称,我想道歉,我是 Python 新手。

在玩的过程中,我发现您可以在 with 语句的 as 部分分配给班级成员:

from contextlib import contextmanager

@contextmanager
def func(val):
    yield val*2

class Foo:
    def __init__(self):
        self.val = "Placeholder"

    def bar(self):
        with func(333) as self.val:
            print("Got", self.val)


if __name__ == "__main__":
    f = Foo()
    print("Before:", f.val)
    f.bar()
    print("After:", f.val)

输出:

之前:占位符
得到 666
之后:666

但是,分配给 except 中的成员会给我一个语法错误:

class Foo:
    def __init__(self):
        self.err = None

    def bar(self):
        try:
            os.remove(path)
        except FileNotFoundError as self.err:
            print("Couldn't remove", path)

输出:

except FileNotFoundError as self.err:                                      
                                ^

SyntaxError: 无效语法

由于搜索as 是徒劳的,我无法找到任何关于此的参考,我的问题是:

  1. with 语句的as 部分中分配给成员的定义是否明确?
  2. 如果是,为什么在异常处理中不允许?

编辑:我想关于import的类似问题可以问...

【问题讨论】:

  • 我不知道答案是什么,但这是一个非常有趣的问题!
  • 请注意,as 不是单独的运算符,而是相应语句的一部分。它在import ... as ...except ... as ...with ... as ... 中的含义不同。
  • @MisterMiyagi,我明白了,虽然语义相似。 (另外,打蜡,打蜡)。

标签: python exception with-statement


【解决方案1】:

except clause 中,as 只能分配给一个标识符。在with clause 中,as 可以分配给任意目标。

try1_stmt ::=  "try" ":" suite
           ("except" [expression ["as" identifier]] ":" suite)+
           ["else" ":" suite]
           ["finally" ":" suite]

with_item ::=  expression ["as" target]

target 是标识符 (foo)、属性 (foo.bar)、切片 (foo[:bar])、订阅 (foo[bar])、上述列表/元组 (@987654333 @) 或上述内容的拼凑 (*foo)。


异常在其异常处理程序之后自动清除。在处理程序之后使用名称表明它已被删除:

>>> a = 1
>>> try:
...     1/0
... except ZeroDivisionError as a:
...     pass
... print(a)
NameError: name 'a' is not defined

这避免了异常、引发异常的帧和绑定异常的名称之间不必要的引用循环。

直接绑定到另一个命名空间需要选择以下两种情况之一:

  • 处理程序后删除该属性。这意味着对象的外观不一致。
  • 处理程序后不删除该属性。这意味着除非手动清除,否则框架将无限期存在。

这两种变体都需要在处理程序之外显式处理异常。此外,它们很容易意外触发需要在其他地方进行显式处理的情况。

【讨论】:

  • 谢谢,这是否意味着我可以在with 语句中使用对成员的赋值,而这不仅仅是我正在使用的 Python 版本的怪癖?
  • @Motti 我已经添加了相应的语法定义。是的,您可以依靠使用with ... as ... 进行属性分配。
猜你喜欢
  • 2016-05-30
  • 2020-06-07
  • 2013-10-25
  • 2015-03-25
  • 1970-01-01
  • 1970-01-01
  • 2021-10-15
  • 2014-09-01
  • 1970-01-01
相关资源
最近更新 更多