28

Why does it say that it can not find my class? Why should I create another class with the same name in order to make make it not complain?

from typing import Dict


class WeekDay:

    def __init__(self, day_number, day_name):
        self.day_name = day_name
        self.day_number = day_number

    @staticmethod
    def get_week_days() -> Dict[str, WeekDay]:  # WeekDay unresolved reference error
        weekdays = {
            "monday": WeekDay(1, "Monday"),
            "tuesday": WeekDay(2, "Tuesday"),
            "wednesday": WeekDay(3, "Wednesday"),
            "thursday": WeekDay(4, "Thursday"),
            "friday": WeekDay(5, "Friday"),
            "saturday": WeekDay(6, "Saturday"),
            "sunday": WeekDay(7, "Sunday")
        }
        return weekdays
Morse
  • 8,258
  • 7
  • 39
  • 64
Laimonas Sutkus
  • 3,247
  • 2
  • 26
  • 47
  • 1
    https://www.python.org/dev/peps/pep-0484/#forward-references – Ashwini Chaudhary Mar 20 '18 at 19:43
  • Duplicate of [How do I specify that the return type of a method is the same as the class itself?](https://stackoverflow.com/questions/33533148/how-do-i-specify-that-the-return-type-of-a-method-is-the-same-as-the-class-itsel) – Georgy Nov 07 '19 at 08:53

3 Answers3

38

From docs (Section Forward references)

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.

so in order to solve that just wrap the type with quotes, like this:

from typing import Dict


class WeekDay:
    def __init__(self, day_number, day_name):
        self.day_name = day_name
        self.day_number = day_number

    @staticmethod
    def get_week_days() -> Dict[str, 'WeekDay']:  # quote WeekDay 
        weekdays = {
            "monday": WeekDay(1, "Monday"),
            "tuesday": WeekDay(2, "Tuesday"),
            "wednesday": WeekDay(3, "Wednesday"),
            "thursday": WeekDay(4, "Thursday"),
            "friday": WeekDay(5, "Friday"),
            "saturday": WeekDay(6, "Saturday"),
            "sunday": WeekDay(7, "Sunday")
        }

        return weekdays
leandro
  • 496
  • 3
  • 6
15

From Python3.7, you can use: from __future__ import annotations

Jboulery
  • 238
  • 2
  • 9
0

you cannot reference a class from its own definition

class A:
    def foo(self):
        pass

    bar = A.foo

this will raise the following error:

Traceback (most recent call last):
    class A:
  File "/home/shmulik/so/ans.py", line 28, in A
    bar = A.foo
NameError: name 'A' is not defined

as a workaround this issue, PEP484 - Type Hints (thanks to @ashwini-chaudhary for the comment) allows to write the class definition as a string.

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.

so we can for example write:

class A:
    def foo(self, x: 'A'):
        pass

and this class will be interpreted happily by python.

Side Note

so hey you mentioned on the first example that we cannot reference class from its definition, so why this code works?

class A:
    def foo(self):
        A.bar()

    @staticmethod
    def bar():
        print(42)


A().foo()

this code works as the python interpreter skips the body of the method definition of foo() during the definition of class A, and only on the last line, when foo() is called (and class A is defined), the python interpreter executes the body of foo() and calling A.bar().

ShmulikA
  • 3,468
  • 3
  • 25
  • 40