Python相当于VB“with”块

时间:2014-07-23 20:21:36

标签: python

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

这样的东西
obj.update_attr(
   'attr1': 'foo',
   'attr2': 'bar'
)

4 个答案:

答案 0 :(得分:4)

首先,请记住,你真的没有节省太多空间 - 你可以节省更多的空间,并通过暂时将对象绑定到一个较短的名称来使你的风格更加Pythonic:

_ = obj
_.attr1 = 'foo'
_.attr2 = 'bar'

将其与VB-ish语法进行比较:

vbwith obj:
    .attr1 = 'foo'
    .attr2 = 'bar'

你真的只是每行输入一个额外的字符。这太重了吗?

这在具有值复制语义的C风格变量的语言中不起作用,因为您只需在obj的副本上设置属性。但是在Python中,a = b使a成为b命名的值的另一个名称,它不会复制任何内容。 (如果你来自C背景,可能有助于将其视为_ = &obj,然后是一堆以_->开头的行。)


如果你真的想这样做,最安全的方法是将update_attr写成setattr的循环:

def update_attrs(obj, **attrs):
    for attr, value in attrs.items():
        setattr(obj, attr, value)

update_attr(obj,
    attr1='foo',
    attr2='bar'
)

您希望使用setattr而不是修改对象的__dict__vars()的原因是并非所有属性都存储在对象的__dict__中。它们可以存储在类的__slots__@property描述符中,或者存储在C扩展对象上的get-set方法,或者由元类提供的某些自定义事物。因此,在某些情况下修改__dict__可能会失败,或者可能看起来无效,或者最糟糕的是,以一种很难说的方式做错事(比如隐藏属性而不是设置)它)。只要直接访问能够正常工作,setattr就可以正常工作,并且只要直接访问失败就会失败。


虽然很多Python社区认为实际的VB风格的with语法是一件坏事(虽然我找不到Guido关于它的博客文章的链接),但是你的更明确的语法似乎是可读的而不是所有误导我,所以如果你真的想使用这个功能,请继续。但同样,我不认为有太多需要。

答案 1 :(得分:2)

让我们写一个函数!

def update_attr(obj, **kw):
    for key, value in kw.iteritems():
        setattr(obj, key, value)

让我们使用这个功能!

class X:
    pass

x = X()

update_attr(x, blue=3, red=5)
update_attr(x, **{'yellow': 6})

print vars(x)

输出!

{'blue': 3, 'yellow': 6, 'red': 5}

答案 2 :(得分:1)

如果您的目标只是为了避免重复并且您正在使用自己的对象,则可以使用fluent interface这样的内容:

obj.set_attr1('foo')
   .set_attr2('bar')

答案 3 :(得分:0)

也许这是unpythonic但VB风格的With块可以帮助使程序结构更清晰。这在设置层次结构时非常有用,例如GUI布局。

“快速,肮脏,也许是单声道”的方法是:

for x in [my_object_with_a_long_name]:
    x.my_method()
    x.another_method()
    ...