首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python组合setattr和getattr

Python组合setattr和getattr
EN

Stack Overflow用户
提问于 2013-03-08 19:32:30
回答 2查看 4.2K关注 0票数 1

我想动态更新类的属性,但似乎setattr和getattr的组合并不能像我想使用的那样工作。

下面是我的主类:

代码语言:javascript
复制
class Container(object):
    def __init__(self):
        pass
container = Container()
attributes = ['a', 'b', 'c', 'd']
values = [[1, 2, 3, 4, 5], [True, False], ['red', 'blue', 'green'], [0, 1, -1, -5, 99]]

请注意,出于该示例的目的,我显式地构造了属性及其各自的值的列表。但是,在这段代码的实际应用中,我事先并不知道任何事情。无论是它们的编号、名称还是值。这就需要动态地做这件事。

下面是代码的其余部分:

代码语言:javascript
复制
for key, value in zip(attributes, values):
    setattr(container, key, [])
    for val in value:
        setattr(container, key, getattr(container, key).append(val))

当我运行代码时,这部分不起作用。我可以将getattr部分保存在一个tmp变量中,然后在调用setattr之前调用列表的append方法,但如果可能的话,我想压缩它。

有人能给我解释一下为什么这个不起作用吗?我还能有什么选择?

谢谢你的帮忙

EN

回答 2

Stack Overflow用户

发布于 2013-03-08 19:37:26

您正在追加到就地列表。与所有就地变异函数一样,.append()返回None,因此您的最后一行:

代码语言:javascript
复制
setattr(container, key, getattr(container, key).append(val))

最终计算结果为:

代码语言:javascript
复制
setattr(container, key, None)

只需在类上设置一个列表的副本:

代码语言:javascript
复制
for key, value in zip(attributes, values):
    setattr(container, key, values[:])

其中,[:]通过以简写表示法从0切片到values来创建len(values)的副本,而不需要循环。

如果您想要做的就是创建一个提供键和值作为属性的对象(很像dict使用属性访问而不是项访问),您还可以使用:

代码语言:javascript
复制
class Container(object):
    def __init__(self, names, values):
        self.__dict__.update(zip(names, values))

然后运行:

代码语言:javascript
复制
Container(attributes, values)

这消除了在循环中调用setattr()的需要。

票数 3
EN

Stack Overflow用户

发布于 2013-03-08 19:51:48

如果你能观察每一步的进度,它可能会帮助你理解正在发生的事情:

代码语言:javascript
复制
class Container(object):
    def __init__(self):
        pass
    def __str__(self):
        return '%s(%s)' % (self.__class__.__name__,
            ', '.join(['%s = %s' % (attr, getattr(self, attr))
                for attr in self.__dict__]))

现在你可以使用print container了。如果您在嵌套循环中执行此操作,您将看到在第一次尝试setattr之后,您已经破坏了存储在container.a中的原始列表(正如Martijn所指出的):

代码语言:javascript
复制
for key, value in zip(attributes, values):
    setattr(container, key, [])
    for val in value:
        print 'before:', container
        setattr(container, key, getattr(container, key).append(val))
        print 'after:', container

before: Container(a = [])
after: Container(a = None)
before: Container(a = None)
Traceback (most recent call last): ...

做到这一点的“最佳”方法显然取决于真正的问题--考虑到缩小的问题,Martijn的版本是非常合适的,但也许你必须在创建一些初始container实例之后的某个时刻附加一个项目,或者扩展多个项目。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15293006

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档