2016-04-18 7 views
1

Ich bin durch diese tutorial arbeiten, die die folgende Binary Klasse:verstehen nicht, warum `__index__` Methode funktioniert

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 

wenn ein Unittest mit pytest laufen wir bekommen:

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

zu lösen Dies besagt der Artikel:

Laut der offiziellen Dokumentation, "Wenn X kein Python Int-Objekt ist, muss es d efine eine __index__() Methode, die eine ganze Zahl zurückgibt. " Das ist es, was uns fehlt. Wie für __index__(), die Dokumentation besagt, dass "Um eine kohärente Integer-Klasse zu haben, wenn __index__() definiert ist, sollte auch __int__() definiert werden, und beide sollten den gleichen Wert zurückgeben."

Also müssen wir

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

Das funktioniert, fügen Sie einfach, aber warum die __index__ tun und __int__ wie hier geschrieben, denselben Wert zurückgeben? In Bezug auf:

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

Shouldnt es sein: return self._value. __int__()

edit:

mit:

def __int__(self): 
     return self._value 

Dies macht Sinn für mich, weil _value eine ganze Zahl ist.

mit:

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

Auch in diesem Fall ist selbst eine Instanz einer Klasse, die in der Theorie könnte viele Attribute (wenn auch nicht in diesem Fall). Ich verstehe nicht, wie im Gegenzug selbst. __int__(), weiß der __int__() die ganze Zahl gespeichert in _value zu erhalten, wenn wir _value passieren nicht explizit auf __int__()

+2

Sie den gleichen Wert zurück, weil das ist, wie sie geschrieben sind; '__index__' gibt den Wert von' __int__' zurück. Sie aliasieren die Methode "__int__" mehr oder weniger einfach unter einem anderen Namen. – deceze

+0

Sie brauchen '__index__' nicht, um' _value' an '__int__' zu übergeben, weil' __int__' bereits so programmiert ist, dass das '_value' Attribut auf' self' gelesen wird. Sie verstehen, dass 'self .__ int __()' die Methode '__int__' aufruft, die Sie zuvor definiert haben, oder? – Blckknght

+0

erwägen, einen Zwischenschritt hinzuzufügen: 'def __index __ (self): x = selbst .__ int __(); return x 'Sie rufen die' __int__' Methode auf, die das '_value' Attribut erhält und es an' __index__' zurückgibt und dann von '__index__' zurück zu dem, was immer es heißt. –

Antwort

2

self._value ist ein int, auf einen int die __int__() Methode aufrufen denselben Wert zurückgibt, so schreiben:

return self._value.__int__() 

würde das gleiche tun wie:

return self._value 

Und genau mein Punkt zu beweisen, dass es die gleiche sein würde, wie:

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

In den meisten Fällen Sie __index__ sein, um einen direkten Alias ​​auf die gleiche Funktion schreiben:

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

P. S. Vielleicht möchten Sie PEP 357 für die rationale warum die __index__ Methode existiert.

Grundsätzlich ist es zwischen Objekten zu unterscheiden, die zu einem int und Objekte umgewandelt werden können, die von Natur aus ganzen Zahlen sind:

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

Danke, dass Sie sich die Zeit genommen haben, dies zu schreiben. Ich habe den '__int__' Teil, aber nicht den'______ Teil verstanden, weil der Index sich nicht auf' _value' bezieht. Wie also weiß die von '___ ___ aufgerufene' __int__' Funktion auf '_value' zu ​​reagieren? – user61629

+0

was meinst du mit _act auf '_value'_? Wenn Sie 'return self .__ int __()' zurückgeben, rufen Sie die '__int__' -Methode auf und geben das Ergebnis zurück, so wäre es, wenn Sie' def myFunc (x): return math.sqrt (x) '_always_ zurückgeben würden das gleiche Ergebnis wie das direkte Aufrufen von 'math.sqrt (x)', siehe auch [@ decezes Kommentar] (http://stackoverflow.com/questions/36695699/not-understanding-why-index-method-works/36696282?noredirect) = 1 # comment60979766_36695699) –

+0

Dies ist wahrscheinlich ein Problem in meinem Verständnis von Python, so lassen Sie mich auslegen, wie ich denke, Dinge funktionieren und Sie können Löcher hineinstecken :). Ich werde es oben bearbeiten. – user61629

Verwandte Themen