从父类继承所有 __init__ 参数的类型提示

问题描述 投票:0回答:1

注意:我的问题可能是重复的或不必要的,或者我什至可能一直都是错的。但我无法搜索它,因为它是一个兔子洞,我需要有人的建议。

嗨,这是我第一次使用其他模块和类的继承。因此,每当我创建一个继承自定义良好的类(如

tkinter.Frame
pandas.Dataframe
sqlite3.Connection
)的子类时,我都会获得带有类型提示的所有参数(我正在使用
vscode
并按
tab
它会自动完成
def __init_
并生成它们
)。但类型命中总是被破坏,尤其是省略号
...

我知道它可以通过导入类型提示来解决 如果存在

TypeVar
TypeAlias
,或者完全删除它们,甚至删除所有我并不真正需要的额外参数请使用
*args, **kwargs
来代替。

但我不想这样

我希望我的子类以与超类相同的方式运行,并且仅扩展其功能。我发现带有类型提示的明确参数可以更好地使用类及其功能。

示例:

import tkinter
from tkinter import ttk

class MyFrame(ttk.Frame):
    def __init__(self, master: tkinter.Misc | None = ..., *, border: tkinter._ScreenUnits = ...,
        borderwidth: tkinter._ScreenUnits = ..., class_: str = ..., cursor: tkinter._Cursor = ...,
        height: tkinter._ScreenUnits = ..., name: str = ..., padding: _Padding = ...,
        relief: tkinter._Relief = ..., style: str = ..., takefocus: tkinter._TakeFocusValue = ...,
        width: tkinter._ScreenUnits = ...) -> None:
    
        super().__init__(master, border, borderwidth, class_, cursor, height, name,
                        padding, relief, style, takefocus, width)

在此示例中,所有省略号都会导致问题,并且某些类型提示不会显示。例如

_Padding

并用此类运行正常代码会引发此错误:

AttributeError: module 'tkinter' has no attribute '_ScreenUnits'
或者
AttributeError: module 'tkinter' has no attribute '_Cursor'

如果我决定删除所有类型提示,我会因为省略号而收到此错误。

TypeError: can only concatenate str (not "ellipsis") to str
意味着
...
正在作为
str
值传递

正如我所说,我知道我可以用其他方式修复它,但是有没有一种简单的方法可以从超类继承类型提示,而不破坏我的代码?

还是我做错了什么??

python oop inheritance type-hinting init
1个回答
0
投票

这应该对你有用:)

import tkinter
from tkinter import ttk
from typing import ParamSpec, TypeVar, Callable

_P = ParamSpec("_P")
_T = TypeVar("_T")

def inherit_signature_from(
    _to: Callable[_P, _T]
) -> Callable[[Callable[..., _T]], Callable[_P, _T]]:
    """Set the signature checked by pyright/vscode to the signature of another function."""
    return lambda x: x  # type: ignore


class MyFrame(ttk.Frame):
    @inherit_signature_from(ttk.Frame.__init__)
    def __init__(self, *args, **kwargs) -> None:
        # do stuff?
        super().__init__(*args, **kwargs)

VSCode 现在会认为

MyFrame.__init__
ttk.Frame.__init__
具有相同的签名/参数,并相应地检查它们。

© www.soinside.com 2019 - 2024. All rights reserved.