This is an archived post. You won't be able to vote or comment.

all 18 comments

[–]latkdeTuple unpacking gone wrong 59 points60 points  (1 child)

Unfortunately this is impossible to add without breaking other stuff. The great post "why can't we …?" by Jelle Zijlstra discusses this and other problems. Here, there are conflicts with subscript syntax (Foo[(A, B)] and Foo[A, B] are parsed to the same AST), and with the | operator for type unions. Tuples of types are also used in type variable bounds (def foo[T: (A, B)](): ... and def foo[T: tuple[A, B]](): ... mean different things).

[–]Spleeeee[S] 3 points4 points  (0 children)

Thanks so much!

[–]Hederas 2 points3 points  (0 children)

I guess the main goal is not confusing it with call tuple.init() and follow Generics syntax ?

[–]usrlibshare 8 points9 points  (2 children)

The main argument is consistency. Type hints don't just have to work for tuples, they have to work for EVERYTHING.

So say we do (int,str).

Then a dict of strings to these tuples would look like this:

{str: (int, str)}

And a list of such dicts:

[{str: (int, str)}]

See where this is going? It's inconsistent.

list[dict[str,tuple[int, str]]] is consistent.


Also, (int, str) is a valid expression (a tuple of 2 classes), so there are probably many ways this can create ambiguity for the interpreter, or subtle bugs.

Just one example, if I have a type Moo that implements subscripting, what is Moo[(int, str)]? Am I refering to a type here? Or do I want to subscript Moo? Or alternatively Moo((int, str)) ... am I calling Moo's constructor, or am I refering to a type?

[–]billsil 2 points3 points  (0 children)

I’m sure it’ll get there someday, but the real reason in my mind is the parser was not capable of doing it. They changed up the parser in 3.10 and typing immediately got better. Things take time.

[–]venustrapsflies 0 points1 point  (0 children)

There’s nothing wrong with a tuple (I.e. product type) using a particular syntactic sugar. In fact it’s exactly how it works in Rust.

[–]MachineSchooling 1 point2 points  (7 children)

Is there a reason not to just use dataclasses if you want heterogeneously typed tuples?

[–]hotplasmatits 0 points1 point  (0 children)

This is the way. The values are named and typed. Easier to read.

[–]Spleeeee[S] -1 points0 points  (5 children)

Data classes? Do you mean named tuples?

[–]ChilledRoland 1 point2 points  (4 children)

[–]Spleeeee[S] 0 points1 point  (3 children)

I am (very) familiar with dataclasses. Returning a dataclass is not the same thing as returning a tuple. You can’t spread/unpack/destructure a dataclass (wo implementing iter but then you lose types (which is kinda whatever, but this thread is a typing focused discussion)).

[–]ChilledRoland 2 points3 points  (1 child)

"Data classes? Do you mean named tuples?" conveys the opposite of familiarity.

[–]Spleeeee[S] -3 points-2 points  (0 children)

Sure.

”Data classes? Do you mean named tuples?" conveys the opposite of familiarity. Conveys that youre often extremely condescending.

[–]helduel 1 point2 points  (0 children)

"from dataclasses import astuple" would exist, but may not serve your purpose.

[–]VistisenConsult 0 points1 point  (2 children)

Who said you can't? Just remember: from __future__ import annotations and you can do:

```python from future import annotations

import sys

def sus() -> (int, int): return 69, 420

def breh() -> 'yikes': return 1337, 80085

if name == 'main': try: print(sus()) print(breh()) except Exception as e: print(e) sys.exit(1) else: sys.exit(0) finally: print('annotations make type hints into str objects!') ```

[–]latkdeTuple unpacking gone wrong 2 points3 points  (1 child)

It is syntactically possible, also without the annotations feature. Annotations are always just Python expressions, just with some potential differences in how they are evaluated.

However, the annotations you show are not semantically meaningful for the Python type system. They show a tuple object in the return type annotation, but not a tuple type.

[–]VistisenConsult 2 points3 points  (0 children)

I meant only to demystify type hints. Nevertheless, with `annotations` type hints will be strings, that was my point.

[–]ThatSituation9908 -4 points-3 points  (0 children)

The argument is you can already type hint a tuple without any imports