python类型标注self

发布时间 2023-08-16 16:37:53作者: faf4r

起因

假设有如下代码,我想标注类方法的返回值为自己本身

class Queue:
    def __init__(self):
        self.items = []

    def enqueue(self, item) -> Queue:
        self.items.append(item)
        return self

Queue来标注返回值类型,但是呢,运行时Python会报错

Traceback (most recent call last):
  ...
NameError: name 'Queue' is not defined

这说明,自定义的类里不能用该类名来作为类型标注

解决方法一:用typing的Self(注意大写)--首选

try:
    from typing import Self             # python3.11只后
except:
    from typing_extensions import Self  # Python3.11以前
    
class Queue:
    def __init__(self):
        self.items = []

    def enqueue(self, item) -> Self:  # 使用Self替换Queue
        self.items.append(item)
        return self

这样就没有问题了,而且Self更能体现返回自身

当然,Self代表了自定义的这个类,不是说只有return self才能用它

这个方法作为首选就是因为其它方法或多或少有点问题

解决方法二:用typing的TypeVar(注意大写)

from typing import TypeVar  # 或从typing_extensions导入

# 实例化一个TypeVar并绑定类型
TQueue = TypeVar('TQueue', bound='Queue')  # 第一个参数name随意,bound绑定我们的类
    
class Queue:
    def __init__(self):
        self.items = []

    def enqueue(self, item) -> TQueue:  # 使用实例化的TQueue
        self.items.append(item)
        return self

该方法和前面相比

  • 要自己实例化一个类,麻烦
  • 有些IDE可能解析不了

解决方法三:用内置__future__模块

from __future__ import annotations  # 注意要写在代码最前面来配置解析规则

class Queue:
    def __init__(self):
        self.items = []

    def enqueue(self, item) -> Queue:  # 可以直接使用自定义的类
        self.items.append(item)
        return self

这个看似最好最方便,但是如果是继承类的话,它会识别不了,而识别成基类,就会有问题,所以反而不推荐这个方法

原文链接:https://realpython.com/python-type-self/