从字典创建类实例属性?

100 投票
12 回答
113160 浏览
提问于 2025-04-15 15:27

我正在从一个CSV文件导入数据,得到的数据大致是这样的格式:

{ 'Field1' : 3000, 'Field2' : 6000, 'RandomField' : 5000 }

字段的名称是动态的。也就是说,可能会有比Field1Field2更多的字段,但我知道Field1Field2总是会存在。

我希望能把这个字典传入我的类allMyFields,这样我就可以像访问属性一样访问上面的数据。

class allMyFields:
    # I think I need to include these to allow hinting in Komodo. I think.
    self.Field1 = None
    self.Field2 = None

    def __init__(self,dictionary):
        for k,v in dictionary.items():
            self.k = v
            #of course, this doesn't work. I've ended up doing this instead
            #self.data[k] = v
            #but it's not the way I want to access the data.

q = { 'Field1' : 3000, 'Field2' : 6000, 'RandomField' : 5000 }
instance = allMyFields(q)
# Ideally I could do this.
print q.Field1

有什么建议吗?我想这样做的原因是我想利用代码提示,而像我现在这样把数据导入到一个叫data的字典中并不能让我享受到这个功能。

(因为变量名在运行时才会被解析,所以我还是得给Komodo一些提示,我觉得self.Field1 = None应该就足够了。)

那么,我该怎么做才能实现我的想法呢?还是说我在追求一个设计不好的、与Python不太相符的方案?

12 个回答

20

你也可以用 dict.update 来代替手动一个一个遍历 items(如果你真的要遍历的话,使用 iteritems 会更好)。

class allMyFields(object):
    # note: you cannot (and don't have to) use self here
    Field1 = None
    Field2 = None

    def __init__(self, dictionary):
        self.__dict__.update(dictionary)

q = { 'Field1' : 3000, 'Field2' : 6000, 'RandomField' : 5000 }
instance = allMyFields(q)

print instance.Field1      # => 3000
print instance.Field2      # => 6000
print instance.RandomField # => 5000
43
>>> q = { 'Field1' : 3000, 'Field2' : 6000, 'RandomField' : 5000 }
>>> q = type('allMyFields', (object,), q)
>>> q.Field1
3000

关于 type 的文档解释得很清楚,这里讲的是它的用法(可以当作构造函数来用)。

补充说明: 如果你需要实例变量,下面的代码也可以用:

>>> a = q()             # first instance
>>> a.Field1
3000
>>> a.Field1 = 1
>>> a.Field1
1
>>> q().Field1           # second instance
3000
151

你可以使用setattr这个函数(不过要小心:不是每个字符串都能作为有效的属性名!):

>>> class AllMyFields:
...     def __init__(self, dictionary):
...         for k, v in dictionary.items():
...             setattr(self, k, v)
... 
>>> o = AllMyFields({'a': 1, 'b': 2})
>>> o.a
1

补充说明:让我来解释一下上面的代码和SilentGhost的回答之间的区别。上面的代码片段创建了一个类,这个类的实例属性是基于给定的字典。而SilentGhost的代码则创建了一个类,这个类的类属性是基于给定的字典。

根据你的具体情况,这两种解决方案可能各有适用之处。你是打算创建一个类的实例,还是多个实例?如果答案是一个,那你可以完全跳过对象的创建,直接构造类型(这样就可以选择SilentGhost的回答)。

撰写回答