首页 > 编程问答 >如何在没有元类冲突的情况下将泛型类型与 PyQt 子类一起使用?

如何在没有元类冲突的情况下将泛型类型与 PyQt 子类一起使用?

时间:2024-07-30 13:55:07浏览次数:12  
标签:python pyqt5 python-typing pyside2 metaclass

我已经尝试过使用 sip 包装类型,并且当使用 abc.ABCMeta 进行子类化时效果很好。 abc.ABC 但它不适用于

class QABCMeta(wrappertype, ABCMeta):
    pass

class WidgetBase(QWidget, metaclass=QABCMeta):
    ...

class InterfaceWidget(WidgetBase, ABC):
    ...

class MainWidget(InterfaceWidget):
    ...

typing.Generic 它提出了:

class QGenericMeta(wrappertype, GenericMeta):
    pass

class WidgetBase(QWidget, Generic[T], metaclass=QGenericMeta):
    ...

class GenericWidget(WidgetBase[float]):
    ...

我希望它使用像往常一样通用子类:

line 980, in __new__
    self if not origin else origin._gorg)
TypeError: can't apply this __setattr__ to sip.wrappertype object

但是

class TableBase(QTableWidget, Generic[T]):
    @abstractmethod
    def raw_item(self, row: int) -> T:
        ...
    def data(self) -> Iterator[T]:
        yield from (self.raw_item(row) for row in range(self.rowCount()))

class MainTable(TableBase[float]):
    def raw_item(self, row: int) -> float:
        return float(self.item(row, 1).text())  # implementation

table = MainTable()
for data in table.data():
    data: float

仍然是 data 当没有继承 Any 时。 Generic[T] 可以用PEP 560解决进行类型检查吗?

Can it solved with PEP 560 to do type checking?


你碰到的问题是因为 typing.Generic 使用了元类来修改类的行为,并支持泛型类型。而 PyQt 使用 sip.wrappertype 来包装 C++ 类,这两种机制之间存在冲突。

以下是一种解决方法,可以在不使用元类的情况下将泛型类型与 PyQt 子类一起使用,并利用 PEP 560 进行类型检查:

from typing import TypeVar, Generic, Iterator, List
from PyQt5.QtWidgets import QWidget, QTableWidget

T = TypeVar('T')

class WidgetBase(QWidget):
    """基础 Widget 类,不使用泛型"""
    pass

class TableBase(QTableWidget, Generic[T]):
    def raw_item(self, row: int) -> T:
        raise NotImplementedError

    def data(self) -> Iterator[T]:
        for row in range(self.rowCount()):
            yield self.raw_item(row)

class FloatTable(TableBase[float]):
    def raw_item(self, row: int) -> float:
        return float(self.item(row, 1).text())

class StringTable(TableBase[str]):
    def raw_item(self, row: int) -> str:
        return self.item(row, 0).text()

# 使用示例
float_table = FloatTable()
for data in float_table.data():
    print(f"Data: {data}, Type: {type(data)}")  # data 的类型为 float

string_table = StringTable()
for data in string_table.data():
    print(f"Data: {data}, Type: {type(data)}")  # data 的类型为 str

解释:

  1. 不使用元类: 我们不再尝试创建自定义元类来组合 sip.wrappertype typing.Generic
  2. 直接继承 Generic : TableBase 直接继承 typing.Generic[T] ,从而获得泛型支持。
  3. 类型提示: 使用类型提示 ( -> T ) 来指定 raw_item data 方法的返回类型。
  4. 具体实现类: 创建具体的子类,如 FloatTable StringTable ,并实现 raw_item 方法以返回特定类型的数据。

优点:

  • 避免了元类冲突。
  • 代码更简洁易懂。
  • PEP 560 仍然可以对类型进行检查,因为我们使用了类型提示。

缺点:

  • WidgetBase 类本身不能是泛型的。

这种方法提供了一种更简单的方式来使用泛型类型和 PyQt,同时仍然可以利用类型提示进行类型检查。

标签:python,pyqt5,python-typing,pyside2,metaclass
From: 54635205

相关文章

  • PIL 和 python 静态类型
    我有一个函数参数,它可以接受图像的多种类型:defsomefunc(img:Union[np.array,Image,Path,str]):PILImage在这种情况下抛出以下异常:TypeError:Union[arg,...]:eachargmustbeatype.Got<module'PIL.Image'from...进一步检查图像对象后这才有......
  • 学会用Python爬取小说网站,想看什么就爬什么,广告也不用看了~
    今天以爬取笔趣阁小说网站为例,练习Python爬虫技术。通过这个爬虫,可以完成批量爬取一本小说的所有章节,并将所有章节内容按顺序保存到一个txt文档内,下面我们就开始吧。首先,百度搜索“笔趣阁”,发现有很多网站都叫笔趣阁。我们可以随便挑选一个网站尝试,本文我以‘https://......
  • 计算机毕业设计django+vue《Python数据分析》的教学系统【开题+论文+程序】
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容研究背景在当今数字化时代,数据分析已成为各行各业不可或缺的技能之一,而Python作为数据分析领域的首选语言,其重要性日益凸显。然而,传统的教学模式在......
  • 如何将多个变量分配给 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......
  • 从零开始的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调试没有反应......