在python中,如何将类对象强制转换为dict

在python中,如何将类对象强制转换为dict,python,Python,假设我有一个简单的python类 class Wharrgarbl(object): def __init__(self, a, b, c, sum, version='old'): self.a = a self.b = b self.c = c self.sum = 6 self.version = version def __int__(self): return self.s

假设我有一个简单的python类

class Wharrgarbl(object):
    def __init__(self, a, b, c, sum, version='old'):
        self.a = a
        self.b = b
        self.c = c
        self.sum = 6
        self.version = version

    def __int__(self):
        return self.sum + 9000

    def __what_goes_here__(self):
        return {'a': self.a, 'b': self.b, 'c': self.c}
我可以很容易地把它转换成整数

>>> w = Wharrgarbl('one', 'two', 'three', 6)
>>> int(w)
9006
太棒了!但是,现在我想以类似的方式把它交给一个dict

>>> w = Wharrgarbl('one', 'two', 'three', 6)
>>> dict(w)
{'a': 'one', 'c': 'three', 'b': 'two'}
我需要定义什么才能让它工作?我尝试用
\u dict\u
dict
替换
\u这里的内容,但是
dict(w)
导致了
类型错误:Wharrgarbl对象在这两种情况下都不适用。我不认为简单地让课堂变得易学就能解决问题。我还尝试了许多谷歌搜索,其中包含了我所能想到的“python将对象转换为dict”的不同措辞,但找不到任何相关内容:{

另外!请注意调用
w.\uu dict\uuu
不会做我想做的事情,因为它将包含
w.version
w.sum
。我想通过使用
def int(self)
将强制转换自定义为
int
,以同样的方式将强制转换自定义为
int

我知道我可以这样做

>>> w.__what_goes_here__()
{'a': 'one', 'c': 'three', 'b': 'two'}
但是我假设有一种pythonic方法可以使
dict(w)
工作,因为它与
int(w)
str(w)是同一类型的东西
。如果没有更具python风格的方法,那也没关系,我想我会问。哦!我想,既然这很重要,这是针对python2.7的,但对于一个2.4年前就已经过时的解决方案来说,这也是一个额外的积分

还有一个问题与此类似,但可能不同到足以证明这不是一个重复的问题。我相信OP正在询问如何将其类对象中的所有数据转换为字典。我正在寻找一种更为定制的方法,因为我不希望字典返回中包含
\uu dict\uu
中的所有内容由
dict()
编辑。类似于公共变量和私有变量的内容可能足以解释我要查找的内容。对象将存储计算中使用的一些值,这样我就不需要/不想显示在结果字典中

更新:
我选择了asdict建议的
路线,但选择我想要的答案是一个艰难的选择。@RickTeachey和@jpmc26都提供了我将要使用的答案,但前者有更多的信息和选项,也得到了相同的结果,而且被投票率更高,所以我选择了。Upal谢谢你的帮助。我已经在stackoverflow上埋伏了很长时间,我正努力让自己的脚趾更多地伸进水里。

如果不知道问题的全部背景,很难说,但我不会忽略
\uuuuuiter\uucode>

class MyKwargUnpackable:
    def keys(self):
        return list("abc")
    def __getitem__(self, key):
        return dict(zip("abc", "one two three".split()))[key]
我将在类上实现
\uu此处的内容\uuu

as_dict(self:
    d = {...whatever you need...}
    return d
至少有五种六种方法。首选方法取决于您的用例

备选案文1: 只需添加一个
asdict()
方法

根据问题的描述,我将非常考虑<代码> Addit < /Cord>其他答案所建议的事情的方式。这是因为它并没有显示你的对象真的是一个集合:

class Wharrgarbl(object):

    ...

    def asdict(self):
        return {'a': self.a, 'b': self.b, 'c': self.c}
使用下面的其他选项可能会让其他人感到困惑,除非非常清楚哪些对象成员会被迭代,哪些不会被指定为键值对

备选案文1a: 继承您的类(或大部分等效类),并使用为您提供的

from typing import NamedTuple

class Wharrgarbl(NamedTuple):
    a: str
    b: str
    c: str
    sum: int = 6
    version: str = 'old'
使用命名元组是一种非常方便的方法,可以用最少的工作量向类中添加大量功能,包括。但是,如上所示,NT将在其
\u asdict
中包含所有成员

如果有您不想包含在词典中的成员,则需要修改
\u asdict
结果:

from typing import NamedTuple

class Wharrgarbl(NamedTuple):
    a: str
    b: str
    c: str
    sum: int = 6
    version: str = 'old'

    def _asdict(self):
        d = super()._asdict()
        del d['sum']
        del d['version']
        return d
另一个限制是NT是只读的。这可能是可取的,也可能不是可取的

备选案文2: 实施

比如说:

def __iter__(self):
    yield 'a', self.a
    yield 'b', self.b
    yield 'c', self.c
现在,您只需执行以下操作:

dict(my_object)
这是因为
dict()
构造函数接受
的iterable(键,值)
成对构造字典。在执行此操作之前,请自问这样一个问题:以这种方式将对象作为一系列键、值对进行迭代(同时方便创建
dict
)在其他上下文中是否真的是令人惊讶的行为。例如,自问“应该列出
的行为是什么?”(我的对象)
be…?”

此外,请注意,使用get item
obj[“a”]
语法直接访问值将不起作用,关键字参数解包也不起作用。对于这些,您需要实现映射协议

备选案文3: .This允许通过键行为进行访问,在不使用
\uuuuu iter\uuuuuu
的情况下强制转换到
dict
,并且还提供解包行为(
{**my\u obj}
)和关键字解包行为(如果所有键都是字符串(
dict(**my\u obj)

映射协议要求您(至少)同时提供两种方法:
keys()
\uuu getitem\uu

class MyKwargUnpackable:
    def keys(self):
        return list("abc")
    def __getitem__(self, key):
        return dict(zip("abc", "one two three".split()))[key]
现在,您可以执行以下操作:

>>> m=MyKwargUnpackable()
>>> m["a"]
'one'
>>> dict(m)  # cast to dict directly
{'a': 'one', 'b': 'two', 'c': 'three'}
>>> dict(**m)  # unpack as kwargs
{'a': 'one', 'b': 'two', 'c': 'three'}
如上所述,如果您使用的是足够新的python版本,那么您还可以将映射协议对象解包到类似这样的字典理解中(在这种情况下,您的键不需要是字符串):

请注意,当直接将对象强制转换为
dict
时(无需使用kwarg解包,即
dict(m)
),映射协议优先于
\uuuu iter\uuu
方法。因此,当对象用作iterable时(例如,
list(m)
),可能导致对象具有不同的行为,有时也很方便与转换为
dict
dict(m)
)时的对比

强调:仅仅因为您可以使用映射协议,并不意味着您应该这样做。将对象作为一组键值对或关键字参数和值传递到底有意义吗
from dataclasses import dataclass, asdict, field, InitVar

@dataclass
class Wharrgarbl(object):
    a: int
    b: int
    c: int
    sum: InitVar[int]  # note: InitVar will exclude this from the dict
    version: InitVar[str] = "old"

    def __post_init__(self, sum, version):
        self.sum = 6  # this looks like an OP mistake?
        self.version = str(version)
    >>> asdict(Wharrgarbl(1,2,3,4,"X"))
    {'a': 1, 'b': 2, 'c': 3}
class Wharrgarbl(TypedDict):
    a: str
    b: str
    c: str
    >>> w = Wharrgarbl(a=1,b=2,b=3)
    >>> w
    {'a': 1, 'b': 2, 'c': 3}
    >>> type(w)
    <class 'dict'>
class MyDict(TypedDict):
    def my_fancy_method(self):
        return "world changing result"
>>> MyDict().my_fancy_method()
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
AttributeError: 'dict' object has no attribute 'my_fancy_method'
class MyClass:
    def __init__(self,x,y,z):
       self.x = x
       self.y = y
       self.z = z
    def __iter__(self): #overridding this to return tuples of (key,value)
       return iter([('x',self.x),('y',self.y),('z',self.z)])

dict(MyClass(5,6,7)) # because dict knows how to deal with tuples of (key,value)
class A(object):
    def __init__(self, a, b, c, sum, version='old'):
        self.a = a
        self.b = b
        self.c = c
        self.sum = 6
        self.version = version

    def __int__(self):
        return self.sum + 9000

    def __iter__(self):
        return self.__dict__.iteritems()

a = A(1,2,3,4,5)
print dict(a)
def to_dict(self):
    class_vars = vars(MyClass)  # get any "default" attrs defined at the class level
    inst_vars = vars(self)  # get any attrs defined on the instance (self)
    all_vars = dict(class_vars)
    all_vars.update(inst_vars)
    # filter out private attributes
    public_vars = {k: v for k, v in all_vars.items() if not k.startswith('_')}
    return public_vars
def update(self, other=(), /, **kwds):
    ''' D.update([E, ]**F) -> None.  Update D from mapping/iterable E and F.
        If E present and has a .keys() method, does:     for k in E: D[k] = E[k]
        If E present and lacks .keys() method, does:     for (k, v) in E: D[k] = v
        In either case, this is followed by: for k, v in F.items(): D[k] = v
    '''
    if isinstance(other, Mapping):
        for key in other:
            self[key] = other[key]
    elif hasattr(other, "keys"):
        for key in other.keys():
            self[key] = other[key]
    else:
        for key, value in other:
            self[key] = value
    for key, value in kwds.items():
        self[key] = value
class Wharrgarbl(object):
    def __init__(self, a, b, c, sum, version='old'):
        self.a = a
        self.b = b
        self.c = c
        self.sum = 6
        self.version = version

    def __int__(self):
        return self.sum + 9000

    def __keys__(self):
        return ["a", "b", "c"]

    def __getitem__(self, key):
        # have obj["a"] -> obj.a
        return self.__getattribute__(key)
>>> w = Wharrgarbl('one', 'two', 'three', 6)
>>> dict(w)
{'a': 'one', 'c': 'three', 'b': 'two'}
def convert_to_dict(args: dict):
json = dict()
for key, value in args.items():
    key_vals = str(key).split("_")
    last_index = len(key_vals)
    json[str(key_vals[last_index-1])] = value
return json