【问题标题】:Overriding tuple() behaviour on object覆盖对象上的 tuple() 行为
【发布时间】:2017-07-11 00:10:54
【问题描述】:

我可以使用__iter__ 来定义自定义对象看起来像dict。有没有办法单独自定义tuple转换? (是的,我确实意识到这可能会令人困惑,并且可能很少几乎从来都不是一个好主意。)

默认行为:

>>>o = MyClass()
>>>dict(o)
{'value': 1, 'attr_1': "foo", 'attr_2': "bar"}
>>>tuple(o)
(('value', 1), ('attr_1', "foo"), ('attr_2', "bar"))

期望的行为:

>>>o = MyClass()
>>>dict(o)
{'value': 1, 'attr_1': "foo", 'attr_2': "bar"}
>>>tuple(o)
(1, {'attr_1': "foo", 'attr_2': "bar"})

这是o 所属类的一个最小示例:

class MyClass(object):

   def __init__(self):
       self.value = 1
       self.attributes = {'attr_1': "foo", 'attr_2': "bar"}

   def __iter__(self):
        yield ("value", self.value)
        for k, v in self.attributes.items():
            yield (k, v)

相关,但不是关于 dict 和 tuple 的不同结构:special method for an object to override tuple expansion?

【问题讨论】:

  • 我怀疑你能做到这一点。为什么不定义一个方法o.to_tuple()
  • o 的类型是什么?
  • @MosesKoledoye 是的,这实际上就是我正在做的事情,但我很好奇我是否也可以让tuple(o) 表现相同,作为一种语法糖
  • @stamaimer 它属于一个自定义类(新式),如果这很重要?
  • 可以显示自定义__iter__的代码吗?

标签: python


【解决方案1】:

为元组编写自己的构造函数是一个更好的主意:

class MyTuple(tuple):

    @classmethod
    def from_default_tuple(cls): # your alternative constructor
        pass

如果你真的想改tuple,这行也没什么问题:(除了你的IDE会觉得你有点疯)

tuple = MyTuple.from_default_tuple

但这绝对是个坏主意。我建议你改用MyTuple.from_default_tuple()

【讨论】:

  • 不需要自定义元组的构造函数。因为自定义类是可迭代的。内置元组和自定义元组的区别在于表示对象的方式。
  • @pythad 谢谢!覆盖tuple不是我要去的地方,但很好的参考。
  • @leo 我实际上会更进一步:不要依赖__iter__ 来生成适合任一 tupledict 的值流,并提供明确的to_tupleto_dict 类方法。 (可以肯定的是,to_dict 作为 实现 细节仍然可以简单地成为 dict(self) 的包装,因为您的 __iter__ 实现是合法的。只是不要指望它是一个全部 -目的将例程转换为任意类型。)
【解决方案2】:

您可以自定义元组的特殊方法__str____repr__

class my_tuple(tuple):
    def __repr__(self):
        return "(%r, %r)" % (self[0][1], dict(self[1:]))

test = MyClass()
print my_tuple(test)

更新

你可以重写你的自定义类的__iter__来达到你的目的。

def __iter__(self):
    yield self.value
    yield self.attributes

o = MyClass()
tuple(o)

【讨论】:

  • 我不确定我是否理解您的建议?示例中的 o 不是元组。并且在进行类型转换时不会调用tuple._repr__...
  • 因为你在MyClass中实现了__iter__,你可以从MyClass的实例构造一个元组。当您调用tuple(o) 时,解释器调用元组的__repr__ 进行检查。正如我在另一个答案和你的问题中评论的那样。你想要的是改变内置元组的表示。
  • 我不知道你为什么要从你的自定义类的实例中构造一个元组。
  • 您仍然只更改了 my_tuple 的表示。如果你尝试例如t=my_tuple(test);print t[0] 你会看到区别。
  • 我猜这是相关代码:github.com/python/cpython/blob/…
猜你喜欢
  • 2014-07-03
  • 1970-01-01
  • 1970-01-01
  • 2011-09-06
  • 1970-01-01
  • 2014-09-21
  • 1970-01-01
  • 1970-01-01
  • 2011-01-20
相关资源
最近更新 更多