【问题标题】:TypeError: __init__() should return None, not 'int'TypeError: __init__() 应该返回 None,而不是 'int'
【发布时间】:2016-04-16 15:53:36
【问题描述】:

我正在处理这个tutorial。我正在迭代地解决这个问题。此时我有以下二进制类:

class Binary:
    def __init__(self,value):
        self.value = str(value)
        if self.value[:2] == '0b':
            print('a binary!')
            self.value= int(self.value, base=2)
        elif self.value[:2] == '0x':
            print('a hex!')
            self.value= int(self.value, base=16)
        else:
            print(self.value)
        return int(self.value)

我正在使用 pytest 进行一系列测试,包括:

    def test_binary_init_hex():
        binary = Binary(0x6)
        assert int(binary) == 6
      E TypeError: int() argument must be a string or a number, not 'Binary'

我问了一个关于这个TypeError: int() argument must be a string or a number, not 'Binary' 的问题,并根据答案将代码更改为如上。现在,当我使用 pytest 运行测试套件时,所有测试都失败了,错误是:

       TypeError: __init__() should return None, not 'int'

为什么会出现问题?

【问题讨论】:

  • 该答案不会从__init__ 返回int。它定义了一个__int__ 方法,用于数值转换。
  • __init__() 用于初始化对象,所以不要那样使用它,而是为以后的目的使用单独的方法。
  • 为什么这是一个类而不仅仅是一个函数?

标签: python oop


【解决方案1】:

在提供任何答案之前,我评论您__init__() 用于初始化对象,因此您不能在其中返回任何值。但奇怪的是,上面的一些赞成的答案要求不要在__init__() 内返回值,但他们的解决方案仍然不尊重他们所说的话。只有@CPanda没有做与他说的相反的事情。这就是为什么我想highlight this again 作为答案:

在创建实例之后(由__new__())调用,但之前 它被返回给调用者。参数是那些传递给 类构造函数表达式。如果基类有 __init__() 方法,派生类的__init__() 方法,如果有的话,必须显式 调用它以确保正确初始化 实例;例如:BaseClass.__init__(self, [args...]).

因为__new__()__init__() 在构造对象时协同工作(new() 创建它,__init__() 自定义它),没有 __init__() 可以返回非 None 值;这样做会导致 TypeError 在运行时引发。

所以不要使用__init__()返回值!

我想补充的另一件事,即使 Python Enhancement Proposals 中没有提到 AFAIK,我个人从不使用 __init__() 来打印使用 print''/print('') 的消息。我在__init__() 中打印的唯一消息是与以raise ValueError() 等形式引发的异常错误消息相关的消息(有关更多信息,请查看Built-in Exceptions

【讨论】:

    【解决方案2】:

    documentation 声明:

    "因为__new__()__init__() 在构造对象时协同工作(__new__() 用于创建对象,__init__() 用于自定义对象),所以__init__() 不会返回非None 值;这样做会导致在运行时引发 TypeError。"

    所以删除 return 语句并将它放在你的类中的 __int__ 方法中:

    def __int__(self):
        return int(self.value)
    

    【讨论】:

    • 当你说不应该做的时候为什么要返回一个int?这令人困惑。
    • @MartinThoma:你是不是把__int____init__ 混淆了?
    【解决方案3】:

    __init__ 不能返回除None 以外的任何内容。这是因为它是__new__ 创建的实例的初始化器,当您调用可调用类时,它们都会被隐式调用。因此,如果您尝试自己从中返回任何内容,则会引发 TypeError 异常。

    可能的解决方案是将您的代码重构为方法或@propertys,然后再使用它们。如果你想要更大胆的结帐元类。

    【讨论】:

      【解决方案4】:

      __init__ 初始化一个类的实例(在你的例子中,一个Binary 的实例)。类的实例是特定类型的特定事物

      在您的情况下,您似乎没有将它用作 thingtype,而是用作智能转换数字的实用程序。相反,你应该把它变成一个函数:

      def binary ( value ) :
          value = str(value)
          if self.value[:2] == '0b':
              print('a binary!')
              value = int(value, base=2)
          elif self.value[:2] == '0x':
              print('a hex!')
              value = int(value, base=16)
          else:
              print(value)
          return int(value)
      

      【讨论】:

      • 谢谢您,您可能是对的,但我正在关注博客文章以自学一些 oop
      • 但是您错过了 OOP 的重点,因为您所做的不是对象。
      【解决方案5】:

      __init__ 在创建实例后调用

      obj = SomeClass()
      

      所以现在可以将任何返回值分配给变量,因此__init__ 不得返回任何内容(隐式None 除外)。

      为了通过你的测试,对象应该有一个神奇的方法__int__,当使用函数int时会调用它。

      【讨论】:

      • 谢谢丹尼尔,这回答了我的另一个问题,__int__ 方法是什么?所以如果我理解正确__int__ 会覆盖常规的 int() 内置函数?
      猜你喜欢
      • 2019-08-09
      • 2013-12-24
      • 1970-01-01
      • 2019-07-09
      • 1970-01-01
      • 1970-01-01
      • 2023-03-20
      • 2014-12-03
      • 1970-01-01
      相关资源
      最近更新 更多