Python中是否不允许将一个类的方法的参数的类型注解为该类型本身?

代码如下:

class A:
    def __init__(self,a:A):
        pass

Python 版本(Anaconda):Python 3.7.0 (default, Jun 28 2018, 08:04:48) [MSC v.1912 64 bit (AMD64)] on win32

这段代码运行时就会触发NameError:name 'A' is not defined异常。那么这个异常的引发是因为解释器本身的限制还是因为写法有误?我查阅官方文档(PEP 3107)后并未找到有关内容。毕竟这样的需求还是经常有的,比如一个容器类的元素应该可以是这个类的实例。谢谢!


Python中是否不允许将一个类的方法的参数的类型注解为该类型本身?

11 回复

对的,使用 a: ‘A’ 即可: 注解类型加单引号。


可以的,Python完全允许在类的方法中使用指向自身的类型注解,这被称为“前向引用”(Forward Reference)。从Python 3.7开始,你可以直接使用字符串字面量来注解尚未完全定义的类名。在Python 3.10及更高版本中,你还可以使用from __future__ import annotations来隐式地将所有注解存储为字符串,或者使用新的typing.Self类型(Python 3.11+),这是最清晰、最推荐的方式。

下面是一个代码示例,展示了三种主要方法:

# 方法1:使用字符串字面量进行前向引用 (Python 3.7+)
class Node:
    def set_next(self, other_node: 'Node') -> None:
        self.next = other_node

# 方法2:使用 __future__ import annotations (Python 3.7+)
from __future__ import annotations

class TreeNode:
    def connect_to(self, child: TreeNode) -> None:
        self.child = child

# 方法3:使用 typing.Self (Python 3.11+, 最推荐)
from typing import Self

class LinkedListNode:
    def link_to(self, target: Self) -> Self:
        self.next = target
        return self

核心解释: 当Python解释器在类定义体中首次遇到class Node:时,这个Node类对象本身还没有被创建完成。因此,如果你直接在方法注解中写other_node: Node,解释器会报错,因为它找不到名为Node的类型。上述三种方法都是解决这个“先有鸡还是先有蛋”问题的标准方案。

一句话总结:typing.Self(3.11+)或字符串字面量就能轻松解决。

#1 那这样的话您使用的 ide 会有代码提示吗?我用的 PyCharm 2018.3 似乎在接下来的编码中并不会提示我 a 是一个 A 类型的变量(比如输入 a.不会提示成员)

#1 不好意思打扰了,我刚刚的问题在于对 A 的内部类 B 进行注解的时候没有使用’A.B’,而是使用了’B’,最后请教一些单引号注释类型是在何处规定的呢?

目前是没有的

#4 python 里单引号和双引号没什么区别, 也有提示

是不是因为你这个例子里 A 也没什么其他方法, 所以没有提示…

因为官方都是这么用,我其实也没细究原始出处

from future import annotations
就可以了。
不默认支持是因为这个会 break 一些特殊的包。

https://www.python.org/dev/peps/pep-0563/

注解延迟求值,Python 4 的特性之一

回到顶部