不使用isinstance时,如何满足类型检查器并判断实例子类归属?
不用isinstance,基于Protocol实现类型安全的子类判断与方法调用
要解决你遇到的Pylance类型检查报错问题,核心是用**类型守卫(Type Guard)**给类型检查器提供足够的类型信息,让它能识别is_file()判断后的实例类型,全程无需依赖isinstance。
完整代码实现
from typing import Protocol, TypeGuard, Self # 基础协议:所有条目都必须实现is_file方法 class Entry(Protocol): def is_file(self) -> bool: ... # 文件协议:继承Entry,新增get_size方法 class File(Entry, Protocol): def is_file(self) -> TypeGuard[Self]: return True def get_size(self) -> int: ... # 文件夹协议:继承Entry,新增get_children方法 class Folder(Entry, Protocol): def is_file(self) -> TypeGuard[Self]: return False def get_children(self) -> list[Entry]: ... # 具体实现类(符合协议即可,无需显式继承) class LocalFile: def is_file(self) -> bool: return True def get_size(self) -> int: return 1024 class LocalFolder: def is_file(self) -> bool: return False def get_children(self) -> list[Entry]: return [] def do_something(entry: Entry) -> None: if entry.is_file(): # Pylance现在能识别entry是File类型,可安全调用get_size print(f"文件大小:{entry.get_size()}") else: # 自动推断为Folder类型,可调用get_children print(f"文件夹包含{len(entry.get_children())}个条目") # 测试代码 do_something(LocalFile()) do_something(LocalFolder())
关键说明
类型守卫的作用:
把File和Folder中的is_file方法返回类型标注为TypeGuard[Self],相当于告诉类型检查器:- 当
is_file()返回True时,当前实例肯定是File类型 - 当返回
False时,当前实例肯定是Folder类型
这样Pylance就能在分支中正确识别实例类型,不会再报“无get_size方法”的错误。
- 当
避免isinstance的优势:
这种方式基于鸭子类型的协议实现,只要类符合协议的方法签名,就可以被当作对应的类型处理,不需要显式继承类,代码耦合度更低,扩展性更强。另一种实现方式(独立类型守卫函数):
如果不想修改协议中的方法返回类型,也可以写一个独立的类型守卫函数:def is_file(entry: Entry) -> TypeGuard[File]: return entry.is_file() def do_something(entry: Entry) -> None: if is_file(entry): print(f"文件大小:{entry.get_size()}") else: print(f"文件夹包含{len(entry.get_children())}个条目")效果和上面的实现完全一致,选择哪种看你的代码风格偏好。
内容的提问来源于stack exchange,提问作者Shahar Nacht
相关产品推荐
相关产品推荐

