Reputation: 1210
type(1,)
Out[1]: int
a=1,
a
Out[3]: (1,)
type(a)
Out[4]: tuple
I am using Python 3.6, and I am expecting type(1,) to return a tuple.
According to this link:
... a tuple with one item is constructed by following a value with a comma...
What am I missing?
Upvotes: 5
Views: 1537
Reputation: 6246
The issue lies in how python has to interpret function arguments, while allowing the "quality of life" trailing comma. Functions are called with parentheses with comma separated arguments. When you pass type(1,)
, There is ambiguity between a comma separated argument with a trailing comma, and an actual tuple.
A simple example:
def test(x):
print(x)
test("hello") #Output: hello
test("hello",) #is also valid, Output: hello
To see how python is actually accepting the argument, you can use the repr
function.
repr(1)
'1'
repr(1,)
'1'
To specifically ensure you pass a tuple as the first argument, you should wrap it in parenthesis and resolve ambiguity.
repr((1,))
'(1,)'
type((1,))
tuple
The reason why it works after assigning is because the ambiguity is resolved while storing the value as a tuple.
a = 1,
repr(a)
'(1,)'
Additional info
As for when trailing commas can be useful, we can refer to the relevant PEP8 section.
When trailing commas are redundant, they are often helpful when a version control system is used, when a list of values, arguments or imported items is expected to be extended over time. The pattern is to put each value (etc.) on a line by itself, always adding a trailing comma, and add the close parenthesis/bracket/brace on the next line.
Which means, you should never be putting redundant trailing commas in a single line.
#No good
func_with_future_changes_or_variable_args(arg1, arg2=True,)
#Good
func_with_future_changes_or_variable_args(arg1,
arg2=True,
)
I personally don't run into much issues with functions that change, but trailing commas are life-savers when maintaining lists or dictionaries that can change over time. For example:
FILES = [
'setup.cfg',
'tox.ini',
]
Adding or removing values from a list like that only requires changing a single line in isolation like following, making it really easy to track in version control commits.
FILES = [
'setup.cfg',
'tox.ini',
+ 'new_item.txt',
]
Upvotes: 9
Reputation: 5463
From the docs:
Tuples may be constructed in a number of ways:
- Using a pair of parentheses to denote the empty tuple: ()
- Using a trailing comma for a singleton tuple: a, or (a,)
- Separating items with commas: a, b, c or (a, b, c)
- Using the tuple() built-in:tuple() or tuple(iterable)
According to this, all of the following are tuples. You will notice explicit assignment to a variable removes all ambiguities:
In [8]: a = ()
In [9]: type(a)
Out[9]: tuple
In [10]: b = (1,)
In [11]: type(b)
Out[11]: tuple
In [12]: b = 1,
In [13]: type(b)
Out[13]: tuple
When we look at type(1,)
, we should keep in mind that type()
is a function and the trailing comma is an argument separator. The 1
is the first argument which is an integer and as trailing commas are allowed in Python, this is a valid statement but much less explicit. According to the official docs for type()
, it is recommended to use the built-in isinstance function for type-checking which is more explicit:
In [21]: isinstance((1,), tuple)
Out[21]: True
Upvotes: 0