Allow Self or Self-like type arguments for generics
Chưa có ai nhận issue này.
- Ngôn ngữ chính
- Python
- Star
- 1.8k
- Fork
- 302
- Merge trung bình
- 23 giờ
- Pull request đã merge (30 ngày)
- 8
Mô tả
from contextlib import AbstractContextManager
class ManagerA(AbstractContextManager):
def __init__(self, x: int) -> None:
self._x = x
def __enter__(self) -> int:
return self._x
This can raise type check errors because AbstractContextManager is a generic type, and this code omits the type argument. Fair enough, and easy to fix:
from contextlib import AbstractContextManager
class ManagerA(AbstractContextManager[int]):
def __init__(self, x: int) -> None:
self._x = x
def __enter__(self) -> int:
return self._x
But what if we are not overriding the __enter__ method? Consider this example:
from contextlib import AbstractContextManager
class ManagerB(AbstractContextManager):
def __init__(self, x: int) -> None:
self._x = x
# Other methods are defined, but __enter__ is not overridden
In this case, there is no great way to accurate type annotate it in order to reflect the fact that the __enter__ method always returns the object that it was called on (which is the default implementation of the __enter__ method in AbstractContextManager.
If we were willing to mark this class as final, then we could annotate it as:
class ManagerB(AbstractContextManager["ManagerB"]):
And that would work. But if we want to be able to subclass it, then this would no longer be accurate. Consider:
from contextlib import AbstractContextManager
from types import TracebackType
from typing import Type
class ManagerB(AbstractContextManager["ManagerB"]):
def __init__(self, x: int) -> None:
self._x = x
# Other methods are defined, but __enter__ is not overridden
def __exit__(
self, exc_type: Type[BaseException] | None,
exc_val: BaseException | None,
exc_tb: TracebackType | None) -> bool | None:
return None
class SubManager(ManagerB):
def harf(self) -> None:
print("harf")
with SubManager(1) as subman:
subman.harf()
This runs fine, but the type checker will rightly complain. The annotations indicate that subman should be of type ManagerB, but ManagerB has no harf attribute.
It feels like it would be appropriate to use:
class ManagerB(AbstractContextManager[Self]):
But Self is not allowed to be used in this context.
The feature I would like to see is some way to accurately handle non-final subclasses of AbstractContextManager that do not overwrite the __enter__ method (or that overwrite it but still return self).
Obviously this issue applies generally to generics -- this is just an obvious example since the Python implementation of that class makes it impossible to type annotate many of its subclasses. But ideally any solution would apply generally to generics -- essentially giving a way to use Self (or something Self-like) as the type argument for a generic.
Hướng dẫn đóng góp
Chưa lập chỉ mục được hướng dẫn đóng góp cho kho mã nguồn này
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Hướng nghiên cứu
Bắt đầu với các ví dụ về AbstractContextManager và hạn chế đã nêu về việc sử dụng Self làm đối số kiểu generic. So sánh hành vi mong muốn đối với ManagerB và SubManager với các quy tắc hiện tại dành cho Self, tính kế thừa và các đối số kiểu generic. Được xem là hoàn thành khi một giải pháp tổng quát suy luận chính xác lớp con cụ thể, đồng thời duy trì hành vi chính xác đối với các phương thức enter được ghi đè hoặc kế thừa.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Đánh giá
- Công nghệ
- python
- Lĩnh vực
- tooling
- Loại issue
- Tính năng
- Độ khó
- 5/5
- Thời gian dự kiến
- Hơn một tuần
- Mức độ hoạt động
- Ít trao đổi
- Độ rõ ràng
- Khá rõ ràng
- Mức phù hợp với người mới
- 35/100