通过setattr向类添加字段与在Python中存储字典

时间:2013-01-24 15:22:50

标签: python

我有一个名为User的课程:

class User(object):

    def __init__(self, arg1, ..., traits = None):
        self.arg1 = arg1
        ...
        self.traits = traits

用户有一个属性traits,这是一个字典。当我需要保存关于除了电子邮件地址,用户ID等基本内容之外的用户的更多信息时,我可以填充这些内容。

创建Traits类并使用__init__设置setattr中的属性会更高效还是更低效?查找工作会更好吗?这台机器会给我带来什么东西,或者它最终只是更多的工作?

2 个答案:

答案 0 :(得分:2)

您可以直接修改实例__dict__(假设它没有实现__slots__或任何愚蠢的事情)

这是一个简单的例子:

class Traits(object):
    pass

class User(object):
    def __init__(self,**traits):
        self.traits = Traits()
        self.traits.__dict__.update(traits)

a = User(eye_color="blue")
print a.traits.eye_color

当然,只有这样做才有可能更安全(但效率稍差):

class User(object):
    def __init__(self,**traits):
        self.traits = Traits()
        for k,v in traits.items():
            setattr(traits,k,v)

实际上只有一行代码可以提供相同的API。它更安全,因为你永远不知道有人做了什么来混淆Traits以提供各种描述符(例如属性)等。setattr将正确地做所有这些事情,盲目地写__dict__可能是可能有害。

答案 1 :(得分:2)

对我来说很好,我很想重写:

class User(object):
    def __init__(self, arg1, arg2, **traits):
        self.arg1 = arg1
        self.arg2 = arg2
        self.traits = traits

如果您真的想要,那么如果找不到属性,您可以覆盖以回溯到特征字典:

def __getattr__(self, name):
    return self.traits[name]

示例:

>>> u = User(1, 2, email='something')
>>> y = User(1, 2, email='bob', telno='999')
>>> u.arg1, u.arg2, u.email
(1, 2, 'something')
>>> y.arg1, y.arg2, y.email, y.telno
(1, 2, 'bob', '999')
>>> y.arg1, y.arg2, y.email, y.something
Traceback (most recent call last):
  File "<pyshell#105>", line 1, in <module>
    y.arg1, y.arg2, y.email, y.something
  File "/home/jon/adfafasdf.py", line 7, in __getattr__
    return self.traits[name]
KeyError: 'something'

所以你可能希望把它变成一个更明智的错误,并改为:

def __getattr__(self, name):
    try:
        return self.traits[name]
    except KeyError as e:
        raise AttributeError() # with suitably formatted string