Method signature arguments of type (self)

When I define a class, how do I include the arguments in its method signatures, which should be of the same class? I'm building a graph structure that should work like this, but here's a simplified example:

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()

      

This results in the following error:

NameError: name 'Dummy' is not defined

      

I mean, I can do it in Python 2, but I was hoping there was more python-3-ic solution than this:

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

      

+3


source to share


1 answer


While I agree, this is a pretty ugly hack, you can use strings as type hints:

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
      

as described in PEP-484 in types:



If the type hint contains names that are not yet defined, this definition can be expressed as a string literal, which will be resolved later .

The situation in which this happens is usually the definition of a container class, where a particular class appears in the signature of some of the methods. For example, the following code (start a simple binary tree implementation) doesn't work:

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

      

To solve this problem, we write:

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

      

The string literal must contain a valid Python expression (i.e., compile(lit, '', 'eval')

must be a valid code object), and it must evaluate without error after the module is fully loaded. the local and global namespace in which it is evaluated must be the same namespace in which the default arguments for the same function would be evaluated.

However, the problem with this hack is that if you are doing the renaming in the IDE , then it is definitely possible that the IDE will not respect those string literals and thus not be able to rename them.

+2


source







All Articles