VB(实际上是C99和C#)有一种方法可以使用缩小语法在一个对象上设置多个属性,您不必在“。”之前重复对象名称。 。有没有办法在Python中执行此操作而不必遍历字典,在每个项目上调用setattr
?
像
这样的东西obj.update_attr(
'attr1': 'foo',
'attr2': 'bar'
)
答案 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()
...