Role of comma when adding a dictionary entry in Python - python

I have a simple question.
I have a dictionary: table = collections.defaultdict(set), and a previously defined grammar consisting of rules like the following:
Rule(('Noun', ('money',)))
Rule(('Noun', ('book',)))
Rule(('S', ('book',)))
Now, when I type this, nothing happens.
for rule in grammar:
if rule.symbols == ("book"):
table[col - 1, col].add(rule.head)
When I type this, the entry is added.
for rule in grammar:
if rule.symbols == ("book",):
table[col - 1, col].add(rule.head)
The only difference between the two is the comma behind "book". What does this comma do and why is it necessary?

In the first case, ("book") the parens are just a way of grouping the expression. The value of that expression is just the string "book".
In the second case, it's creating a tuple, with one element in it.

You need add comma to make it a tuple, otherwise it's just a string.

One is string, second is tuple (,):
>>> ("book")
'book'
>>> ("book",)
('book',)

The comma transform the expression type from str (with useless parenthesis around) to tuple with single element.
Use type() to see this in action:
>>> type(("book"))
<class 'str'>
>>> type(("book",))
<class 'tuple'>

Related

FastApi pydantic returns Boolean as True but sqlalchemy throws error Not a boolean value: True [duplicate]

Why does adding a trailing comma after an expression create a tuple with the expression's value? E.g. in this code:
>>> abc = 'mystring',
>>> print(abc)
('mystring',)
Why is the printed output ('mystring',), and not just mystring?
It is the commas, not the parentheses, which are significant. The Python tutorial says:
A tuple consists of a number of values separated by commas
Parentheses are used for disambiguation in other places where commas are used, for example, enabling you to nest or enter a tuple as part of an argument list.
See the Python Tutorial section on Tuples and Sequences
Because this is the only way to write a tuple literal with one element. For list literals, the necessary brackets make the syntax unique, but because parantheses can also denote grouping, enclosing an expression in parentheses doesn't turn it into a tuple: you need a different syntactic element, in this case the comma.
Make sure to read this great answer by Ben James.
Tuples are not indicated by the parentheses. Any expression can be enclosed in parentheses, this is nothing special to tuples. It just happens that it is almost always necessary to use parentheses because it would otherwise be ambiguous, which is why the __str__ and __repr__ methods on a tuple will show them.
For instance:
abc = ('my', 'string')
abc = 'my', 'string'
What about single element tuples?
abc = ('mystring',)
abc = 'mystring',
So in effect what you were doing was to create a single element tuple as opposed to a string.
The documentation clearly says:
An expression list containing at least one comma yields a tuple. The length of the tuple is the number of expressions in the list. The expressions are evaluated from left to right.
Unpacking multi-element tuple:
a, b = (12, 14)
print(type(a))
Output:
int
Unpacking single-element tuple:
a, = (12, )
print(type(a))
Output:
int
Otherwise:
a = (12,)
print(type(a))
Output:
tuple
In the question's example, you assigned the variable 'abc' to a Tuple with a length of 1.
You can do multiple assignments with this similar syntax:
x,y = 20,50
Also note that the print statement has a special understanding for ending a print statement with a comma; This tells print to omit the trailing newline.
print 'hello',
print 'world'
result:
hello world
I was somewhat confused about the application of the comma, as you also apply a comma to make a list instead of tuple, but with a different variable assignment.
Hereby, a simple example that I made of how to create a tuple or a list.
abc = 1,2,3 # prints a tuple: (1, 2, 3)
*abc, = 1,2,3 # prints a list: [1, 2, 3]

Type(1,) returns int expected tuple

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?
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',
]
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

Python data type behaving some different

I am finding out difference between data types in python . I am little bit confuse why type of demo2 is giving list instead of tuple . Can anyone tell me why it is printing type list instead of tuple ?
Code
demo1 = ()
print ("demo1 {}".format(type(demo1)))
demo2 = ([])
print ("demo2 {}".format(type(demo2)))
demo3 = ([],[])
print ("demo3 {}".format(type(demo3)))
Output
demo1 <type 'tuple'>
demo2 <type 'list'>
demo3 <type 'tuple'>
To create an empty tuple, use tuple(). It will print as (), but that's not how you create an empty tuple. As minimum, a tuple must contain one item. So you need to create it as ([],).
Your code ([]) is the same as [], the parenthesis in this case act as continuation characters` and not an empty tuple.
Expressions in parentheses, square brackets or curly braces can be
split over more than one physical line without using backslashes.
See the documentation on lexical analysis for more details.
You can also verify this at the interpreter:
>>> ([]) == []
True
Basically () small brackets are block enclosing brackets but eventually this represents tuple too in python. whenever we declare a tuple into python we need to comma separate 2 values or assign () (small opening and closing brackets, this will create an empty tuple).
So in your demo3 you made a list and enclosed with brackets that means your demo3 have a list vector. If you provide comma after [] just like ([], ) it will make a tuple of lists.
Below are some enhanced examples: -

Why single element tuple is interpreted as that element in python?

Could anyone explain why single element tuple is interpreted as that element in Python?
And
Why don't they just print the tuple (1,) as (1)?
See the examples below:
>>> (1)
1
>>> ((((1))))
1
>>> print(1,)
1
>>> print((1,))
(1,)
It's because (1) is not a tuple. (1) is 1 with parentheses surrounding it. As the python documentation states
it is the comma, not the parentheses, that define the tuple.
Source
The only tuple without a comma is a 0-tuple, which is (). Note, you can check this by running type((1)) and seeing that it returns <type 'int'> not <type 'tuple'>.
A single element tuple is never treated as the contained element. Parentheses are mostly useful for grouping, not for creating tuples; a comma does that.
Why don't they just print (1,) as (1)?
Probably because printing a builtin container type gives a representation that can be used to recreate the container object via , say eval:
The docs for __repr__ provides some clarity on this:
If at all possible, this should look like a valid Python expression
that could be used to recreate an object with the same value
Answering your question, (1) is just integer 1 with a grouping parenthesis. In order to recreate the singleton tuple via its representation, it has to be printed as (1,) which is the valid syntax for creating the tuple.
>>> t = '(1,)'
>>> i = '(1)'
>>> eval(t)
(1,) # tuple
>>> eval(i)
1 # int
Because only (1, ) in your examples is tuple. The rest are expressions.
In [4]: type(1,)
Out[4]: int
In [5]: type((1,))
Out[5]: tuple
In [6]: type((1))
Out[6]: int
This is very detailed answer from #Ray Total
Sure, in general parentheses don't change the meaning of an expression. For example you can say 4+(1) and it will be 5, the same way 4*(2-1) would be 4. Because the convention is to use parentheses for grouping of subexpressions, the designer of Python thought it would be too confusing to overload the meaning to mean both grouping and single-element tuples. Also Python has a type function. In fact type((2)) is int and type((2,)) is tuple. We don't want there to be any ambiguity, which there would be if (2) were treated as a tuple
A tuple consists of a number of values separated by commas (not necessary parentheses).
You can even define tuple like this
t = 1, # (with or without surrounding parentheses)
>>> type(t)
<class 'tuple'>
Here , used to tell interpreter to create tuple if not present it will consider as int.
Same rule applies when we define like this
>>> t = (1)
>>> type(t)
<class 'int'>
(1) is not a tuple, it's just parentheses around a number. This is because sometimes you want to use parentheses to indicate order of operations, for example: (x+y)*z. This obviously doesn't refer to a tuple containing x+y, it's just to show that the addition should happen before the multiplication.
(((1))) is not a tuple for the same reason, the parentheses are just saying "evaluate what's inside before moving on".
print(1,) is just calling the print function on the number 1. When calling a function, a trailing comma is allowed. However, in python2, this will probably pring (1,), because print isn't a function.
print((1,)) is the only thing that prints a tuple, because we are now actually passing a tuple into the function.

Python string converts magically to tuple. Why?

I've got a dict in which I load some info, among others a name which is a plain string. But somehow, when I assign it to a key in the dict it gets converted to a tuple, and I have no idea why.
Here's some of my code:
sentTo = str(sentTo)
print type(sentTo), sentTo
ticketJson['sentTo'] = sentTo,
print type(ticketJson['sentTo']), ticketJson['sentTo']
which outputs the following on my terminal:
<type 'str'> Pete Chasin
<type 'tuple'> ('Pete Chasin',)
Why does assigning it to a dict convert it to a tuple?
You told Python to create a tuple containing a string:
ticketJson['sentTo'] = sentTo,
# ^
It is the comma that defines a tuple. Parentheses are only needed to disambiguate a tuple from other uses of a comma, such as in a function call.
From the Parenthesized forms section:
Note that tuples are not formed by the parentheses, but rather by use of the comma operator. The exception is the empty tuple, for which parentheses are required — allowing unparenthesized “nothing” in expressions would cause ambiguities and allow common typos to pass uncaught.
and from Expression lists:
An expression list containing at least one comma yields a tuple. The length of the tuple is the number of expressions in the list. The expressions are evaluated from left to right.
ticketJson['sentTo'] = sentTo, is single element tuple

Categories

Resources