Hacktoberfest 2026:维护者为十月标记出来的 issue,仍然开放、适合新手。 浏览 Hacktoberfest issue

Documenting specialisation rules

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

还没有人认领这个 Issue。

评估

难度
5/5
预计耗时
一周以上
新手友好度
35/100
Issue 类型
文档
描述清晰度
基本清楚
活跃度
停滞
技术栈
python
领域
documentation

调研方向

先阅读 PEP 718 和 PEP 696 的链接以及链接的 MyPy 和 Pyright 复现,然后比较示例中描述的特化行为。确定哪些规则已经达成共识,以及它们应归入 typing 文档的哪一部分。完成的标准是:这些规则(包括 new 情况)已结合相关示例记录下来,并且不再依赖尚未解决的解释。

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

描述

I wasn't aware there were discrepancies between type checkers about this. Coming from https://github.com/microsoft/pyright/issues/5830, PEP 718 will require documentation about specialisation for functions and PEP 696 requires documentation about whether methods should bind default type parameters for the class.

PEP 718 problems

from typing_extensions import assert_type

class Foo[T, U]:
    def bar(self): ...

class Baz[U](Foo[int, U]):
    ...

# sorry for using PEP 677 syntax but it's easier to follow
# also Unknown is implicit Any (borrowed from pyright)
assert_type(Foo.bar, (self: Foo[Unknown, Unknown]) -> None)
assert_type(Baz.bar, (self: Foo[int, Unknown]) -> None)
assert_type(Foo[str, str].bar, (self: Foo[str, str]) -> None)

Foo[str, int].bar(Foo[str, int]())  # fine
Foo[int, int].bar(Baz[int]())  # fine
Baz.bar(Foo[str, int]())  # should error as Self is bound to Baz not Foo
MyPy

MyPy currently shows methods not binding type parameters at all which is problematic as type parameters should be bound in the scope they are defined. This behaviour is also I think incorrect in allowing the final call to pass as it is ignoring the specialisation of the class.

Pyright

Pyright currently shows, it isn't binding U to Unknown.

PEP 696 problems

from typing_extensions import assert_type

class Spam[T=int]:
    def meth[U](self, another: U, other: T) -> U:
        ...

assert_type(Spam.meth, (self: Spam[int], another: U, other: int) -> U)
MyPy

MyPy currently shows and appears to be binding T's default as I thought it should (good mind reading skills Marc), however, it is still suffering from the problems proposed above and would ignore any prior specialisation.

Pyright

Pyright currently shows meth as being partially unknown which is what I opened the original issue about.

A __new__ issue (🥁) W.R.T. PEP 718

Say I have a generic __new__/__init__ method that uses parameters that aren't bound by the class.

class New[T]:
    def __new__[U](cls, arg: T, l: list[U], elem: U):
        self = super().__new__(cls)
        l.append(elem)

This may seem a bit contrived but it can come up where there's a mapping between types e.g. for registering types for serialisation.

How should this be specialisable? A couple of options:

  • New[T, U]() is fine:
    What about if it's added in init?
    • Class[ClassParams, ..., NewParams, ..., InitParams, ...]
    • Should order be lexicographical? I don't think there's a world in which this is practical
  • Manually call through the __new__ method yourself and __init__ can't add any new type parameters.

My preference would be manually constructing the class through __new__ because the other case seems full of edge cases and is a special case with no real gain.

Summary of my thoughts

class Summary0[T, U]:
    def bar(self): ...

class Summary0Sub[U](Summary0[int, U]):
    ...

# Summary0 should bind type parameters in the scope they were defined
Summary0.bar  # should warn about implicit Any
# A specialised Summary0 should modify the type of self in methods
Summary0[int, bool].bar  # `self` should be Summary0[int, bool]
Summary0Sub[bool].bar  # `self` should be Summary0Sub[bool]

class Summary1[T=int]:
    def meth(self) -> T: ...

# defaults should bind on method access if not specialised
assert_type(Summary1().meth(), int)
assert_type(Summary1[str]().meth(), str)

class Summary2[T]:
    def id[U](self, x: U) -> tuple[T, U]: ...

assert_type(Summary2[bool]().id[str]("hi"), tuple[bool, str])
Summary2.id[int, str]  # error expected 1 type param not 2


class Summary3[T]:
    def __new__[U](cls, arg: T, l: list[U], elem: U): ...

Summary3[int].__new__[complex](1, [], 1j)
Summary3[int, complex](1, [], 1j)  # errors because special cases aren't special enough to break the rules

Does anyone have any objections to this? Where is this best documented neither PEP really feels like the right place for all of this.

Would be nice to hear from the MyPy and Pyright teams on this.

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

贡献指南

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

从这里开始

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

python/typing 的其他 Issue

查看 python/typing 的全部 Issue

相似的 Issue

更多 Python Issue

把新 issue 发到你的邮箱

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