首页 > 解决方案 > 在 python 中使用 str.format() 女巫类

问题描述

我有一个具有__getitem__()可订阅功能的类,就像字典一样。但是,当我尝试将它传递给 a 时,str.format()我得到一个TypeError. 如何在 python 中使用带有该format()函数的类?

>>> class C(object):
      id=int()
      name=str()

      def __init__(self, id, name):
        self.id=id
        self.name=name

      def __getitem__(self, key):
        return getattr(self, key)

>>> d=dict(id=1, name='xyz')
>>> c=C(id=1, name='xyz')
>>>
>>> #Subscription works for both objects
>>> print(d['id'])
1
>>> print(c['id'])
1
>>>
>>> s='{id} {name}'
>>> #format() only works on dict()
>>> print(s.format(**d))
1 xyz
>>> print(s.format(**c))
Traceback (most recent call last):
  File "<pyshell#13>", line 1, in <module>
    print(s.format(**c))
TypeError: format() argument after ** must be a mapping, not C

标签: pythonpython-3.xstringmappingtypeerror

解决方案


正如一些评论提到你可以继承自dict,它不起作用的原因是:

如果语法 **expression 出现在函数调用中,则表达式必须计算为映射,其内容被视为附加关键字参数。如果关键字同时出现在表达式中并作为显式关键字参数出现,则会引发 TypeError 异常。

要使其工作,您需要实施 Mapping ABC。类似这样的东西:

from collections.abc import Mapping


class C(Mapping):

    id=int()
    name=str()

    def __init__(self, id, name):
        self.id = id
        self.name = name

    def __iter__(self):
        for x in self.__dict__.keys():
            yield x

    def __len__(self):
        return len(self.__dict__)

    def __getitem__(self, key):
        return self.__dict__[key]

这样你就应该能够使用s = '{id}{name}'.format(**c) 而不是s = '{id}{name}'.format(**c.__dict__)

如果您希望能够像在字典中一样更改类变量,也可以使用MutableMappingfrom module。collections.abcMutableMapping 还需要实现__setitem____delitem__


推荐阅读