Python3 使用**kwargs设置属性时出现AttributeError

3 投票
3 回答
977 浏览
提问于 2025-04-19 17:56

简单来说,我不明白为什么我不能用一个 for 循环和 **kwargs 来设置一个属性,像这样:

class Person():
    def __init__(self, onevar, *args, **kwargs):
        self.onevar = onevar
        for k in kwargs:
            self.k = kwargs[k]
            print(k, self.k)   

def run():
    ryan = Person('test', 4, 5, 6, name='ryan', age='fifty')
    print(ryan.name)

def main():
    run()

if __name__=="__main__":
    main()

这段代码返回了以下内容:

AttributeError: 'Person' object has no attribute 'name'

有人知道为什么吗?

3 个回答

0

这一行代码:

            self.k = kwargs[k]

... 是在每次循环中设置 self.k,也就是 self 这个对象里名为 k 的属性,而不是你想象中的 self.value_of_k

如果你把这一行改成:

            setattr(self, k, kwargs[k])

你应该能得到你想要的结果。

0

编辑: @tzaman 的回答更好。按照他的建议使用 setattr

你可能希望 k 变成一个变量,但实际上并不是这样。不过,你可以在 Python 中扩展基本的 object,并通过内部的 __dict__ 属性来设置你的变量。

你还可以使用 iteritems() 来直接获取值。

class Person(object):
    def __init__(self, onevar, *args, **kwargs):
        self.onevar = onevar
        for k,v in kwargs.iteritems():
            self.__dict__[k] = v
            print(k, self.__dict__.get(k))
5

当你给 self.k 赋值时,其实并不是在创建一个叫做 k 的属性,而是一直在创建一个名为 k 的属性。如果我理解你想做的事情,你需要把

self.k = kwargs[k]

替换成

setattr(self, k, kwargs[k])

这样才能实现你想要的效果。

撰写回答