各キーがそのオブジェクトの属性になるような方法で、Pythonのディクショナリからオブジェクトを作成することは可能ですか?
このようなもの:
d = { 'name': 'Oscar', 'lastName': 'Reyes', 'age':32 }
e = Employee(d)
print e.name # Oscar
print e.age + 10 # 42
私はそれがこの質問のほぼ逆になると思います:オブジェクトのフィールドからのPython辞書
各キーがそのオブジェクトの属性になるような方法で、Pythonのディクショナリからオブジェクトを作成することは可能ですか?
このようなもの:
d = { 'name': 'Oscar', 'lastName': 'Reyes', 'age':32 }
e = Employee(d)
print e.name # Oscar
print e.age + 10 # 42
私はそれがこの質問のほぼ逆になると思います:オブジェクトのフィールドからのPython辞書
回答:
確かに、このようなもの:
class Employee(object):
def __init__(self, initial_data):
for key in initial_data:
setattr(self, key, initial_data[key])
更新
ブレントナッシュが示唆するように、キーワード引数も許可することで、これをより柔軟にすることができます。
class Employee(object):
def __init__(self, *initial_data, **kwargs):
for dictionary in initial_data:
for key in dictionary:
setattr(self, key, dictionary[key])
for key in kwargs:
setattr(self, key, kwargs[key])
次に、次のように呼び出すことができます。
e = Employee({"name": "abc", "age": 32})
またはこのように:
e = Employee(name="abc", age=32)
またはこのようにさえ:
employee_template = {"role": "minion"}
e = Employee(employee_template, name="abc", age=32)
Employee(some_dict)
とEmployee(**some_dict)
APIの両方を提供することは矛盾しています。どちらが良いかを指定する必要があります。
()
代わりに設定した場合、次のように設定None
できますdef __init__(self, iterable=(), **kwargs): self.__dict__.update(iterable, **kwargs)
。
[[setattr(self,key,d[key]) for key in d] for d in some_dict]
AddressNotFoundError
(爆破するのではなく、修正されたデータを返すため)に対処しています-PHP ((object) ['x' => 'y']
)で非常に簡単なものはPythonで非常に
この方法で属性を設定することは、ほとんどの場合、問題を解決するための最良の方法ではありません。どちらか:
すべてのフィールドを事前に知っておく必要があります。その場合、すべての属性を明示的に設定できます。これは次のようになります
class Employee(object):
def __init__(self, name, last_name, age):
self.name = name
self.last_name = last_name
self.age = age
d = {'name': 'Oscar', 'last_name': 'Reyes', 'age':32 }
e = Employee(**d)
print e.name # Oscar
print e.age + 10 # 42
または
すべてのフィールドが事前にどうあるべきか分からない。この場合、オブジェクトの名前空間を汚染するのではなく、dictとしてデータを保存する必要があります。属性は静的アクセス用です。このケースは次のようになります
class Employee(object):
def __init__(self, data):
self.data = data
d = {'name': 'Oscar', 'last_name': 'Reyes', 'age':32 }
e = Employee(d)
print e.data['name'] # Oscar
print e.data['age'] + 10 # 42
基本的にケース1と同等の別の解決策は、を使用することcollections.namedtuple
です。それを実装する方法については、vanの回答を参照してください。
を使用してオブジェクトの属性にアクセスし、そのオブジェクト__dict__
のupdateメソッドを呼び出すことができます。
>>> class Employee(object):
... def __init__(self, _dict):
... self.__dict__.update(_dict)
...
>>> dict = { 'name': 'Oscar', 'lastName': 'Reyes', 'age':32 }
>>> e = Employee(dict)
>>> e.name
'Oscar'
>>> e.age
32
__dict__
実装のアーティファクトであり、使用しないでください。また、これはクラス上の記述子の存在を無視します。
__dict__
言語の文書化された部分であり、実装の成果物ではありません。
setattr
アクセス__dict__
するよりも使用することをお勧めします。__dict__
使用したときにそこにない、または望んでいることをしていないことにつながる可能性のある多くのことを覚えておく必要がありますが__dict__
、setattr
実際には実際に行っていることと同じですfoo.bar = baz
。
__dict__
は推奨されないようです:docs.python.org/tutorial/classes.html#id2
辞書のキーとして属性名を使用しないのはなぜですか?
class StructMyDict(dict):
def __getattr__(self, name):
try:
return self[name]
except KeyError as e:
raise AttributeError(e)
def __setattr__(self, name, value):
self[name] = value
名前付き引数、タプルのリスト、ディクショナリ、または個別の属性割り当てで初期化できます。例:
nautical = StructMyDict(left = "Port", right = "Starboard") # named args
nautical2 = StructMyDict({"left":"Port","right":"Starboard"}) # dictionary
nautical3 = StructMyDict([("left","Port"),("right","Starboard")]) # tuples list
nautical4 = StructMyDict() # fields TBD
nautical4.left = "Port"
nautical4.right = "Starboard"
for x in [nautical, nautical2, nautical3, nautical4]:
print "%s <--> %s" % (x.left,x.right)
または、属性エラーを発生させる代わりに、不明な値に対してNoneを返すことができます。(web2pyストレージクラスで使用されるトリック)
settattr
本当にサポートが必要な場合は、答えを使用するのがよいと思いますdict
。
しかし、Employee
objectが.name
dict構文(['name']
)ではなくドット構文()でアクセスできる構造体である場合、次のような名前付きタプルを使用できます。
from collections import namedtuple
Employee = namedtuple('Employee', 'name age')
e = Employee('noname01', 6)
print e
#>> Employee(name='noname01', age=6)
# create Employee from dictionary
d = {'name': 'noname02', 'age': 7}
e = Employee(**d)
print e
#>> Employee(name='noname02', age=7)
print e._asdict()
#>> {'age': 7, 'name': 'noname02'}
_asdict()
すべてのプロパティにディクショナリとしてアクセスする方法はありますが、後で追加の属性を追加することはできません。作成中のみです。
dictを使用するのと同様に、kwargsを次のように使用できます。
class Person:
def __init__(self, **kwargs):
self.properties = kwargs
def get_property(self, key):
return self.properties.get(key, None)
def main():
timmy = Person(color = 'red')
print(timmy.get_property('color')) #prints 'red'
def __init__(self,**initial_data)
、あなたは(あまりにも(例えば「E =会社員(名= 『オスカー』)」または単に(辞書に取る例えば「E =従業員をキーワード引数を行うことができますinitメソッドを持つの追加利益を得ます**辞書)」)。