PEP-585 made the `list[2, 3, 5]` typo into a silent error, can we improve that?

Background

Skimming PEP 585 -- Type Hinting Generics In Standard Collections | Python.org after reading Only Python: Python's tug of war between beginner-friendly features and support for advanced users :

I don’t see any obvious text in PEP-585 that discusses why making life harder on people who make () vs [] typos was accepted?

If you didn’t read the above blog, the TL;DR here is:


3.8 and earlier made it easy to immediately see the mistake at its source:

>>> x = list[1, 3]
TypeError: 'type' object is not subscriptable

3.9 and later surface a mysterious to the uninitiated error later at runtime rather than at the source of the problem where [] were used on list in the first place. Debugging this is hard. Even if your Google search tells you what is wrong, you still have to hunt for the line errant line of code.

>>> x = list[1, 3]
# ... unknown amount of code later ...
>>> x[0]
TypeError: There are not type variables left in list[1, 3]

Proposal

Shouldn’t we do more to make things that are obviously not typing related an immediate, at __class_getitem__ time, error in a user friendly manner?
… While also documenting this caveat for situations we cannot in the PEP as a known issue (potentially with an “oops, sorry!” on it).

The PEP-585 Rejected Alternative “generics erasure” section discusses some unfriendly error situations not unlike this in its rejection text… Ironic, given this situation exists in the accepted, implemented, and shipped thing.

3.9 has shipped this behavior. So we’re somewhat stuck. But a look at how it gets used to see if we can safely limit it to meaningful typing related use cases seems worthwhile.

Sure, linters can be forced to pick up some slack on our mistake here. They could flag the most obvious of these… But the people most likely to lose time to these typos cannot be assumed to be using linters (or the blog author’s Friendly-traceback).

I don’t like that addressing this could complicate the class getitem implementations on these types. But I suspect even some very simple and fast up front checks could go a long way.

7 Likes

Note that list(2, 3, 5) is an error too. So this is not just a typo.

1 Like

Note that list(2, 3, 5) is an error too. So this is not just a typo.

While list(2, 3, 5) would indeed be a typo, the following perhaps illustrate better the “problem”.

>>> list('123')
['1', '2', '3']
>>> x = list['123']
>>> x.append
<method 'append' of 'list' objects>
>>> x.append('4')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: descriptor 'append' for 'list' objects doesn't apply to a 'str' object

I don’t see any easy resolution to this. Even though I complained in various forums (and on my blog) about the confusion that type annotation could cause for beginners, on the whole they are likely a much needed feature for programmers working on large projects.

My personal preference would be if there were a way to “turn them off” so that using them would be a syntax error. If this could be done by a directive at the top of a file, something like:

# typing: off

I think it would go a long way towards easing the pain of learning Python for beginners.

1 Like

What if list[t1, t2] was disallowed, and instead list[t1 | t2] or list[typing.Union[t1, t2]] was required instead.
This would require a deprecation period, but the warnings emitted could mention the possible misuse along with the proper way to specify multiple types.

edit: That leaves open the misuse-case of the single-element list. which could possibly be taken care of by checking that the argument is an instance of type or whatever the base-class is for typing, which then leaves open the corner case where you intend to create a single element list of types.

1 Like

Also usages like list['int'] (single element list of a type’s name in string form).

1 Like