【问题标题】:Override dict() on class在类上覆盖 dict()
【发布时间】:2018-03-19 12:17:58
【问题描述】:

我正在尝试在 Python 中创建类似 dict 的类。

当你创建一个类时,你有一些方法告诉 Python 如何创建一个内置类。例如,重写 __int__ 方法告诉 Python 如果用户在类的实例上使用 int() 会返回什么。 __float__ 也一样。您甚至可以通过覆盖__iter__ 方法来控制Python 如何生成类的可迭代对象(这可以帮助Python 生成您的类的lists 和tuples)。我的问题是你将如何告诉 Python 如何为你的自定义类创建一个dict?没有特殊的__dict__ 方法,那么你会怎么做呢?我想要以下内容:

class Foo():
    def __dict__(self):
        return {
            'this': 'is',
            'a': 'dict'
        }

foo = Foo()
dict(foo) # would return {'this': 'is', 'a': 'dict'}

我尝试让类继承自 dict,但由于子类试图从 dicttype 继承,因此在代码中稍后会引发错误,因此从 dict 继承不是可能性。还有其他方法吗?

另外,我已经覆盖了 __iter__ 方法,以便它返回一个 dict_keyiterator 对象(当您在 dict 上使用 iter() 时返回的内容),但它似乎仍然没有以应有的方式工作。

【问题讨论】:

  • 你尝试过从collections.abc.*Mapping继承吗?
  • 使用您的类比,我认为“您甚至可以通过覆盖 __iter__ 方法来控制 Python 如何从类中生成 可迭代对象 可能更清楚。 " dicts 是可迭代对象,就像列表和元组一样,您可以通过传入迭代器来创建它们。
  • @martineau,我认为在这种情况下您不会想使用@staticmethod,对吗?大概您的to_dict 需要访问实例才能将其属性转换为字典。
  • 有点通过在我的课堂上创建keys 方法找到了答案。如果你在一个类上使用dict,它会首先尝试使用keys() 方法创建一个映射。我从这里得到它:stackoverflow.com/a/8601389/6212261 它不使用__iter__ 方法,所以我可以实现自己的__iter__ 方法并且仍然能够使用相同的方法制作dict类。
  • ForeverWintr: 对不起...当我写那条评论时,我的意思是@classmethod,这意味着函数需要传递对象才能操作,所以对它的调用看起来像@ 987654352@——不管你是对的,还是让它成为一个常规方法会更好,所以调用可以简单地类似于result = foo_obj.to_dict()

标签: python python-3.x dictionary iterator overriding


【解决方案1】:

dict 可以使用一对可迭代的对来调用,因此如果您将 __iter__ 设计为返回一个可迭代的元组,那么您的示例将按您的意愿工作:

class Foo:
    def __iter__(self):
        yield from {
            'this': 'is',
            'a': 'dict'
        }.items()

dict(Foo())
{'a': 'dict', 'this': 'is'}

如果你想让你的类表现得像一个 python 字典,因为迭代一个实例会迭代它的键,你可以实现 abc.Mapping 定义的接口。

您可以通过实现__getitem____iter____len__ 并从abc.Mapping 继承,或者通过实现所有__getitem____iter____len__ __contains__keysitemsvaluesget__eq____ne__

【讨论】:

  • Foo 对象上创建dict 确实可以正常工作,但是您无法遍历项目的键。像for i in Foo() 这样的东西不会遍历对象的keys,它会遍历(key, value) 元组的tuple
  • @Christian: 好点...但是Foo 不是dict 的正式子类,因此假设它在迭代时会表现得完全一样是不完全合理的。
  • ForeverWintr:FWIW,给你的类(只是)一个__getitem__() 方法也将允许从它们的实例创建内置的dict 类对象。我仍然认为最好更明确地给类一个to_dict() 方法,而不是依赖另一个类的有点晦涩的构造参数细节。..
  • ForeverWintr:作为证据,尝试用def __getitem__(self, key): 替换你的__iter__() 方法,然后是return [('this', 'is'), ('a', 'dict')][key]——这使它的行为有点像(键,值)对的list
  • @martineau:啊,当然!这可能是一个更好的答案。想添加吗?
【解决方案2】:

尽管来自@ForeverWintr 的answer 中的方法相当聪明且有效,但我认为它有点晦涩,因为它利用了有关传递给dict 类构造函数的参数属性的一些神秘细节.

因此,一个更好的方法可能是我在我的 cmets 中所说的,即添加一个可以执行您想要的操作的方法(另外显示了如何简单地给它一个名称来准确地指示正在发生的事情使其更易于理解)。

示例代码:

class Foo:
    def to_dict(self):
        return {'this': 'is', 'more': 'clear'}

print( Foo().to_dict() )  # -> {'this': 'is', 'more': 'clear'}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-08-08
    • 1970-01-01
    • 1970-01-01
    • 2022-07-31
    • 2011-05-03
    • 2017-09-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多