Reusing more builtins for type-hinting
In the spirit of 3.9 allowing builtin collections like `list`, `dict`, `tuple`, and `set` to be subscripted for type-hinting to remove the need for importing their equivalents from `typing`, I'd like to propose the same thing for a few other builtin objects, namely: `type` (for use instead of`typing.Type`) `any` (for use instead of `typing.Any`) `callable` (for use instead of `typing.Callable`) (I'm aware that a better syntax for type-hinting callables using arrow-syntax is potentially currently in the works, so maybe this last one can be ignored) Having to explicitly import objects from `typing` for basic type-hinting use-cases is a not-inconsiderable source of frustration preventing their uptake, especially by beginners. 3.9 made a valuable step forward in reducing this friction, but I think we can go further.
FYI type[Something] is already valid as it was implemented in PEP 585 and is prefered over typing.Type[Something].
On Fri, Oct 1, 2021 at 8:02 AM Matt del Valle <matthewgdv@gmail.com> wrote:
In the spirit of 3.9 allowing builtin collections like `list`, `dict`, `tuple`, and `set` to be subscripted for type-hinting to remove the need for importing their equivalents from `typing`, I'd like to propose the same thing for a few other builtin objects, namely:
`type` (for use instead of`typing.Type`) `any` (for use instead of `typing.Any`) `callable` (for use instead of `typing.Callable`)
(I'm aware that a better syntax for type-hinting callables using arrow-syntax is potentially currently in the works, so maybe this last one can be ignored)
Having to explicitly import objects from `typing` for basic type-hinting use-cases is a not-inconsiderable source of frustration preventing their uptake, especially by beginners. 3.9 made a valuable step forward in reducing this friction, but I think we can go further.
As was already stated: type[Thing] is already in the works, and callable is also being addressed elsewhere. This leaves any(). But any() is a function and not a type; it would have to graduate to a type for the type-hint syntax to work. Seems like that could cause some problems. Additionally, all() is in many ways the cousin of any(), and all() would presumably remain a function. I wonder if this asymmetry would also cause problems? Have you thought about any of this? --- Ricky. "I've never met a Kentucky man who wasn't either thinking about going home or actually going home." - Happy Chandler
I had no idea that type[Something] was already a thing, and this makes me so happy! :) It's true that `any` would have to converted to be either: 1) an object implementing __call__ and __getitem__ 2) a type implementing __new__ and __class_getitem__ 3) some special-cased type implemented in the interpreter that couldn't be recreated in python (like maybe implementing `any` as a special subclass of `builtin_function_or_method` that can be subscripted or allowing `builtin_function_or_method` to be optionally subscriptable) 4) some other option I'm not thinking of? The first two options would *technically* represent a backwards-incompatible change, but it's hard to imagine any **sane** code that would be affected. You'd have to be doing something like: ``` import builtins builtin_function_or_method = type(max) for item in builtins.__dict__.values(): if isinstance(item, builtin_function_or_method): ... # do something with all the builtin functions, which would no longer include `any` ``` The third option would neatly sidestep this and be fully backwards-compatible, but I assume would represent a bigger change to the interpreter. As I don't have any knowledge of the interpreter's internals I can't really give a preference for an approach, but I think the first step would be agreeing that a subscriptable version of `any` for type-hinting is desirable. If this seems to be something that people want then I'm sure there are people far more qualified than me to discuss implementation details. If not then it's irrelevant anyway. On Fri, Oct 1, 2021 at 2:15 PM Ricky Teachey <ricky@teachey.org> wrote:
On Fri, Oct 1, 2021 at 8:02 AM Matt del Valle <matthewgdv@gmail.com> wrote:
In the spirit of 3.9 allowing builtin collections like `list`, `dict`, `tuple`, and `set` to be subscripted for type-hinting to remove the need for importing their equivalents from `typing`, I'd like to propose the same thing for a few other builtin objects, namely:
`type` (for use instead of`typing.Type`) `any` (for use instead of `typing.Any`) `callable` (for use instead of `typing.Callable`)
(I'm aware that a better syntax for type-hinting callables using arrow-syntax is potentially currently in the works, so maybe this last one can be ignored)
Having to explicitly import objects from `typing` for basic type-hinting use-cases is a not-inconsiderable source of frustration preventing their uptake, especially by beginners. 3.9 made a valuable step forward in reducing this friction, but I think we can go further.
As was already stated: type[Thing] is already in the works, and callable is also being addressed elsewhere. This leaves any().
But any() is a function and not a type; it would have to graduate to a type for the type-hint syntax to work. Seems like that could cause some problems. Additionally, all() is in many ways the cousin of any(), and all() would presumably remain a function. I wonder if this asymmetry would also cause problems?
Have you thought about any of this?
--- Ricky.
"I've never met a Kentucky man who wasn't either thinking about going home or actually going home." - Happy Chandler
On Fri, Oct 1, 2021 at 9:49 AM Matt del Valle <matthewgdv@gmail.com> wrote:
I had no idea that type[Something] was already a thing, and this makes me so happy! :)
It's true that `any` would have to converted to be either:
1) an object implementing __call__ and __getitem__ 2) a type implementing __new__ and __class_getitem__ 3) some special-cased type implemented in the interpreter that couldn't be recreated in python (like maybe implementing `any` as a special subclass of `builtin_function_or_method` that can be subscripted or allowing `builtin_function_or_method` to be optionally subscriptable) 4) some other option I'm not thinking of?
The first two options would *technically* represent a backwards-incompatible change, but it's hard to imagine any **sane** code that would be affected. You'd have to be doing something like:
``` import builtins
builtin_function_or_method = type(max)
for item in builtins.__dict__.values(): if isinstance(item, builtin_function_or_method): ... # do something with all the builtin functions, which would no longer include `any` ```
The third option would neatly sidestep this and be fully backwards-compatible, but I assume would represent a bigger change to the interpreter.
As I don't have any knowledge of the interpreter's internals I can't really give a preference for an approach, but I think the first step would be agreeing that a subscriptable version of `any` for type-hinting is desirable.
If this seems to be something that people want then I'm sure there are people far more qualified than me to discuss implementation details. If not then it's irrelevant anyway.
I'd expect to see something more like an EAFP construct; try: maybe_all_maybe_mapping[key] except KeyError: # it's all()! I agree it would be weird. But not hard to imagine. --- Ricky. "I've never met a Kentucky man who wasn't either thinking about going home or actually going home." - Happy Chandler
The fact that the built in “any” is not a type is not an implementation detail. any() and typing.Any are completely different things/concepts. They just happen to be spelled the same. I don’t think it’s a bad thing that objects that are specifically about Type Hinting can be found in the typing module. Overloading names in builtins to save an import is a really bad idea. -CHB On Fri, Oct 1, 2021 at 7:10 AM Ricky Teachey <ricky@teachey.org> wrote:
On Fri, Oct 1, 2021 at 9:49 AM Matt del Valle <matthewgdv@gmail.com> wrote:
I had no idea that type[Something] was already a thing, and this makes me so happy! :)
It's true that `any` would have to converted to be either:
1) an object implementing __call__ and __getitem__ 2) a type implementing __new__ and __class_getitem__ 3) some special-cased type implemented in the interpreter that couldn't be recreated in python (like maybe implementing `any` as a special subclass of `builtin_function_or_method` that can be subscripted or allowing `builtin_function_or_method` to be optionally subscriptable) 4) some other option I'm not thinking of?
The first two options would *technically* represent a backwards-incompatible change, but it's hard to imagine any **sane** code that would be affected. You'd have to be doing something like:
``` import builtins
builtin_function_or_method = type(max)
for item in builtins.__dict__.values(): if isinstance(item, builtin_function_or_method): ... # do something with all the builtin functions, which would no longer include `any` ```
The third option would neatly sidestep this and be fully backwards-compatible, but I assume would represent a bigger change to the interpreter.
As I don't have any knowledge of the interpreter's internals I can't really give a preference for an approach, but I think the first step would be agreeing that a subscriptable version of `any` for type-hinting is desirable.
If this seems to be something that people want then I'm sure there are people far more qualified than me to discuss implementation details. If not then it's irrelevant anyway.
I'd expect to see something more like an EAFP construct;
try: maybe_all_maybe_mapping[key] except KeyError: # it's all()!
I agree it would be weird. But not hard to imagine.
--- Ricky.
"I've never met a Kentucky man who wasn't either thinking about going home or actually going home." - Happy Chandler
_______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/GJZFK3... Code of Conduct: http://python.org/psf/codeofconduct/
-- Christopher Barker, PhD (Chris) Python Language Consulting - Teaching - Scientific Software Development - Desktop GUI and Web Development - wxPython, numpy, scipy, Cython
On Fri, 1 Oct 2021 at 15:50, Christopher Barker <pythonchb@gmail.com> wrote:
The fact that the built in “any” is not a type is not an implementation detail. any() and typing.Any are completely different things/concepts. They just happen to be spelled the same.
Agreed.
I don’t think it’s a bad thing that objects that are specifically about Type Hinting can be found in the typing module.
Overloading names in builtins to save an import is a really bad idea.
Having to take the runtime cost of an import to do a development-time static analysis of the code, sort of is, though... Paul
On Fri, Oct 1, 2021 at 8:05 AM Paul Moore <p.f.moore@gmail.com> wrote:
Having to take the runtime cost of an import to do a development-time static analysis of the code, sort of is, though...
Perhaps so — though I’d think that could be addressed in a more comprehensive way. Thus can’t be the only runtime overhead that could conceivably be avoided. And if that was the primary goal, add Any to builtins… -CHB
Paul
-- Christopher Barker, PhD (Chris) Python Language Consulting - Teaching - Scientific Software Development - Desktop GUI and Web Development - wxPython, numpy, scipy, Cython
On Fri, Oct 1, 2021 at 2:52 PM Christopher Barker <pythonchb@gmail.com> wrote:
On Fri, Oct 1, 2021 at 8:05 AM Paul Moore <p.f.moore@gmail.com> wrote:
Having to take the runtime cost of an import to do a development-time static analysis of the code, sort of is, though...
Perhaps so — though I’d think that could be addressed in a more comprehensive way. Thus can’t be the only runtime overhead that could conceivably be avoided.
And if that was the primary goal, add Any to builtins…
-CHB
Paul
on the one hand: with all the other type-hint syntax made available (gone are the need for importing Optional, Union, Type, Dict, List, Tuple, and Set) and more coming, having to import Any certainly does feel annoying. it seems to me, in my own code at least, that many others in the typing module are used just as often (if not more!) than Any: TypeVar, Generic, and ClassVar to name a few. there are also the collections.abc types. input argument hints are more robust and proper when using types like : Mapping[] and Sequence[] (and their Mutable friends) rather than using Dict[] and List[] and Tuple[] (which can now be dict[] and list[] and tuple[]). so these are in constant use for function argument type-hints. so if Any is going to matriculate its way into built-ins, i don't see much of a reason why a big chunk of the rest of the typing module shouldn't. that being the case, i think it should probably stay where it is. --- Ricky. "I've never met a Kentucky man who wasn't either thinking about going home or actually going home." - Happy Chandler
On Fri, Oct 1, 2021 at 12:14 PM Ricky Teachey <ricky@teachey.org> wrote:
<snip>
that being the case, i think it should probably stay where it is.
Exactly:-) -CHB
--
Christopher Barker, PhD (Chris) Python Language Consulting - Teaching - Scientific Software Development - Desktop GUI and Web Development - wxPython, numpy, scipy, Cython
Is there a reason we can't use "Object" and make "Any" just an alias for "Object"? On Fri, Oct 1, 2021, 10:47 Christopher Barker <pythonchb@gmail.com> wrote:
The fact that the built in “any” is not a type is not an implementation detail. any() and typing.Any are completely different things/concepts. They just happen to be spelled the same.
I don’t think it’s a bad thing that objects that are specifically about Type Hinting can be found in the typing module.
Overloading names in builtins to save an import is a really bad idea.
-CHB
On Fri, Oct 1, 2021 at 7:10 AM Ricky Teachey <ricky@teachey.org> wrote:
On Fri, Oct 1, 2021 at 9:49 AM Matt del Valle <matthewgdv@gmail.com> wrote:
I had no idea that type[Something] was already a thing, and this makes me so happy! :)
It's true that `any` would have to converted to be either:
1) an object implementing __call__ and __getitem__ 2) a type implementing __new__ and __class_getitem__ 3) some special-cased type implemented in the interpreter that couldn't be recreated in python (like maybe implementing `any` as a special subclass of `builtin_function_or_method` that can be subscripted or allowing `builtin_function_or_method` to be optionally subscriptable) 4) some other option I'm not thinking of?
The first two options would *technically* represent a backwards-incompatible change, but it's hard to imagine any **sane** code that would be affected. You'd have to be doing something like:
``` import builtins
builtin_function_or_method = type(max)
for item in builtins.__dict__.values(): if isinstance(item, builtin_function_or_method): ... # do something with all the builtin functions, which would no longer include `any` ```
The third option would neatly sidestep this and be fully backwards-compatible, but I assume would represent a bigger change to the interpreter.
As I don't have any knowledge of the interpreter's internals I can't really give a preference for an approach, but I think the first step would be agreeing that a subscriptable version of `any` for type-hinting is desirable.
If this seems to be something that people want then I'm sure there are people far more qualified than me to discuss implementation details. If not then it's irrelevant anyway.
I'd expect to see something more like an EAFP construct;
try: maybe_all_maybe_mapping[key] except KeyError: # it's all()!
I agree it would be weird. But not hard to imagine.
--- Ricky.
"I've never met a Kentucky man who wasn't either thinking about going home or actually going home." - Happy Chandler
_______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/GJZFK3... Code of Conduct: http://python.org/psf/codeofconduct/
-- Christopher Barker, PhD (Chris)
Python Language Consulting - Teaching - Scientific Software Development - Desktop GUI and Web Development - wxPython, numpy, scipy, Cython _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/FJJ4G2... Code of Conduct: http://python.org/psf/codeofconduct/
02.10.21 17:10, Todd пише:
Is there a reason we can't use "Object" and make "Any" just an alias for "Object"?
If you mean "object", then the reason is that "object" has no methods and attributes (besides few dunder methods like __repr__ and __reduce__), while "Any" has all methods and attributes.
Just spitballing but how about any.obj as an alias for typing.Any? It suffers from the same problem as using naked any- which is that any doesn't really have anything to do with type hinting... but it doesn't suffer from the problem of having to convert any to a type. It would just grow a class attribute referring to typing.any. And it seems pretty readable to me. Rick. On Sat, Oct 2, 2021, 10:30 AM Serhiy Storchaka <storchaka@gmail.com> wrote:
02.10.21 17:10, Todd пише:
Is there a reason we can't use "Object" and make "Any" just an alias for "Object"?
If you mean "object", then the reason is that "object" has no methods and attributes (besides few dunder methods like __repr__ and __reduce__), while "Any" has all methods and attributes.
_______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/NMKXER... Code of Conduct: http://python.org/psf/codeofconduct/
On Sat, Oct 2, 2021, 10:40 AM Ricky Teachey <ricky@teachey.org> wrote:
Just spitballing but how about any.obj as an alias for typing.Any? It suffers from the same problem as using naked any- which is that any doesn't really have anything to do with type hinting... but it doesn't suffer from the problem of having to convert any to a type. It would just grow a class attribute referring to typing.any. And it seems pretty readable to me.
Rick.
Sorry I should have said function attribute, not class attribute. Hopefully it was clear.
01.10.21 15:01, Matt del Valle пише:
`any` (for use instead of `typing.Any`) `callable` (for use instead of `typing.Callable`)
The problem is than any() and callable() are not types, but functions, whose names are accidentally similar to names of some typing types. If the name of callable() would be iscallable(), you would not even came with this idea. Now, if merge any() and typing.Any, callable() and typing.Callable, what should help() show for any and callable? What are they signatures? How do you explain that the same object is used for two different, completely unrelated things?
Having to explicitly import objects from `typing` for basic type-hinting use-cases is a not-inconsiderable source of frustration preventing their uptake, especially by beginners. 3.9 made a valuable step forward in reducing this friction, but I think we can go further.
In any case you need to import for Mapping, Sequence, Final, NoReturn, TypeVar, etc. list[int] is not the same as Iterable[int], and using interfaces and protocols in annotations is more preferable than using concrete classes.
participants (7)
-
Christopher Barker
-
James H-B
-
Matt del Valle
-
Paul Moore
-
Ricky Teachey
-
Serhiy Storchaka
-
Todd