You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pylance中Union类型顺序违反交换律问题

问题分析:Protocol中Union类型顺序影响Pylance检查的原因

你遇到的问题并非Union类型交换律失效,而是Pylance对非标准类型注解写法(or)的特殊处理逻辑,以及对属性可变性的推断规则导致的:

问题本质

Python类型注解的标准Union写法是typing.Union或Python 3.10+的|运算符,而非or。Pylance对or做了兼容处理,但处理逻辑会受类型顺序影响:

  • 当property放在or左侧时,Pylance会将协议中的position推断为只读属性(因为property本质是描述符,通常对应只读的getter),此时Player类用@property实现的position完全符合只读要求。
  • 当Tuple[int, int]放在or左侧时,Pylance会将position推断为可写属性(因为普通Tuple属性支持直接赋值),而你的Player类的position是只读的@property(无setter),无法满足“可写”要求,因此触发类型不兼容错误。

正确解决方案

放弃or这种非标准写法,改用标准Union语法,并明确协议中属性的可变性:

方案1:明确标注为只读属性(推荐)

如果position只需要支持读取,直接在Protocol中用@property标注,这样不管实现类是用@property还是直接的Tuple属性,都能兼容:

from typing import Protocol, Tuple

class Moveable(Protocol):
    @property
    def position(self) -> Tuple[int, int]:
        ...

class Player:
    @property
    def position(self) -> Tuple[int, int]:
        return (0, 0)

entity: Moveable = Player()  # 无类型错误

方案2:使用标准Union并明确可变性

如果需要同时支持可读可写的Tuple属性和只读的property,改用标准Union语法即可消除顺序影响:

from typing import Protocol, Tuple, Union

class Moveable(Protocol):
    position: Union[property, Tuple[int, int]]

class Player:
    @property
    def position(self) -> Tuple[int, int]:
        return (0, 0)

entity: Moveable = Player()  # 标准Union写法不受顺序影响

总结

你看到的“交换律失效”是Pylance对非标准or写法的特殊处理导致的,改用标准Union语法后,类型顺序就不会再影响检查结果。同时,明确协议中属性的可变性(只读/可写),能让类型检查更准确。

内容的提问来源于stack exchange,提问作者Michael Moreno

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 11:40:30