Make anonymous classes and functions (with name _
) reassignable with any type
#3620
Replies: 5 comments 5 replies
-
Pyright distinguishes between symbols with declared types and symbols without declared types. Type declarations come from statements like It applies the following rules:
I have already added an exception to rule 2 for you if the symbol is named Now you are asking for a special case to rule 1 if the symbol is named I'm more inclined at this point to remove the special case for 2 that I previously added for you. I'm regretting making that change at this point. I think the correct workaround in your code is to use a name other than def my_function() -> None: ...
x = my_function
...
x = something_else |
Beta Was this translation helpful? Give feedback.
-
I'm fully supporting you if you are going to revert that change, as current rules about But I still don't think naming a fire-and-forget function is a good idea when its functionality can get fully explained elsewhere. For example -- def __init__(self) -> None:
@self.view.ok_button.clicked.connect
def handle_click_on_ok_button() -> None:
... against def __init__(self) -> None:
@self.view.ok_button.clicked.connect
def _() -> None:
... I prefer the latter version, because it will cause less pain when |
Beta Was this translation helpful? Give feedback.
-
Ah, I almost forgot that the normal version should be def __init__(self) -> None:
def handle_click_on_ok_button() -> None:
...
self.view.ok_button.clicked.connect(handle_click_on_click_button) or even def __init__(self) -> None:
self.view.ok_button.clicked.connect(self.handle_click_on_click_button)
def handle_click_on_ok_button(self) -> None:
... which are both less readable to me, as the event and the handler either are declared in a reversed order in occurence or get separated away. |
Beta Was this translation helpful? Give feedback.
-
If Pyright is not going to support arbitrary assignment for Then it can be said that |
Beta Was this translation helpful? Give feedback.
-
I've found a simpler work-around -- from __future__ import annotations
from typing import Any, Callable, TypeVar
_T = TypeVar("_T")
def retry_until_success(action: Callable[[], _T], /) -> _T:
while True:
try:
return action()
except:
continue
@retry_until_success
def _() -> str:
return ""
str_value = _ # Implicitly typed as 'str' which is expected. Hooray.
def discardable() -> int:
return 0
_ = discardable() # Typed as 'Any' instead of 'int', but it should be ignored nevertheless.
@retry_until_success
def _() -> int:
return 0
int_value: int = _ # No problem with an explicit type.
value_of_wrong_type: str = _ # Found type issue here, as expected.
# Suppressing warnings of assigning incompatible types to '_'.
_: Any The last line is what accomplishes magic. It overwrites the declared type of '_' as This work-around is coupling tightly with internal logic of pyright, but the result is exactly what I need. As long as you have no recent plans of changing how '_'s and declared types work, I will keep on this way. |
Beta Was this translation helpful? Give feedback.
-
Currently, this is allowed --
And this is also allowed --
But this is NOT allowed --
I don't think the logic behind is making sense.
In real code, I have several occations that I like to deploy an anonymous function (e.g. a Qt signal connection) and it conflicts with some anonymous values elsewhere, and anonymous values are not that rare because of "reportUnusedCallResult".
Beta Was this translation helpful? Give feedback.
All reactions