2017-06-20 7 views
3

Wie kann ich bei der Definition einer Klasse Argumente in die Signaturen ihrer Methoden aufnehmen, die derselben Klasse angehören müssen? Ich bin eine Graphenstruktur bauen, die wie das funktionieren sollen, aber hier ist ein vereinfachtes Beispiel:Methodensignaturargumente vom Typ (self)

class Dummy: 
    def __init__(self, value: int, previous: Dummy=None): 
     self._value = value 
     self._previous = previous 

    @property 
    def value(self): 
     return self._value 

    def plus_previous(self): 
     return self.value + self._previous.value 

d1 = Dummy(7) 
d2 = Dummy(3, d1) 
d2.plus_previous() 

Diese in den folgenden Fehlern führt:

NameError: name 'Dummy' is not defined 

Ich meine, ich kann es tun, der Python 2 Art und Weise, aber ich hatte gehofft, es ist ein python-3-ic Lösung als das:

class Dummy: 
    def __init__(self, value: int, previous=None): 
     assert type(previous) is Dummy or previous is None 
     ... 
+0

PS: Natürlich, ich kann nicht verwendet werden: Typ (Selbst-) als selbst ist nicht definiert noch in der Signatur. Ich konnte nur das tun: Assert-Typ (früher) ist Typ (Selbst) , die zumindest eine kleine Verbesserung ist –

+0

Als Nebenbemerkung, erkennen Sie, dass Typ Hinweise nicht wie die'Asssert'-Anweisung funktionieren wird, richtig? Sie werden nicht erzwungen. Sie sind * Hinweise *. –

Antwort

2

Obwohl ich stimme zu, es ist ein ziemlich hässlich Hack, können Sie Zeichenfolgen verwenden als Typ deutet auch:

class Dummy: 
    def __init__(self, value: int, previous: 'Dummy'=None): 
     self._value = value 
     self._previous = previous 

    @property 
    def value(self): 
     return self._value 

    def plus_previous(self): 
     return self.value + self._previous.value

wie in PEP-484 auf Typ Hinweise beschrieben:

When a type hint contains names that have not been defined yet, that definition may be expressed as a string literal, to be resolved later.

A situation where this occurs commonly is the definition of a container class, where the class being defined occurs in the signature of some of the methods. For example, the following code (the start of a simple binary tree implementation) does not work:

class Tree: 
    def __init__(self, left: Tree, right: Tree): 
     self.left = left 
     self.right = right 

To address this, we write:

class Tree: 
    def __init__(self, left: 'Tree', right: 'Tree'): 
     self.left = left 
     self.right = right 

The string literal should contain a valid Python expression (i.e., compile(lit, '', 'eval') should be a valid code object) and it should evaluate without errors once the module has been fully loaded. The local and global namespace in which it is evaluated should be the same namespaces in which default arguments to the same function would be evaluated.

Ein Problem mit diesem Hack jedoch, dass, wenn Sie eine Umbenennungs in der IDE tun, es ist Auf jeden Fall ist es möglich, dass die IDE diese Zeichenfolgenliterale nicht berücksichtigt und sie daher nicht umbenennt.

Verwandte Themen