Python 为什么要使用setattr()和getattr()内置函数?

Python 为什么要使用setattr()和getattr()内置函数?,python,python-3.x,Python,Python 3.x,通过阅读这些文件,我确切地了解了我所做的事情。但它也明确指出,getattr(x,'foobar')相当于x.foobar,setattr(x,'foobar',123)相当于x.foobar=123 那么我为什么要使用它们呢?因为您也可以使用动态变量: somevar = 'foo' getattr(x, somevar) 使用常规属性访问语法无法做到这一点 请注意,getattr()还采用可选的默认值,如果缺少该属性,则返回该值: 或者可以使用setattr()设置动态属性: for i,

通过阅读这些文件,我确切地了解了我所做的事情。但它也明确指出,
getattr(x,'foobar')
相当于
x.foobar
setattr(x,'foobar',123)
相当于
x.foobar=123


那么我为什么要使用它们呢?

因为您也可以使用动态变量:

somevar = 'foo'
getattr(x, somevar)
使用常规属性访问语法无法做到这一点

请注意,
getattr()
还采用可选的默认值,如果缺少该属性,则返回该值:

或者可以使用
setattr()
设置动态属性:

for i, value in enumerate(dynamic_values):
    setattr(i, 'attribute{}'.format(i), value)

如果要访问的属性是变量而不是文本字符串,则可以使用它们。它们允许您参数化属性访问/设置


没有理由执行
getattr(x,'foobar')
,但是您可能有一个名为
attr
的变量,可以将该变量设置为“foobar”或“otherAttr”,然后执行
getattr(x,attr)

如果您需要的属性的对象可能是
None
,我发现它非常有用。举例如下

obj = None
attr_val = getattr(obj, 'anyvar', None) #This is not an error.

另一个案例可能表明它们并不完全相同:

class A:
    def __init__(self):
        self.__var = 10
        setattr(self, '__var2', 100)

a = A()
print(a.__var2)
# 100
print(a.__var)
# AttributeError: 'A' object has no attribute '__var'

至少,
setattr

不同,如果您想不出使用它们的好理由,您可能没有理由:但是有一天,你发现自己在一个字符串变量中有一个属性名(例如,来自用户输入,或者通过处理来自服务器的一些JSON计算出来,或者其他任何东西),你想得到该变量中给定名称的属性,这时你就可以使用它了。很好的解释。但值得注意的是,如果你认为你想要这个,你通常不会;属性应该是字典中的一个值,而不是一个属性。@abarnert:不总是这样。有一些用例可以处理现有对象上的动态转换。或者查找可能丢失的属性。@MartijnPieters:是的,这就是为什么我说“经常”。如果它们从来都没有用过,那么它们就根本不会出现在语言中。一个很好的经验法则是:如果您通常希望静态地访问某些内容,但偶尔需要动态地访问,请使用带有偶尔
getattr
的属性;如果您通常希望动态地访问它,但偶尔静态地访问,请使用带有临时文字键的dict;其中4个是正面;其余的使用
getattr()
来处理可选属性,如果缺少,则返回默认值。@MartijnPieters:我的代码中的
\uu getattr\uuuu
实例实际上比
getattr
多……但是,是的,我也使用它。当我第一次想要
getattr
某个地方时,我停下来问自己这个东西是否真的应该是属性。有时答案是“是”(或者,有时是“不是,但此时意大利面太多,无法修复…”)。但这总是值得考虑的(除非是显而易见的情况——例如,您正在编写用于调试的反射代码)。
obj = None
attr_val = getattr(obj, 'anyvar', None) #This is not an error.
class A:
    def __init__(self):
        self.__var = 10
        setattr(self, '__var2', 100)

a = A()
print(a.__var2)
# 100
print(a.__var)
# AttributeError: 'A' object has no attribute '__var'