如何将Python dict转换为特定类型的对象?
使用Python2.7,我需要将字典转换为类型化对象 例如,如果我有这句话:如何将Python dict转换为特定类型的对象?,python,dictionary,metaprogramming,Python,Dictionary,Metaprogramming,使用Python2.7,我需要将字典转换为类型化对象 例如,如果我有这句话: mapy = {'id': 1, 'name': 'bob'} 鉴于前面的映射和类型名(在本例中为'Person'),我需要某种方法在运行时生成此类: 我是否应该考虑使用元编程技术,如果是这样的话,哪一个是精确的(装饰器,元类,…)?< /P> 请注意,我不仅仅需要将dict转换为对象;我还需要将一些类型信息附加到结果对象 您可以尝试将命名为tuple: from collections import namedtu
mapy = {'id': 1, 'name': 'bob'}
鉴于前面的映射和类型名(在本例中为'Person'
),我需要某种方法在运行时生成此类:
我是否应该考虑使用元编程技术,如果是这样的话,哪一个是精确的(装饰器,元类,…)?< /P>
请注意,我不仅仅需要将dict转换为对象;我还需要将一些类型信息附加到结果对象 您可以尝试将
命名为tuple
:
from collections import namedtuple
mapy = { 'id' : 1, 'name' : 'bob'}
# Note that the order of `mapy.keys()` is unpredictable.
Person = namedtuple('Person', mapy.keys())
p = Person(**mapy)
p.id
p.name
您可以尝试
namedtuple
:
from collections import namedtuple
mapy = { 'id' : 1, 'name' : 'bob'}
# Note that the order of `mapy.keys()` is unpredictable.
Person = namedtuple('Person', mapy.keys())
p = Person(**mapy)
p.id
p.name
通常,您的
\uuuu init\uuuu
将具有实际参数来提供属性值:
class Person:
def __init__(self, id, name):
self.id = id
self.name = name
然后,您可以直接将词典解压缩到其中:
>>> p = Person(**{'id': 1, 'name': 'bob'})
>>> p.id
1
>>> p.name
'bob'
>>> p
<__main__.Person object at 0x02DA5730>
p=Person(**{'id':1,'name':'bob'})
>>>p.id
1.
>>>p.name
“鲍勃”
>>>p
通常,您的
\uuuu init\uuuu
会有实际参数来提供属性值:
class Person:
def __init__(self, id, name):
self.id = id
self.name = name
然后,您可以直接将词典解压缩到其中:
>>> p = Person(**{'id': 1, 'name': 'bob'})
>>> p.id
1
>>> p.name
'bob'
>>> p
<__main__.Person object at 0x02DA5730>
p=Person(**{'id':1,'name':'bob'})
>>>p.id
1.
>>>p.name
“鲍勃”
>>>p
您可以使用以下函数根据给定的
dict
生成\uuuuuuu初始化\uuuuuuu
方法:
def make_init(d):
def __init__(self, **kwargs):
for name in d:
setattr(self, name, kwargs[name])
return __init__
然后,使用type
的三参数形式在运行时创建一个类
type_name = "Person"
Person = type(type_name, (object,), { '__init__': make_init(mapy) })
最后,使用字典实例化该类以向\uuuu init\uuuu
提供参数:
obj = Person(**mapy)
您可以使用以下函数根据给定的
dict
生成\uuuuu init\uuuu
方法:
def make_init(d):
def __init__(self, **kwargs):
for name in d:
setattr(self, name, kwargs[name])
return __init__
然后,使用type
的三参数形式在运行时创建一个类
type_name = "Person"
Person = type(type_name, (object,), { '__init__': make_init(mapy) })
最后,使用字典实例化该类以向\uuuu init\uuuu
提供参数:
obj = Person(**mapy)
您的请求有一个问题:“我不仅需要将dict转换为对象;我还需要将某些类型信息附加到结果对象上。”问题是“某些类型信息”太模糊。最直接的实现将为每个对象创建一个新类,这几乎肯定不是您想要的 试试这个:
def make_dict_into_object(name, d):
class Dummy(object):
def __init__(self, attr):
self.__dict__.update(attr)
Dummy.__name__ = name
return Dummy(d)
mapy = { 'id' : 1, 'name' : 'bob'}
bob = make_dict_into_object('Person', mapy)
print bob.name
mapx = { 'id' : 1, 'name' : 'steve'}
steve = make_dict_into_object('Person', mapx)
print steve.id
到目前为止还不错,对吧?但这可能不是你想要的。运行上述操作后,添加以下内容:
print type(steve) == type(bob)
结果将是False,因为make_dict_into_class
在每次调用时生成一个新类。将“某些类型信息”附加到对象是愚蠢的,因为它是每个对象的新类型
有多种方法可以解决这个问题,具体取决于结果对象的实际用例。一种方法是缓存新创建的类,并假设具有相同名称的后续调用引用相同的类:
class_cache = {}
def make_dict_into_object(name, d):
the_class = class_cache.setdefault(name, None)
if the_class is None:
class the_class(object):
def __init__(self, attr):
self.__dict__.update(attr)
the_class.__name__ = name
class_cache[name]=the_class
return the_class(d)
使用此版本,bob
和steve
的最终类型相同:
mapy = { 'id' : 1, 'name' : 'bob'}
bob = make_dict_into_class('Person', mapy)
print bob.name
mapx = { 'id' : 1, 'name' : 'steve'}
steve = make_dict_into_class('Person', mapx)
print steve.id
print type(steve) == type(bob)
您的请求有一个问题:“我不仅需要将dict转换为对象;我还需要将某些类型信息附加到结果对象上。”问题是“某些类型信息”太模糊。最直接的实现将为每个对象创建一个新类,这几乎肯定不是您想要的 试试这个:
def make_dict_into_object(name, d):
class Dummy(object):
def __init__(self, attr):
self.__dict__.update(attr)
Dummy.__name__ = name
return Dummy(d)
mapy = { 'id' : 1, 'name' : 'bob'}
bob = make_dict_into_object('Person', mapy)
print bob.name
mapx = { 'id' : 1, 'name' : 'steve'}
steve = make_dict_into_object('Person', mapx)
print steve.id
到目前为止还不错,对吧?但这可能不是你想要的。运行上述操作后,添加以下内容:
print type(steve) == type(bob)
结果将是False,因为make_dict_into_class
在每次调用时生成一个新类。将“某些类型信息”附加到对象是愚蠢的,因为它是每个对象的新类型
有多种方法可以解决这个问题,具体取决于结果对象的实际用例。一种方法是缓存新创建的类,并假设具有相同名称的后续调用引用相同的类:
class_cache = {}
def make_dict_into_object(name, d):
the_class = class_cache.setdefault(name, None)
if the_class is None:
class the_class(object):
def __init__(self, attr):
self.__dict__.update(attr)
the_class.__name__ = name
class_cache[name]=the_class
return the_class(d)
使用此版本,bob
和steve
的最终类型相同:
mapy = { 'id' : 1, 'name' : 'bob'}
bob = make_dict_into_class('Person', mapy)
print bob.name
mapx = { 'id' : 1, 'name' : 'steve'}
steve = make_dict_into_class('Person', mapx)
print steve.id
print type(steve) == type(bob)
我不太确定你想在这里做什么,但可能是你想要的。我不太确定你想在这里做什么,但可能是您正在寻找的。类定义需要以编程方式生成,即当程序运行时,定义不存在launched@Chedy2149那么nneonneo的
namedtuple
建议可能是你最好的选择,但我很想听听你为什么认为这是必要的——做你的“课程”没有实例方法?@Chedy2149,Python中的类是一级对象。动态创建一个新类并为其指定所需的名称和属性非常容易;见下面我的答案。类定义需要通过编程生成,即当程序运行时,定义不存在launched@Chedy2149那么nneonneo的namedtuple
建议可能是你最好的选择,但我很想听听你为什么认为这是必要的——做你的“课程”没有实例方法?@Chedy2149,Python中的类是一级对象。动态创建一个新类并为其指定所需的名称和属性非常容易;请看下面我的答案。这是一个很好的方法。我看到的唯一问题是它创建了一个只读对象(因为它是tuple
的一个子类)。@Dan:这一点很好。如果OP需要读/写对象,他们可以查看namedtuple
的实现,了解如何动态生成适当的类定义。这是一种很好的方法。我看到的唯一问题是它创建了一个只读对象(因为它是tuple
的一个子类)。@Dan:这一点很好。如果OP需要读/写对象,他们可以查看namedtuple
的实现,以了解如何动态生成适当的类定义。您可以将for
循环替换为self.\uu dict\uuuuu.update(d)
,并且有一种更明确的动态创建类的方法(参见下面的示例)。您可以将循环的替换为self.\uu dict\uuuu.update(d)
,