python / python/typing

When making a dynamic member descriptor that can also behave as a Wrapper Why Does Self Not get deleted from ParamSpec?

未关闭
#2,060 2 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

topic: other
主要语言
Python
星标
1.8k
派生
302
平均合并
23 小时
30 天内合并 PR
8

描述

I've bumped into one of the largest and most frustrating puzzles I've ever encountered but I wanted to understand what the thought process behind ParamSpec was for class functions because I think if Self was ignored from ParamSpec dynamically based on weather or not a class function was in use it would not only fix lru_cache but it would also allow async_lru library to be type-hinted as well. No matter what I do, nothing works. I've tried multiple search engines to no avail so I go here now as my final resort since it's not a mypy problem because pyright is also plagued by the same rules.


from typing import ParamSpec, TypeVar, Callable, Protocol

P = ParamSpec("P")
T = TypeVar("T")
I = TypeVar("I")

# I made a class of my own for callable to illistrate the problem at hand.
class CallableProto(Protocol[P, T]):
    def __call__(self, *args:P.args, **kwds:P.kwargs) -> T:...

class RespectingCallable(CallableProto[P, T]):
    def __init__(self, func:Callable[P, T]):
        self.func = func
    # My question is Why does Self inside of a class function still get preserved in 
    # ParamSpec when it's just a class function? Shouldn't it get removed?
    # Also Concatenate doesn't work I've tried that one already with no success...
    def __get__(self, instance:I, obj:type[I]) -> CallableProto[P, T]:...

class A:
    def __init__(self) -> None:
        pass
    @RespectingCallable
    def coro(self, val:int) -> str:
        return f"{val}"

g = A()
# It appears as (self: A, val: int) -> str instead of (val: int) -> str 
# (mypy and pyright are also both are plagued by these rules)
g.coro(1)

@RespectingCallable
def func(i:int) -> str:
    return f"{i}"
# Somehow this is fine?
func(1)

贡献指南

这个仓库没有索引到贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

调研方向

从提供的 Python 示例开始,检查 ParamSpec、Self、Concatenate 和 descriptor binding 的规则。比较 mypy 和 pyright 如何解释该示例,然后确定预期结果是否需要澄清规范或修改文档;当行为和预期注解得到明确决定时,即表示完成。

由索引模型根据 Issue 内容生成。

评估

技术栈
python
领域
developer-experience
Issue 类型
文档
难度
5/5
预计耗时
一周以上
活跃度
停滞
描述清晰度
需要澄清
新手友好度
25/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。