Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error when referencing a class within its __init__ method #2020

Closed
shreydesai opened this issue Aug 12, 2016 · 2 comments
Closed

Error when referencing a class within its __init__ method #2020

shreydesai opened this issue Aug 12, 2016 · 2 comments

Comments

@shreydesai
Copy link
Contributor

shreydesai commented Aug 12, 2016

I have a class called Node which represents a general node for a linked list. As defined, a node has two attributes: the node's data and a memory reference to the following node.

from typing import TypeVar, Generic

T = TypeVar('T')

class Node(Generic[T]):
  def __init__(self, data: T, next: Node[T]) -> None:
    self.data = data
    self.next = next

When I run this module with the mypy checker (mypy node.py), it has no issue with this. However, python3 node.py yields the following error: NameError: name 'Node' is not defined.

I tried changing next: Node[T] to next: object, but that generated a mypy error (error: Incompatible types in assignment (expression has type "object", variable has type Node[Any])).

How do I reconcile the differences in behavior when running this module with python3 and mypy while also maintaining the structure of this class?

@Michael0x2a
Copy link
Collaborator

Michael0x2a commented Aug 12, 2016

What's happening here is that when the Python interpreter hits the __init__ method, the Node class is still in the process of being defined, and so Node hasn't been bound to the environment yet. This explains why Python claims Node[T] isn't defined.

The workaround is to use forward references and write Node[T] as a string, which mypy will also understand:

from typing import TypeVar, Generic

T = TypeVar('T')

class Node(Generic[T]):
  def __init__(self, data: T, next: 'Node[T]') -> None:
    self.data = data
    self.next = next

This will make your code work nicely with both mypy and Python.

That said, it would probably be a good idea for mypy to report an error in cases like this, since it seems to be a common tripup. I found a pre-existing issue for it here, but it doesn't seem like anybody has started working on this yet.

@ddfisher ddfisher added this to the Questions milestone Aug 12, 2016
@gvanrossum
Copy link
Member

(Since this question was answered and there's no bug here, shouldn't we just close it?)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants