-
-
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
Descriptor as class attribute is misunderstood #4472
Comments
There's a way to make the type of from typing import Any, Generic, overload, Type, TypeVar
T = TypeVar('T')
class Descr(Generic[T]):
@overload
def __get__(self, obj: T, cls: Type[T]) -> int: pass
@overload
##def __get__(self, obj: None, cls: Type[T]) -> Type[T]: pass # What I originally wrote
def __get__(self, obj: None, cls: Type[T]) -> Descr[T]: pass # What it should be
def __get__(self, obj: Any, cls: Any) -> object: pass
name: str = 'booh'
class C:
a = Descr['C']()
reveal_type(C().a) # int
reveal_type(C.a) # Any
reveal_type(C.a.name) # Any I wish the last two revelations to be |
I think this is rather a bug in descriptor implementation. Probably there is just a missing special case in |
Descriptors are defined to also be called for class attribute requests. That was perhaps a mistake in the design of descriptors but that was ages ago. So technically we need the overload (and typically also the generics, alas). I wouldn't mind if we allowed omitting the overload and somehow ignored the descriptor for class attributes though -- I can't think of a use case for a descriptor that returns something other than the descriptor itself when called for a class attribute. Or perhaps require an explicit overload with |
OK, I see. After re-reading the docs it looks like the overload with We can consider returning descriptor object itself automatically for class access as a temporary measure then. |
Sounds good to me.
…On Jan 16, 2018 16:10, "Ivan Levkivskyi" ***@***.***> wrote:
OK, I see. After re-reading the docs it looks like the overload with
instance=None seems to be most "precise", but it is probably currently
blocked by #3295 <#3295> (overloads
on Nona are problematic) and this is probably why you see Anys.
We can consider returning descriptor object itself automatically for class
access as a *temporary* measure then.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#4472 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/ACwrMjAiHfU75vdDTjUCq9MOKzhHSQyiks5tLTpjgaJpZM4RgGYN>
.
|
This is maybe partially resolved? @gvanrossum's first example still doesn't work, but the second example's output is a little better now after the overload-related changes. Running mypy master now results in:
That said, maybe I'm misunderstanding something about how descriptors are supposed to work, but shouldn't the second alternative have a return type of
|
You're right, the second example should have |
But how do you propose to fix this? Should we special case |
Hm, I've got a feeling I might have been wrong. The signature for |
A use case for class property descriptor that is evaluated and does not return itself: The Conan package manager uses recipes that are classes, with attributes that are class (not instance) attributes. I didn't choose this design, but I have to deal with it. Descriptors give me the ability to define lazy attributes that compute their value, but only when accessed (because the computation is expensive). There is already an open issue for it: #2563 |
A descriptor is something with a
__get__
method; the return type of__get__
defines the type of the corresponding instance attribute. However the corresponding class attribute ought to be inspectable just as if it was an instance of the descriptor class; right now it is treated as the same type as the instance attribute. Example:The text was updated successfully, but these errors were encountered: