【发布时间】:2026-02-18 22:40:04
【问题描述】:
假设我们有Template method pattern 继承场景。我正在使用请求库的示例。
import abc
import json
import requests
from typing import Dict, Any
class Base(abc.ABC)
@abc.abstractmethod
def call(self, *args, **kwargs) -> requests.Response:
raise NotImplementedError
def safe_call(self, *args, **kwargs) -> Dict[str, Any]:
try:
response = self.call(*args, **kwargs)
response.raise_for_status()
return response.json()
except json.JSONDecodeError as je: ...
except requests.exceptions.ConnectionError as ce: ...
except requests.exceptions.Timeout as te: ...
except requests.exceptions.HTTPError as he: ...
except Exception as e: ...
return {"success": False}
class Derived(Base):
def call(self, url: str, json: Dict[str, Any], timeout: int, retries: int) -> requests.Response:
# actual logic for making the http call
response = requests.post(url, json=json, timeout=timeout, ...)
return response
将像这样使用
executor = Derived()
response = executor.safe_call(url='https://example.com', json={"key": "value"}, ...)
有没有办法将Derived.call 的签名附加到Derived.safe_call 以便现代IDE 自动完成和类型检查器工作?
因为这看起来很像装饰器模式,所以我尝试在__init__ 中使用functools.update_wrapper,但失败了
AttributeError: 'method' object has no attribute '__module__'
我确实有一些选择,但我找不到关于这个问题的任何建议
- 我可以在类完全构建之前通过元类路径来更改签名和文档字符串属性。但是,这可能不适用于 IDE。
- 我可以定义一个存根文件
.pyi并与主代码一起维护它。
class Derived(Base):
def safe_call(self, url: str, json: Dict[str, Any], timeout: int, retries: int) -> Dict[str, Any]: ...
-
彻底改变设计
-
(编辑:添加帖子第一个答案)(Ab)使用
@typing.overload
class Derived(Base):
@typing.overload
def safe_call(self, url: str, json: Dict[str, Any], timeout: int, retries: int) -> Dict[str, Any]:
...
def call(self, url: str, json: Dict[str, Any], timeout: int, retries: int) -> requests.Response:
# actual logic for making the http call
response = requests.post(url, json=json, timeout=timeout, ...)
return response
【问题讨论】:
标签: python python-typing