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
という名前の辞書にデータをインポートできるようにしたいと思っています。
(変数名は実行時まで解決されないので、私はまだコモドに骨を投げる必要があります-self.Field1 = None
で十分です。
だから-どうすれば自分がしたいことをするのですか?それとも、設計が不十分なPython以外のツリーをbarえていますか?
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のコードは、クラス属性が指定された辞書に基づいているクラスを作成します。
特定の状況に応じて、これらのソリューションのいずれかがより適している場合があります。 1つまたは複数のクラスインスタンスを作成することは明白ですか?答えが1つの場合は、オブジェクトの作成を完全にスキップして、型のみを構築することもできます(したがって、SilentGhostの答えに進みます)。
>>> q = { 'Field1' : 3000, 'Field2' : 6000, 'RandomField' : 5000 }
>>> q = type('allMyFields', (object,), q)
>>> q.Field1
3000
type
のドキュメントは、ここで何が起こっているのかをよく説明しています(コンストラクターとしての使用を参照)。
edit:インスタンス変数が必要な場合、以下も機能します:
>>> a = q() # first instance
>>> a.Field1
3000
>>> a.Field1 = 1
>>> a.Field1
1
>>> q().Field1 # second instance
3000
items
を手動でループする代わりにdict.update
を使用することもできます(ループする場合は、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
名前付きタプルの使用(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
キーの属性検索を許可する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__
メソッドが呼び出され、キー検索が実行されます。
きれいな方法でsetattrを使用してください。 quick-n-dirtyの方法は、インスタンスの内部辞書を更新することです:
>>> class A(object):
... pass
...
>>> a = A()
>>> a.__dict__.update({"foo": 1, "bar": 2})
>>> a.foo
1
>>> a.bar
2
>>>
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のサブクラス の拡張
再発辞書が機能します!
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 __== '__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)])
"""