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

折月煮酒 提交于 2021-02-17 21:27:16

问题


I'm working through this tutorial. I'm working through this iteratively. At this point I have the following Binary class:

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)

I'm running through a suite of tests using pytest, including:

    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'

I asked a question about this TypeError: int() argument must be a string or a number, not 'Binary' and based on the answer changed the code to as above. Now when I run the suite of tests using pytest, all the tests fail and the error is:

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

Why is there a problem?


回答1:


Before any answer was provided, I commented you that __init__() is used to initialize objects and thus you must not return any value within it. But it is strange to see some of the upvoted answers above asked not to return values within __init__() but still their solution does not respect what they said. Only @CPanda did not do the opposite of what he said. That is why I want to highlight this again as answer:

Called after the instance has been created (by __new__()), but before it is returned to the caller. The arguments are those passed to the class constructor expression. If a base class has an __init__() method, the derived class's __init__() method, if any, must explicitly call it to ensure proper initialization of the base class part of the instance; for example: BaseClass.__init__(self, [args...]).

Because __new__() and __init__() work together in constructing objects (new() to create it, and __init__() to customise it), no non-None value may be returned by __init__(); doing so will cause a TypeError to be raised at runtime.

So do NOT return values using __init__()!

An other thing I want to add, even if this is not mentioned AFAIK in Python Enhancement Proposals, I personally never use __init__() to print messages using print''/print(''). The only messages I print in __init__() are those related to raised exception error messages in a forms such as raise ValueError() (check Built-in Exceptions for more information)




回答2:


The documentation states:

"Because __new__() and __init__() work together in constructing objects (__new__() to create it, and __init__() to customise it), no non-None value may be returned by __init__(); doing so will cause a TypeError to be raised at runtime."

So remove that return statement and place it in an __int__ method in your class:

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



回答3:


__init__ initializes an instance of a class (in your case, an instance of Binary). An instance of a class is a specific thing of a specific type.

In your case, you seem to be not using it as a type of thing but instead as a utility that intelligently converts numbers. You should instead probably just make it a function:

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)



回答4:


__init__ is called, after a instance was created with

obj = SomeClass()

So there is now way to assign any return value to a variable, therefore __init__ must not return anything (except implicitly None).

To pass your test, the object should have a magic method __int__, which is called, when the function int is used.




回答5:


__init__ Cannot return anything other than None. This is because it is the initialiser of an instance created by __new__, both of which are called implicitly when you call the class callable. Hence if you try to return anything yourself from it, a TypeError exception is raised.

Possible solutions are refactor your code in to methods or @propertys and use them later. If you want something more daring checkout metaclasses.



来源:https://stackoverflow.com/questions/36666353/typeerror-init-should-return-none-not-int

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!