我正在从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
应该足够了。)
那么 - 我该怎么做我想要的?还是我咆哮着一棵设计不良的非蟒蛇树?
答案 0 :(得分:86)
您可以使用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's answer之间的区别。上面的代码片段创建了一个类,其中实例属性基于给定的字典。 SilentGhost的代码创建了一个类,其类属性基于给定的字典。
根据您的具体情况,这些解决方案中的任何一种都可能更合适。你明白要创建一个或多个类实例吗?如果答案是1,你也可以完全跳过对象创建并只构造类型(因此请使用SilentGhost的答案)。
答案 1 :(得分:30)
>>> 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
答案 2 :(得分:8)
您也可以使用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
答案 3 :(得分:4)
使用命名元组(Python 2.6):
>>> from collections import namedtuple
>>> the_dict = {'Field1': 3, 'Field2': 'b', 'foo': 4.9}
>>> fields = ' '.join(the_dict.keys())
>>> AllMyFields = namedtuple('AllMyFields', fields)
>>> instance = AllMyFields(**the_dict)
>>> print instance.Field1, instance.Field2, instance.foo
3 b 4.9
答案 4 :(得分:3)
您可以创建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
类中不存在您要求的密钥,则会调用__getattr__
方法并进行密钥查找。
答案 5 :(得分:2)
以漂亮的方式使用setattr。快速脏的方法是更新实例内部字典:
>>> class A(object):
... pass
...
>>> a = A()
>>> a.__dict__.update({"foo": 1, "bar": 2})
>>> a.foo
1
>>> a.bar
2
>>>
答案 6 :(得分:1)
如果您愿意添加新库,则pydantic是一个非常有效的解决方案。它使用python注释构造对象并验证类型。请考虑以下代码:
from pydantic import BaseModel
class Person(BaseModel):
name: str
age: str
data = {"name": "ahmed", "age": 36}
p = Person(**data)
pydantic:https://pydantic-docs.helpmanual.io/
答案 7 :(得分:0)
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__)
答案 8 :(得分:0)
或者您可以尝试
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)
答案 9 :(得分:0)
重复字典有效!
class AttributeDict(dict):
"""https://stackoverflow.com/a/1639632/6494418"""
def __getattr__(self, name):
return self[name] if not isinstance(self[name], dict) \
else AttributeDict(self[name])
if __name__ == '__main__':
d = {"hello": 1, "world": 2, "cat": {"dog": 5}}
d = AttributeDict(d)
print(d.cat)
print(d.cat.dog)
print(d.cat.items())
"""
{'dog': 5}
5
dict_items([('dog', 5)])
"""