【问题标题】:obj.count = 8 or setattr(obj, 'count', 8)obj.count = 8 或 setattr(obj, 'count', 8)
【发布时间】:2013-11-11 15:34:35
【问题描述】:
在 python 中。使用setattr(object, 'var', value 和object.var = value 方法有什么区别。他们似乎都在做同样的事情
class Something(object):
pass
x = Something()
setattr(x, 'count', 2) #sets count to be 2
x.count = 3 #sets count to be 3
【问题讨论】:
标签:
python
oop
methods
var
【解决方案1】:
他们确实做同样的事情,但是你不能使用属性设置语法的变量,而你可以使用setattr()来做到这一点。
换句话说,这是可行的:
foo = 'count'
setattr(x, foo, 2)
但这不是:
foo = 'count'
x.foo = 2
使用setattr() 进行动态 属性设置,其中属性的名称取自变量。将object.attributename = value 用于静态 属性,您事先知道名称。
此外,属性访问语法仅限于正确的 Python 标识符,而 setattr() 可以使用 any 字符串。这意味着您可以使用:
setattr(x, '3 little piggies', 42)
尝试使用静态属性将不起作用,因为 Python 标识符不允许空格,并且不能以数字开头。
【解决方案2】:
正如其他人所提到的,它们本质上是相同的。但是,setattr(obj, 'attr', value) 更通用,因为它允许您做您无法通过句法构造 obj.attr = value 做的事情:
>>> class A(object):
... pass
>>> a = A()
>>> setattr(a, 'foo bar', 5) # space in the attribute name???
>>> print getattr(a, 'foo bar')
5
>>> a.'foo bar' = 7
File "<stdin>", line 1
a.'foo bar' = 7
^
SyntaxError: 无效语法
你是否应该利用 Python 的这个“特性”(提示:你可能不应该)是另一个问题。
【解决方案3】:
直接访问x.count 会产生更高效的代码,我怀疑这是因为可以在解析/字节编译时解析属性访问。这在循环中可能会特别明显。
给定
def f(): setattr(x, 'count', 2)
def g(): x.count = 3
这是dis 在 Python 2.7 上所说的:
>>> dis.dis(f)
1 0 LOAD_GLOBAL 0 (setattr)
3 LOAD_GLOBAL 1 (x)
6 LOAD_CONST 1 ('count')
9 LOAD_CONST 2 (2)
12 CALL_FUNCTION 3
15 POP_TOP
16 LOAD_CONST 0 (None)
19 RETURN_VALUE
>>> dis.dis(g)
1 0 LOAD_CONST 1 (3)
3 LOAD_GLOBAL 0 (x)
6 STORE_ATTR 1 (count)
9 LOAD_CONST 0 (None)
12 RETURN_VALUE
所以g 产生的字节码更少,而且我怀疑它也更快。