0

我有一个名为 User 的类:

class User(object):

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

用户有一个属性traits是字典。它旨在成为一个包罗万象的信息,当我需要保存关于用户的更多信息时,除了电子邮件地址、用户 ID 等基本信息之外,我可以填充它。

Traits创建一个类并在其中设置属性会或多或少有效__init__setattr?查找会更好吗?这台机器有什么可以给我买的吗?还是说它最终只会做更多的工作?

4

2 回答 2

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 的额外 1 行代码。它更安全,因为你永远不知道有人做了什么Traits来提供各种描述符(例如属性)等 setattr,将正确地做所有这些事情,而盲目地写入__dict__可能是有害的。

于 2013-01-24T15:24:43.377 回答
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
于 2013-01-24T15:30:37.193 回答