typed python: using the classes' own type inside class definition

10,968

The name Foo isn't bound yet, because the class itself has not yet been defined at the time that you try to use the name (remember: function arguments are evaluated at function definition time, not at function call time).

From Python 3.7+ you can postpone evaluation of annotations by adding this import at the top of the module:

from __future__ import annotations

In Python 3.10 postponed evaluation will become the default behavior. For Python < 3.7, you can use string literals to delay evaluation of the type:

class Foo:
    def __init__(self, key :str) -> None:
        self.key = key

    def __eq__(self, other: 'Foo') -> bool:
        return self.key == other.key

print('should be true: ', Foo('abc') == Foo('abc'))
print('should be false: ', Foo('abc') == Foo('def'))
Share:
10,968
macjan
Author by

macjan

Updated on June 07, 2022

Comments

  • macjan
    macjan about 2 years

    The following code does not work as expected. Apparently, I cannot use the classes' own type inside class definition:

    class Foo:
        def __init__(self, key :str) -> None:
            self.key = key
    
        def __eq__(self, other :Foo) -> bool:
            return self.key == other.key
    
    print('should be true: ', Foo('abc') == Foo('abc'))
    print('should be false: ', Foo('abc') == Foo('def'))
    

    The result of running it is:

    Traceback (most recent call last):
      File "class_own_type.py", line 1, in <module>
        class Foo:
      File "class_own_type.py", line 5, in Foo
        def __eq__(self, other :Foo) -> bool:
    NameError: name 'Foo' is not defined
    

    Also, checking the code with mypy returns:

    class_own_type.py:5: error: Argument 1 of "__eq__" incompatible with supertype "object"
    

    How can I correct this code to be valid, both for Python and for mypy?