【问题标题】:Not understanding why `__index__` method works不明白为什么`__index__`方法有效
【发布时间】:2016-04-18 13:40:33
【问题描述】:

我正在处理这个tutorial,它具有以下二进制类:

import collections

class Binary:
    def __init__(self, value=0):
        if isinstance(value, collections.Sequence):
            if len(value) > 2 and value[0:2] == '0b':
                self._value = int(value, base=2)
            elif len(value) > 2 and value[0:2] == '0x':
                self._value = int(value, base=16)
            else:
                self._value = int(''.join([str(i) for i in value]), base=2)
        else:
            try:
                self._value = int(value)
                if self._value < 0:
                    raise ValueError("Binary cannot accept negative numbers. Use SizedBinary instead")
            except ValueError:
                raise ValueError("Cannot convert value {} to Binary".format(value))

    def __int__(self):
        return self._value

当使用 pytest 运行单元测试时,我们得到:

    def test_binary_hex():
        binary = Binary(6)
>       assert hex(binary) == '0x6'
E       TypeError: 'Binary' object cannot be interpreted as an integer

为了解决这个问题,文章指出:

根据官方文档,“如果 x 不是 Python int 对象,则必须定义一个返回整数的__index__() 方法。”所以这就是我们所缺少的。至于__index__(),文档指出“为了有一个连贯的整数类型类,当定义__index__() 时,还应该定义__int__(),并且两者都应该返回相同的值。”

所以我们只需要添加

def __index__(self):
    return self.__int__()

这确实有效,但为什么这里写的__index__ 和__int__ 返回相同的值?关于:

def __index__(self):
    return self.__int__()

应该是: 返回 self._value.__int__()

编辑:

与:

    def __int__(self):
        return self._value

这对我来说很有意义,因为 _value 是一个整数。

与:

def __index__(self):
    return self.__int__()

在这种情况下, self 又是一个 class 的实例,理论上它可以有许多属性(尽管在这种情况下不是)。我不明白如何返回 self.__int__(),如果我们不将 _value 明确传递给 __int__(),__int__() 知道获取存储在 _value 中的整数。

【问题讨论】:

  • 它们返回相同的值,因为它们是这样写的; __index__ 返回 __int__ 的值。您或多或少只是将 __int__ 方法别名为另一个名称。
  • 您不需要__index__ 将_value 传递给__int__,因为__int__ 已经被编程为读取self 上的_value 属性。你确实明白self.__int__() 调用了你之前定义的__int__ 方法,对吧?
  • 考虑添加一个中间步骤:def __index__(self): x = self.__int__() ; return x 您正在调用__int__ 方法,该方法获取_value 属性并将其返回给__index__,然后从__index__ 返回到什么叫它。
  • 谢谢,我现在明白了。

标签: python


【解决方案1】:

self._value 是一个 int,在一个 int 上调用__int__() 方法返回相同的值,所以这样写:

return self._value.__int__()

会做同样的事情:

return self._value

为了证明我的观点,它与以下内容相同:

return int(int(int(int(self._value))))

在大多数情况下,您可以将__index__ 写为同一函数的直接别名:

def __int__(self):
    return self._value
__index__ = __int__

附:您可能想查看 PEP 357 以了解为什么存在 __index__ 方法的原因。

基本上是区分可以转换为int的对象和本质上是整数的对象:

>>> int(1.3)
1
>>> hex(1.3)
Traceback (most recent call last):
  File "<pyshell#55>", line 1, in <module>
    hex(1.3)
TypeError: 'float' object cannot be interpreted as an integer

【讨论】:

  • 感谢您花时间写这篇文章。我理解了__int__ 部分,但不是__index__ 部分,因为索引不引用_value,那么__index__ 调用的__int__ 函数如何知道作用于_value?
  • 你是什么意思对_value采取行动?如果您执行return self.__int__(),您正在调用__int__ 方法并返回它的结果,就像您执行def myFunc(x): return math.sqrt(x) 它会总是返回与直接调用math.sqrt(x) 相同的结果,另见@deceze's comment
  • 这可能是我对 python 理解的一个问题,所以让我列出我认为事情是如何工作的,你可以在其中戳洞:)。我会在上面编辑它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-23
  • 2013-07-29
  • 1970-01-01
相关资源
最近更新 更多