Python 参数注释未解决的引用问题

28

为什么它说找不到我的类?为什么我需要创建另一个同名类才能让它不再抱怨?

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

1
https://www.python.org/dev/peps/pep-0484/#forward-references - Ashwini Chaudhary
如何指定方法的返回类型与类本身相同?的重复问题链接:https://dev59.com/3lwX5IYBdhLWcg3wrA96 - Georgy
3个回答

38

来自文档 (正向引用章节)

当类型提示包含尚未定义的名称时,该定义可以作为字符串字面值表示,以便稍后解析。

常见情况是定义容器类时,在一些方法的签名中出现了正在定义的类。

因此,为了解决这个问题,只需用引号将类型包装起来,例如:

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

15
从Python3.7开始,您可以使用: from __future__ import annotations

那是做什么用的? - Toskan
1
在这个例子中,你可以轻松地使用 WeekDay 类而不用担心导入问题。 - Jboulery

0

你不能在类的定义中引用它自己

class A:
    def foo(self):
        pass

    bar = A.foo

这将引发以下错误:

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

作为解决此问题的方法,PEP484 - Type Hints(感谢@ashwini-chaudhary的评论)允许将类定义编写为字符串。

当类型提示包含尚未定义的名称时,可以将该定义表示为字符串文字,以便稍后解析。

因此,我们可以例如编写:
class A:
    def foo(self, x: 'A'):
        pass

这个类将被Python愉快地解释。

旁注

嘿,你在第一个例子中提到我们不能从定义中引用类,那么为什么这段代码可以工作呢?

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

    @staticmethod
    def bar():
        print(42)


A().foo()

这段代码正常运行是因为在定义类 A 时,Python 解释器会跳过方法 foo() 的函数体,只有在最后一行调用 foo() (此时类 A 已经被定义)时,Python 解释器才会执行 foo() 的函数体并调用 A.bar()


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接