In fact, even before Python got as popular as it now is, it followed the same principle - integrating tried and tested approaches rather than adopting “experimental” ideas.
I mean… it’s not like Python hasn’t done a lot of innovative stuff. That would cast Python in a bad light I think. Just the syntax of significant whitespace is pretty radical compared to most other languages. Still to this day!
but in general I don’t think that it’s a typical sort of Python approach.
What part of it is unpythonic? Can you be more specific?
I find it very pythonic. It is certainly DRY. That part is objectively true at least. One can argue that it violates “explicit is better than implicit”, I guess? Although I’d argue that point 
I would argue that this is a proposal for “readability counts”, a part of the Zen that typing-everywhere is at odds with.
Oh, I almost forgot, I was gifted this little tool to explore the correlation between names and types (credit to asottile):
import ast
import collections
import sys
class V(ast.NodeVisitor):
def __init__(self):
self.name_to_type = collections.Counter()
def visit_FunctionDef(self, node):
for arg in node.args.posonlyargs + node.args.args + node.args.kwonlyargs:
if arg.annotation:
self.name_to_type[(arg.arg, ast.unparse(arg.annotation))] += 1
if node.args.vararg and node.args.vararg.annotation:
self.name_to_type[(f'*{node.args.vararg.arg}', ast.unparse(node.args.vararg.annotation))] += 1
if node.args.kwarg and node.args.kwarg.annotation:
self.name_to_type[(f'**{node.args.kwarg.arg}', ast.unparse(node.args.kwarg.annotation))] += 1
self.generic_visit(node)
visit_AsyncFunctionDef = visit_FunctionDef
def visit_AnnAssign(self, node):
if isinstance(node.target, ast.Name):
name = node.target.id
elif isinstance(node.target, ast.Attribute):
name = node.target.attr
else:
raise NotImplementedError(node.target)
self.name_to_type[(name, ast.unparse(node.annotation))] += 1
self.generic_visit(node)
def main() -> int:
v = V()
for filename in sys.argv[1:]:
with open(filename, 'rb') as f:
contents = f.read()
v.visit(ast.parse(contents, filename=filename))
import pprint; pprint.pprint(v.name_to_type.most_common(20))
You can also just visually scan over stubs files to get a feel for this. For example django-stubs. We can take one file like django-stubs/django-stubs/template/response.pyi at master · typeddjango/django-stubs · GitHub and see that it’s quite a lot of mappings here that are duplicated in that file and with a big overlap with django-stubs/django-stubs/views/defaults.pyi at master · typeddjango/django-stubs · GitHub for example.
I also believe this kind of mapping becomes more and more useful the further out from the standar library. So a web app will benefit more than Django itself, which benefits more than the csv
module e.g., which benefits more than re
, etc.
Another nice thing about this idea is that it doesn’t really require big changes to the standard library, nor really a PEP, nor… well… anything really. One can potentially add it as an experimental feature in mypy, pylance, or some other static type checker, and try it out there.
I did try looking at this once but I got lost in the mypy code base and when asking for help I just got “why would you do that?” and no one understood what I was saying heh.
Just some help to find where I could hook into mypy to get a prototype going would be great!