Python 相当于 VB“with”块

Rei*_*ien 0 python

VB(实际上还有 C99 和 C#)有一种方法可以使用简化的语法在一个对象上设置多个属性,您不必在“.”之前重复对象名称。。有没有一种方法可以在 Python 中执行此操作,而无需循环遍历字典,调用setattr每个项目?

就像是

obj.update_attr(
   'attr1': 'foo',
   'attr2': 'bar'
)
Run Code Online (Sandbox Code Playgroud)

aba*_*ert 5

首先,请记住,您实际上并没有节省太多空间\xe2\x80\x94,并且您可以通过临时将对象绑定到更短的名称来节省更多空间,并使您的风格更加Pythonic:

\n\n
_ = obj\n_.attr1 = \'foo\'\n_.attr2 = \'bar\'\n
Run Code Online (Sandbox Code Playgroud)\n\n

将其与 VB 风格的语法进行比较:

\n\n
vbwith obj:\n    .attr1 = \'foo\'\n    .attr2 = \'bar\'\n
Run Code Online (Sandbox Code Playgroud)\n\n

您实际上每行只需键入和读取一个额外字符。这样的负担是否太大了?

\n\n

这在具有值复制语义的 C 风格变量的语言中不起作用,因为您只是在obj. 但在 Python 中,为指定的值创建另一个名称a = b,它不会复制任何内容。(如果您有 C 背景,将其视为后面跟着一串以 开头的行可能会有所帮助。)ab_ = &obj_->

\n\n
\n\n

如果你真的想这样做,最安全的方法是编写update_attr一个循环setattr

\n\n
def update_attrs(obj, **attrs):\n    for attr, value in attrs.items():\n        setattr(obj, attr, value)\n\nupdate_attr(obj,\n    attr1=\'foo\',\n    attr2=\'bar\'\n)\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n

setattr您想要使用而不是修改对象的原因__dict__vars()并非所有属性都存储在对象的__dict__. 它们可能存储在__slots__, 或@property类的描述符中,或 C 扩展对象上的 get-set 方法,或元类提供的一些自定义内容中。因此,修改__dict__在某些情况下可能会失败,或者可能看起来有效但什么也不做,或者最糟糕的是,以一种很难分辨的方式做了错误的事情(比如隐藏属性而不是设置它) 。setattr只要直接访问可以工作,就保证可以工作;只要直接访问失败,就可以保证失败。

\n\n
\n\n

虽然 Python 社区的许多人认为实际的 VB 风格with语法是一件坏事(尽管我找不到 Guido 的博客文章的链接),但您更明确的语法似乎是可读的,并且一点也不误导我,所以如果你真的想使用这个功能,那就继续吧。但话又说回来,我认为没有太大必要。

\n

  • 我认为在这里使用“_”的唯一反对意见是,在控制台上运行时代码的行为会有所不同,其中“_”被分配了最后一个命令的结果。 (2认同)