[Python-ideas] Optional static typing -- the crossroads
Andrew Barnert
abarnert at yahoo.com
Sun Aug 17 10:52:21 CEST 2014
On Aug 17, 2014, at 0:26, Steven D'Aprano <steve at pearwood.info> wrote:
> On Sat, Aug 16, 2014 at 11:02:01PM -0700, Andrew Barnert wrote:
>>
>
>> I won't belabor the point, but again: I don't think we need a generic
>> list type object, and without it, this entire problem--your only
>> remaining problem that isn't a mere stylistic choice--vanishes.
>
> I don't understand. If there's no list typing object, how do you declare
> a variable must be a list and nothing but a list? Or that it returns a
> list?
You think about it and make sure you really do need a list and nothing but a list. Most of the time (as in all three of the examples given in this thread) this is a mistake. If it's not, then you use List. (Or, if the stdlib doesn't provide that, you have to write one line of code: List = TypeAlias(list), and then you can use it.)
If having list[T] is going to be more of an attractive nuisance than a useful feature, and it will be especially attractive and nuisanceful for exactly the same novices who are unlikely to know how to TypeAlias it themselves, why is it a problem to leave it out?
>> Even if you drop the idea for [str] and {int: str}, which I agree
>> seems unavoidable, I think it may still make sense for (int, str) to
>> mean a heterogeneous iterable.
>
> That makes no sense to me. It looks like a tuple, not a generic iterable
> object. Your interpretation has the same problems I discussed above for
> [str] notation: it is an arbitrary choice whether (...) means Iterable,
> Sequence or ImmutableSequence, and it doesn't fit nicely with other
> common uses of parens. See below.
>
>> Python already has target lists, argument lists, parameter lists, and
>> expression lists that all have the same syntax as tuples or a superset
>> thereof, but don't define tuples. In (a, b) = zip(c, d), neither (a,
>> b) nor (c, d) is a tuple, and I don't think anyone is confused by
>> that.
>
> Ha , you've obviously stopped reading the "Multi-line with statement"
> thread on Python-Dev :-)
OK, granted, only 4 of the 5 attempts to reuse the comma-separated lists in Python have been 100% successful. Still not a bad batting average.
>> So, why can't def foo(spam: (int, str)) mean that spam is an
>> iterable of an int and a str, in exactly the same way that the
>> assignment statement means that a and b are assigned the result of
>> unpacking the iterable returned by zip when called with c and d?
>
> But a, b = zip(c, d) requires that there be exactly two elements, not
> some unspecified number.
And spam:(int, str) requires that there be exactly two elements (and that the first be an int and the second a str), not some unspecified number. How is that any different?
> To me, spam:(int, str) has a natural interpretation that spam can be
> either an int or a str, not an Iterable or Sequence or even a tuple.
OK, I see the parallel there with exception statements now that you mention it.
But almost anywhere else in Python, a comma-separated list is a sequence of values, targets, parameters, etc., not a disjunction. The obvious way to spell what you want here is "int | str" (and the fact that it was independently suggested three times on this thread and no other alternatives have been suggested until now makes me feel pretty confident that it really is the obvious way).
Of course there is a _different_ alternative that could be borrowed from some of the typed functional languages: int * str. But I don't think that's at all obvious to a Python reader.
More information about the Python-ideas
mailing list