-2

This question is about design and readbility, not performance:

Is it more pythonic to initialize tuples with the tuple keyword, or just with parenthesis? Both do the same thing, but explicitly typing tuple is more verbose.

Here's two different cases of tuple initalization.

  1. From existing iterable
def myfunc(myarg: Iterable):
    # "tuple" is explicitly typed out
    mytuple = tuple(myarg)
def myfunc(myarg: Iterable):
    # "tuple" is not explicitly typed out; only parenthesis are used
    mytuple = ([myarg])
  1. Creating new tuple from literal
# "tuple" is explicitly typed out
mytuple = tuple([1, 2, 3, 4])
# "tuple" is not explicitly typed out; only parenthesis are used
mytuple = (1, 2, 3, 4)

Contradictorily, I know that it is more common to initialize lists without explicit;y typing list:

mylist = [1, 2, 3, 4] # "list" is not explicitly typed out; only brackets are used

# Rather than:
mylist = list([1, 2, 3, 4]) # "list" is explicitly typed out

Personally, I always explicitly type out tuple to make it easier to see that a tuple is being initialized. However, this contradicts my style (which is the more popular style) of initializing lists (without explicitly typing list.

In conclusion, I want to know which way of initializing tuples is more pythonic.

  • 2
    `list[1, 2, 3, 4]` is not valid Python syntax – Woodford Feb 21 '23 at 23:07
  • 3
    Plus, `tuple(1, 2, 3, 4)` doesn't do what you think it does. You need `(1, 2, 3, 4)`. It's not a matter of style; it's a matter of actually having code that works. – user2357112 Feb 21 '23 at 23:08
  • 2
    `(myarg)` doesn't define a tuple at all; it's just a parenthesized expression, so `mytuple` is assigned whatever value was passed to `myfunc` in the first place: could be a list, a tuple, a dict, a generator, anything that is considered iterable. – chepner Feb 21 '23 at 23:09
  • @Woodford It's valid syntax; it's *symmantically* invalid in older versions of Python betcause `type.__getitem__` isn't defined and `list.__class_getitem__` wasn't introduced yet. As of Python 3.9, `list[1,2,3,4]` simply ignores the tuple in the brackets and returns `list` itself. – chepner Feb 21 '23 at 23:12
  • 1
    @chepner: Well, no, it creates a `types.GenericAlias` instance. – user2357112 Feb 21 '23 at 23:13
  • 2
    Repeat to yourself: *parentheses don't define tuples*. A tuple is defined by an expression list, which is simply a sequence of expressions separated by commas. Parantheses are only necessary to disambiguate *this* use of commas from other uses of commas. The only exception is the empty tuple `()`, since empty parentheses don't otherwise have an established meaning. – chepner Feb 21 '23 at 23:13
  • @user2357112 True; at runtime, though, it behaves like `list`. – chepner Feb 21 '23 at 23:14
  • They are not, in fact, equivalent. – juanpa.arrivillaga Feb 21 '23 at 23:33
  • 2
    @Woodford I'm not sure what 2 people upvoted that, but `list[1, 2, 3, 4]` is valid Python syntax. – wim Feb 21 '23 at 23:33
  • 1
    @wim TIL that it's been added (relatively) recently. But it's syntactically invalid in versions 3.8 and earlier: `TypeError: 'type' object is not subscriptable` – Woodford Feb 21 '23 at 23:41

1 Answers1

2

Apart from the subjective answers one may give to your questions, there are a few mistakes in the code that you present (see the end of this answer).

IMO, tuple and list are not for constructing tuples and lists by enumerating their elements. To do so, use parentheses and brackets, respectively:

t = (1, 2, 3)
l = [1, 2, 3]

In fact, when defining a tuple, parentheses are not necessary:

t = 1, 2, 3

but I think it's much clearer if you use parentheses.

Notice in particular the case of tuples with one element, where it's necessary to use a trailing comma (before the closing parenthesis).

t = (42,)
l = [42]

It doesn't hurt to do the same for lists and, in general, it doesn't hurt to have a trailing comma both in lists and tuples; but in the case of tuples of one element the comma is necessary.

The usefulness of tuple and list is for constructing tuples and lists from other iterables (generators, tuples, lists, etc.), e.g.

t = tuple(i**2 for i in range(10))
l = list(range(100))

For lists, list comprehensions are arguably preferable when possible:

l1 = list(i**2 for i in range(10))
l2 = [i**2 for i in range(10)]       # this is preferable

Notice also that there are three lines in your code that are wrong:

  1. mytuple = (myarg) does not construct a tuple unless myarg is already a tuple; these are just parentheses.
  2. mytuple = tuple(1, 2, 3, 4) raises a TypeError.
  3. list[1, 2, 3, 4] is not a list, just use the brackets (it's funny that this is legal syntax, as mentioned in the comments above, but this is off-topic).

If you insist on using the words tuple and list when you enumerate the elements, here's (one version of) the correct syntax:

t = tuple([1, 2, 3])
l = list([1, 2, 3])
nickie
  • 5,608
  • 2
  • 23
  • 37