-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Is there a way annotate types based on class attributes? #4109
Comments
(Aside: please you mark the line where the error occurs with a comment.)
If you want to parameterize a class you must use a generic parameter; your
approach of using a class attribute doesn't work.
…On Oct 12, 2017 7:10 PM, "Leandro Lima" ***@***.***> wrote:
Take this snippet, for example:
from typing import Iterable, Iterator, Type, TypeVar
T = TypeVar('T')
class GenericNumberIterable(Iterable[T]):
itemtype: Type[T]
def __iter__(self) -> Iterator[T]:
itemtype = self.itemtype
yield from (itemtype(x) for x in range(10))
class FloatIterable(GenericNumberIterable, Iterable[float]):
itemtype = float
class IntIterable(GenericNumberIterable, Iterable[int]):
itemtype = int
An attempt with this with mypy yields:
$ mypy scratch_21.py
scratch_21.py:11: error: Too many arguments for "object"
And further attempts to have itemtype recognized as a placeholder for a
class only generates other errors, for exemple:
from typing import Iterable, Iterator, Type, List
class GenericNumberIterable(Iterable[float]):
itemtype: Type[float]
def __iter__(self) -> Iterator[float]:
itemtype = self.itemtype
yield from (itemtype(x) for x in range(10))
class FloatIterable(GenericNumberIterable, Iterable[float]):
itemtype = float
class IntIterable(GenericNumberIterable, Iterable[int]):
itemtype = int
x: List[int] = list(IntIterable())
Leads mypy to return:
$ mypy scratch_21.py
scratch_21.py:19: error: Argument 1 to "list" has incompatible type "IntIterable"; expected "Iterable[int]"
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#4109>, or mute the thread
<https://github.com/notifications/unsubscribe-auth/ACwrMh143kpJa4YhnMyBnGM_cAxgn-t0ks5srsahgaJpZM4P34M7>
.
|
Do you mean like this?
This one passes, though the |
Can't you write Honestly I'm not sure what you're trying to do, since mypy doesn't really support a numeric tower in a reasonable way. If your real-world example doesn't have to do with numbers then using float/int here is just a distraction. And indeed the typevar declaration probably should use something like |
Yeah, it does have to do with numbers. I have numeric types that enforce contracts (test if value is valid on
And I have sequence types for some of these numeric types:
The sequence types have several useful methods, allowing me to do element wise operations (like sum/multiply/divide) between sequences and also several useful class methods, facilitating the construction of these sequences (like building a sequence out of the number of elements, an initial value and a growth rate). The implementation I'm currently using is akin to the first snippet, but I'm working towards making the code verifiable by mypy, so I'm trying to find a solution that both offer the same interface as the current implementation and is verifiable. Based on our discussion here, this was my lastest attempt:
But this also generates the following errors (also marked in the code above):
|
There are two points that I can recommend here:
|
I didn't know I don't really know what I should bind |
But why do you need class NumberSequence(Sequence[S]):
...
@overload
def __getitem__(self, index: int) -> S: ...
@overload
def __getitem__(self, index: slice) -> 'NumberSequence[S]': ...
... |
@ilevkivskyi, 'cause I don't really wanna return NumberSequence[S], but one of it subtypes, which perform the contract checking. Is there a way for me to pull out the S value at runtime to type check the elements? One of my use cases is that I can get untrusted data from the user and do:
I'm subclassing NumberSequence[T] and defining a class attribute that points to the type each element should be converted to. This way, when I slice it, I don't wanna return an instance of NumberSequence, but one if its subtypes. Does that make sense? |
For this you can use self-types, but they don't work currently in generic classes, see #2354. |
@ilevkivskyi yeah... I did try self-types with no success. Is there an workaround? Maybe with a second type variable, like above? |
Looks like this thread is dead already. Should I close it? |
Sorry, due to some reasons I have not enough time to help you here, maybe someone else can give you advice. |
@ilevkivskyi No problem. I've learned a lot from your advices already -- big thanks for you and @gvanrossum. I asked what to do with the issue 'cause I'm not sure how questions issues are handled when they're considered answered. |
Let's close it. If you have more questions you can still add comments to the issue, or you can create a new one. Good luck! |
Take this snippet, for example:
An attempt with this with mypy yields:
And further attempts to have itemtype recognized as a placeholder for a class only generates other errors, for exemple:
Leads mypy to return:
The text was updated successfully, but these errors were encountered: