2016-04-16 14 views
3

Ich arbeite durch diese tutorial. Ich arbeite das iterativ durch. An diesem Punkt habe ich folgendes Binary Klasse:TypeError: __init __() sollte None zurückgeben, nicht 'int'

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) 

Ich laufe durch eine Reihe von Tests pytest verwenden, einschließlich:

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' 

fragte ich eine Frage zu diesem TypeError: int() argument must be a string or a number, not 'Binary' und auf der Grundlage der Antwort habe den Code wie oben geändert. Nun, wenn ich die Reihe von Tests mit pytest ausführen, werden alle die Tests fehlschlagen, und der Fehler ist:

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

Warum ist es ein Problem?

+3

beziehen Diese Antwort gibt nicht 'int' von' __init__' zurück. Es definiert eine Methode "__int__", die für die numerische Konvertierung verwendet wird. –

+0

'__init __()' wird verwendet, um Objekte zu initialisieren, also benutze es nicht so, sondern verwende eine separate Methode für diesen späteren Zweck. –

+0

Warum ist das überhaupt eine Klasse und nicht nur eine Funktion? – iAdjunct

Antwort

2

Die documentation Zustände:

"Da neue() und init() zusammenarbeiten, um Objekte in der Konstruktion (neue(), um zu erstellen, und init(), um sie anzupassen), wird kein Wert nicht-None durch init() zurückgegeben; sie wird dadurch so eine Typeerror zur Laufzeit erhöht werden "

dass so entfernen. return Anweisung und legen Sie sie in einem __int__ Methode in Ihrer Klasse:

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

__init__ genannt wird, nach einer Instanz mit

obj = SomeClass() 

So erstellt wurde nun Art und Weise ist jede Rückgabewert einer Variablen zuweisen Daher muss __init__ nichts zurückgeben (außer implizit None).

Um Ihren Test zu bestehen, sollte das Objekt eine magische Methode __int__ haben, die aufgerufen wird, wenn die Funktion int verwendet wird.

+0

Dank Daniel, das beantwortete eine andere Frage, die ich hatte, was ist die "__int__" Methode? Wenn ich also richtig verstehe, überschreibt __int__ die reguläre int() - Funktion? – user61629

2

__init__ Kann nichts zurückgeben als None. Dies liegt daran, dass es sich um den Initiator einer Instanz handelt, die von __new__ erstellt wurde. Beide Instanzen werden implizit aufgerufen, wenn Sie die Klasse aufrufbar aufrufen. Daher, wenn Sie versuchen, etwas selbst davon zurückzugeben, wird eine TypeError Ausnahme ausgelöst.

Mögliche Lösungen sind Refactor Ihren Code in Methoden oder @property s und verwenden sie später. Wenn Sie etwas mutigere Check-Metaklassen wollen.

2

__init__ initialisiert eine Instanz einer Klasse (in Ihrem Fall eine Instanz von Binary). Eine Instanz einer Klasse ist eine spezifische Sache eines spezifischen Typs.

In Ihrem Fall, Sie scheinen nicht als von Sache Typen verwendet werden, sondern stattdessen als ein Dienstprogramm, das Zahlen intelligent umwandelt.Sie sollten stattdessen wahrscheinlich machen es nur eine Funktion:

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) 
+0

Vielen Dank, Sie haben wahrscheinlich Recht, aber ich folge dem Blogbeitrag, um mir ein paar OOP beizubringen – user61629

+0

Aber Sie vermissen den Punkt der OOP, weil das, was Sie machen, kein Objekt ist. – iAdjunct

3

Bevor eine Antwort zur Verfügung gestellt wurde, bemerkte ich, dass __init__() Objekte zu initialisieren, verwendet wird, und somit müssen Sie keinen Wert in sich zurück. Aber es ist seltsam zu sehen, einige der oben genannten Antworten gebeten, keine Werte innerhalb __init__() b zurück zu geben, aber ihre Lösung nicht respektieren, was sie sagten. Nur @CPanda tat nicht das Gegenteil von dem, was er sagte. Deshalb habe ich auf highlight this again als Antwort wollen:

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 kehren nicht Werte __init__() mit!

Eine andere Sache, die ich hinzufügen möchte, auch wenn dies nicht AFAIK in Python Enhancement Proposals erwähnt wird, ich persönlich nie __init__() verwenden, um Nachrichten zu drucken print''/print('') verwenden. Die einzigen Nachrichten, die ich in __init__() drucke, sind diejenigen, die auf Fehlermeldungen in Formularen wie raise ValueError() (überprüfen Sie Built-in Exceptions für weitere Informationen)

Verwandte Themen