首页 > 编程问答 >如何使用支持简单类型和属性的字段声明协议?

如何使用支持简单类型和属性的字段声明协议?

时间:2024-07-30 13:15:33浏览次数:10  
标签:python python-typing mypy pyright

(相关但不重复: 如何注释可以实现为属性的属性?

我想创建一个 Protocol ,其中字段可以通过简单类型和财产。例如:

class P(Protocol):
    v: int


@dataclass
class Foo(P):
    v: int


class Bar(P):
    @property
    def v(self) -> int: # ERROR
        return

但是上面的代码没有类型检查。我应该如何解决它?

注意:我想解决这个问题而不重写 Foo Bar ,因为 Foo Bar 不是我实现的。

根据 this问题 下面的代码不是解决方案,因为只读 property 和简单成员具有细微的不同语义。

class P(Protocol):
    @property
    def v(self) -> int: # declare as property
        ...

Pyright 否认这一点 Protocol 由于差异。


很遗憾,你不能直接用 Protocol 来强制要求一个字段可以是简单类型或属性。这是因为 Python 的类型提示系统目前没有办法表达这种特定的约束。

问题根源:

  • 协议和结构类型: Python 的协议是基于结构子类型的,这意味着它们只关心属性的存在和类型,而不关心属性是如何实现的(简单属性或 property )。
  • 属性的双重性: property 在 Python 中既可以作为 getter 方法,也可以作为属性访问。这种双重性使得类型检查器难以在不了解具体实现的情况下,确定一个 property 是否等同于一个简单属性。

可能的解决方案:

  1. 使用抽象基类 (ABC):

你可以使用抽象基类和抽象方法来强制实现,但正如你所说,你想要避免修改 Foo Bar 的定义。

  1. 运行时类型检查:

你可以在 P 的方法中进行运行时检查,确保 v 属性存在并返回正确的类型。但这不会提供静态类型检查的好处。

```python from typing import Protocol

class P(Protocol): @property def v(self) -> int: ...

def some_function(obj: P): if not hasattr(obj, 'v') or not isinstance(getattr(obj, 'v', None), int): raise TypeError("Object does not conform to protocol 'P'") # ... rest of the code ... ```

  1. 自定义类型提示:

你可以创建自定义的类型提示来更准确地描述你的需求,但这需要更复杂的类型系统扩展,例如使用 mypy 插件。

结论:

目前,没有完美的解决方案可以在不修改 Foo Bar 的情况下,用 Protocol 来强制要求一个字段可以是简单类型或属性。你可以根据你的具体需求和项目的复杂度选择最合适的方案。

标签:python,python-typing,mypy,pyright
From: 68325221

相关文章

  • 如何将多个变量分配给 python 函数中的单个参数?
    我正在尝试编写一个程序,如果可能的话,它需要一个三项式并对其进行因式分解。每当用户输入A、B和C时,三项式应该通过Factor(product,summation)函数获取,但我似乎无法弄清楚如何将A和C分配给乘积arg,将B分配给我尝试在函数外部声明不同的变量,product=(a*c)和summati......
  • python - 从文本生成音乐
    请给我一些建议为了解释一下,我输入“深度睡眠的睡眠音乐”,它将返回一个wav文件:https://www.youtube.com/watch?v=1wAdQhFJy54或者我给出一个wav文件,它会返回相同的现在这是我尝试过的:https://github.com/facebookresearch/audiocraft......
  • 当 functools.wraps() 用于泛型函数时,Mypy 1.10 报告错误
    TLDR;我有一个装饰器:更改函数签名包装的函数使用一些泛型类型参数除了我想使用的签名funtools.wraps以保留其余部分信息。有什么办法可以在不抱怨的情况下实现这一目标吗?mypy更多背景一个最小的工作示例如下所示:这......
  • 从零开始的Python开发日记(7):短信验证功能开发流程
    短信验证功能开发流程在开发一个包含登录、注册以及短信验证的功能时,你需要遵循一个系统的开发流程。以下是实现这一功能的基本步骤,包括所需的技术和代码示例。1.环境配置首先,确保你的开发环境已经配置好,并安装了必要的库和工具。pipinstallfastapiuvicornsqlalche......
  • 【Python数值分析】革命:引领【数学建模】新时代的插值与拟合前沿技术
    目录​编辑第一部分:插值的基本原理及应用1.插值的基本原理1.1插值多项式1.2拉格朗日插值 1.3牛顿插值 1.4样条插值2.插值的Python实现2.1使用NumPy进行插值2.2使用SciPy进行插值2.2.1一维插值​编辑2.2.2二维插值3.插值的应用场景3.1数据平......
  • 在家用电脑上设置 Python 和 Jupyter,尝试打开 Jupyter 笔记本并显示错误,无法获取
    我有最新的Python版本3.12.4和以下版本的Jupyter:SelectedJupytercorepackages...IPython:8.26.0ipykernel:6.29.5ipywidgets:notinstalledjupyter_client:8.6.2jupyter_core:5.7.2jupyter_server:2.14.2jupyterlab......
  • Python - Reloading a module
    Eachmoduleisloadedintomemoryonlyonceduringaninterpretersessionorduringaprogramrun,regardlessofthenumberoftimesitisimportedintoaprogram.Ifmultipleimportsoccur,themodule’scodewillnotbeexecutedagainandagain.Suppose......
  • vscode python 3.7 pylance debugpy 插件 vsix
    可能报错  crashed5timesinthelast3minutes.Theserverwillnotberestarted.  ---pylance 可能报错  cannotreadpropertiesofundefinedreadingresolveEnvironment   --- debugger可能      vscodepython3.7调试没有反应......
  • Python获取秒级时间戳与毫秒级时间戳的方法[通俗易懂]
    参考资料:https://cloud.tencent.com/developer/article/21581481、获取秒级时间戳与毫秒级时间戳、微秒级时间戳代码语言:javascript复制importtimeimportdatetimet=time.time()print(t)#原始时间数据print(int(t))......
  • CEFPython
    在Tkinter界面中直接嵌入Selenium的浏览器视图并不是一件直接的事情,因为Selenium本身并不提供图形界面嵌入的功能。Selenium主要用于自动化web浏览器,但它并不直接控制浏览器窗口的显示方式,而是依赖于WebDriver来与浏览器交互。然而,你可以使用一些替代方案来在Tkinter应用中模拟或......