Class 从字典创建类实例属性?

Class 从字典创建类实例属性?,class,python,komodo,Class,Python,Komodo,我正在从CSV导入数据,并以大致相同的格式获取数据 { 'Field1' : 3000, 'Field2' : 6000, 'RandomField' : 5000 } 字段的名称是动态的。(好吧,它们是动态的,因为可能不止有Field1和Field2,但我知道Field1和Field2总是会存在 我希望能够将这本词典传入我的类allMyFields,这样我就可以作为属性访问上述数据 class allMyFields: # I think I need to include thes

我正在从CSV导入数据,并以大致相同的格式获取数据

{ 'Field1' : 3000, 'Field2' : 6000, 'RandomField' : 5000 }
字段的名称是动态的。(好吧,它们是动态的,因为可能不止有Field1和Field2,但我知道
Field1
Field2
总是会存在

我希望能够将这本词典传入我的类
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树吗?

您可以使用(但要小心:不是每个字符串都是有效的属性名!):

编辑:让我解释一下上述代码与的区别。上面的代码片段创建了一个类,其实例属性基于给定的字典。SilentGhost的代码创建了一个类,其类属性基于给定的字典

根据您的具体情况,这两种解决方案中的任何一种都可能更合适。您希望创建一个或多个类实例吗?如果答案是一个,您最好完全跳过对象创建,只构造类型(因此使用SilentGhost的答案)

文档很好地解释了这里发生了什么(请参阅用作构造函数)

编辑:如果需要实例变量,以下操作也可以:

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

您还可以使用
dict.update
而不是手动循环
(如果您正在循环,
iteritems
更好)


使用setattr实现漂亮的方式。quick-n-dirty方式是更新实例内部字典:

>>> class A(object):
...    pass
...
>>> a = A()
>>> a.__dict__.update({"foo": 1, "bar": 2})
>>> a.foo
1
>>> a.bar
2
>>>
使用命名元组(Python 2.6):


您可以创建一个子类
dict
,该子类允许键的属性查找:

class AttributeDict(dict):
    def __getattr__(self, name):
        return self[name]

q = AttributeDict({ 'Field1' : 3000, 'Field2' : 6000, 'RandomField' : 5000 })
print q.Field1              
print q.Field2              
print q.RandomField
如果您试图查找
dict
已经具有的属性(例如
keys
get
),您将获得该
dict
类属性(一种方法)。如果您请求的密钥在
dict
类中不存在,则将调用
\uuu getattr\uuuu
方法并执行密钥查找。

或者您可以尝试此操作

class SomeClass:
    def __init__(self,
                 property1,
                 property2):
       self.property1 = property1
       self.property2 = property2


property_dict = {'property1': 'value1',
                 'property2': 'value2'}
sc = SomeClass(**property_dict)
print(sc.__dict__)
class AllMyFields:
    def __init__(self, field1, field2, random_field):
        self.field1 = field1
        self.field2 = field2
        self.random_field = random_field

    @classmethod
    def get_instance(cls, d: dict):
        return cls(**d)


a = AllMyFields.get_instance({'field1': 3000, 'field2': 6000, 'random_field': 5000})
print(a.field1)
增强的

重复dict工作

类属性指令(dict):
"""https://stackoverflow.com/a/1639632/6494418"""
def _ugetattr _;(self,name):
如果不存在,则返回self[name](self[name],dict)\
else属性指令(self[名称])
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
d={“你好”:1,“世界”:2,“猫”:{“狗”:5}
d=属性指令(d)
打印(d.cat)
打印(d.猫狗)
打印(d.cat.items())
"""
{'dog':5}
5.
口述项目([('dog',5)])
"""

< /代码> 如果你想添加一个新的库,PyDyTic是一个非常有效的解决方案。它使用Python注释来构造对象和验证类型,考虑下面的代码:

from pydantic import BaseModel

class Person(BaseModel):
    name: str
    age: str


data = {"name": "ahmed", "age": 36}

p = Person(**data)

pydantic:

+1,但我认为你应该解释一下这段代码的作用,或者提供文档的链接。我猜他的名字是“SilentGhost”方法很简洁,但它们是类变量这一事实没有实例变量那么引人注目。如果需要,您可以实例化
q
。Komodo编辑提示不需要类属性。它可以读取
\uuuu init\uuuu
方法体来查找
self.
变量。更根本的是,您为什么不使用简单的de>csv.DictReader
用于此操作并从每行创建字典?SLott-I使用re.sub()手动修改标题并添加一个“假”标题。这不是一个很好的理由,但在DictReader之后重命名密钥要昂贵得多。带有额外编辑的代码解释了两个好答案之间的差异,非常有用,谢谢!我惊喜地发现此解决方案与form_dict=flask.form.to_dict()一起使用从一个长web表单创建一个db.Model实例。太棒了!注意-表单中输入的整数和浮点数以字符串的形式返回,但在类使用之前很容易修复。如果键中有空格,是否有简单的修复方法?例如:
instance。由于空格的原因,其他一些东西
无法工作。我想知道是否有一个优雅的解决方法。@Jarad使用
map(lambda-kv:[kv[0])替换(''''.''.'),kv[1]),dictionary.items())
,而不仅仅是
dictionary
。这将用下划线替换所有键名中的所有空格。
class AttributeDict(dict):
    def __getattr__(self, name):
        return self[name]

q = AttributeDict({ 'Field1' : 3000, 'Field2' : 6000, 'RandomField' : 5000 })
print q.Field1              
print q.Field2              
print q.RandomField
class SomeClass:
    def __init__(self,
                 property1,
                 property2):
       self.property1 = property1
       self.property2 = property2


property_dict = {'property1': 'value1',
                 'property2': 'value2'}
sc = SomeClass(**property_dict)
print(sc.__dict__)
class AllMyFields:
    def __init__(self, field1, field2, random_field):
        self.field1 = field1
        self.field2 = field2
        self.random_field = random_field

    @classmethod
    def get_instance(cls, d: dict):
        return cls(**d)


a = AllMyFields.get_instance({'field1': 3000, 'field2': 6000, 'random_field': 5000})
print(a.field1)
from pydantic import BaseModel

class Person(BaseModel):
    name: str
    age: str


data = {"name": "ahmed", "age": 36}

p = Person(**data)