Reputation: 381
The following is a snippet from Django official tutorial.
Link is here: https://docs.djangoproject.com/en/3.0/intro/tutorial05/
class QuestionDetailViewTests(TestCase):
def test_future_question(self):
future_question = create_question(question_text ="future question", days=30)
url = reverse('polls:detail',args = (future_question.id,))
args = (future_question.id,)
: this syntax is very strange to me. Why do we need brackets and coma here?
Upvotes: 2
Views: 274
Reputation: 599
Willem already gave a great answer, but to give a more detail on the fundamental question:
This syntax is very foreign to me. Why do we need brackets and coma here?
It might be simpler to see what's going on by looking at this example in the vanilla Python shell:
>>> a = ('foo')
>>> type(a)
# outputs <class 'str'>
>>> b = ('foo',)
>>> type(b)
# outputs <class 'tuple'>
This behavior might be surprising to you (I know it was to me the first time I saw it). One might expect the parentheses () to have a similar relationship with tuples as brackets [] do with lists. But while for c = ['foo']
, the brackets ensure that c is assigned a list, with c = ('foo')
, the parentheses don't make any difference compared to c = 'foo'
. In fact, if you want to create a tuple, you can do this:
>>> d = 'foo', 'bar'
>>> type(d)
# outputs <class 'tuple'>
>>> e = ('foo',)
>>> type(e)
# outputs <class 'tuple'>
As you can see, the parentheses aren't in themselves necessary for creating a tuple. You do however often need them to specify that the comma-separated values are meant to be interpreted as elements of a tuple. For example:
sum((3, 3))
# outputs 6
This works. However:
sum(3, 3)
# outputs TypeError: 'int' object is not iterable
In this case, Python thinks that the two 3's are to be interpreted as separate arguments in the function call, not as elements of a tuple.
Similarly, for:
reverse('polls:detail',args = (future_question.id,))
Just using args = future_question.id
would mean that you just pass a single int instead of a collection, as Willem described. Also, reverse('polls:detail',args = future_question.id,)
wouldn't work either, because Python would interpret that last comma as an 'argument separator', not as something indicating that future_question.id
is an element of a tuple. So you need both the comma and the parentheses to tell Python that you want to pass a single-element tuple as an argument to the function.
Upvotes: 2
Reputation: 476503
Why do we need brackets and coma here?
To wrap the future_question.id
in a singleton tuple, a tuple with one element. It is however not necessary to use a tuple, you can for example use a list:
url = reverse('polls:detail', args=[future_question.id])
what is important is that it is an iterable, and that the future_question.id
is an element. If you pass future_question.id
directly, and the id
is an int
, then that would not make sense, since args
expects a collection, and an int
is not a collection.
Upvotes: 4