问题
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 aTypeError
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 @property
s and use them later. If you want something more daring checkout metaclasses.
来源:https://stackoverflow.com/questions/36666353/typeerror-init-should-return-none-not-int