【问题标题】:Can I create a class which can be unpacked?我可以创建一个可以解包的类吗?
【发布时间】:2016-07-12 13:16:00
【问题描述】:

例如:

x = (1, 2)
a,b = x

现在我想在x 是某个不是列表或元组的类的实例的情况下完成此操作。简单地覆盖 __getitem____getslice__ 不起作用:

class Test(object):
    def __getitem__(self, key):
        return 1

a,b = Test()

产生ValueError: too many values to unpack。我可以在不继承listtuple(或它们各自的UserX 类)的情况下完成这项工作吗?或者这只是一些我无法使用的底层魔法?

【问题讨论】:

    标签: python python-2.7 iterator


    【解决方案1】:

    您需要覆盖__iter____getitem__。这是一个使用__iter__的示例:

    class Test(object):
        def __iter__(self):
            return iter([1, 2])
    
    a,b = Test()
    

    小心,__iter__ 需要返回一个迭代器。最简单的方法是将数据结构包装在 iter 中,或者让它从生成器中生成。

    有关使用 __getitem__ 的示例,请参阅 jonrsharpe 的出色回答。

    【讨论】:

    • 你不需要,但它可能更整洁!
    【解决方案2】:

    根据PEP-234,它定义了迭代器(强调我的):

    如果实现了一个对象,则可以用“for”对其进行迭代 __iter__() __getitem__()

    可以使用__getitem__ 执行此操作,但它必须抛出IndexError 以指示您何时到达终点。您会看到 too many values to unpack,因为 Python 无法判断它已完成对您的对象的迭代。

    这可行:

    class Test(object):
        def __getitem__(self, key):
            if key > 1:
                raise IndexError
            return 1 
    

    使用中:

    >>> t = Test()
    >>> a, b = t
    >>> a
    1
    >>> b
    1
    >>> t[2]
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 4, in __getitem__
    IndexError
    

    【讨论】:

    • 哦,很高兴知道!我不会认为__getitem__ 会为此工作。
    • 我想过实现__len__,但我错了。好吧,我想请求宽恕更容易:)。
    • 如果可以的话,我也会接受这个答案。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2015-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-27
    • 1970-01-01
    相关资源
    最近更新 更多