53

What is better to do?

self.call(1, True, "hi")

or

self.call(1, True, "hi",)

And what in the following cases:

self.call(
    1,
    True,
    "hi"
)

or

self.call(
    1,
    True,
    "hi",
)

?

Reasons for adding a trailing comma in data structures are familiar to me, but what about function calls?

moooeeeep
  • 31,622
  • 22
  • 98
  • 187
taper
  • 9,236
  • 5
  • 28
  • 29
  • 2
    Can you outline these reasons? I've only ever felt compelled to do it in php and that's a language that makes me neaseous. – Aesthete Aug 23 '12 at 08:37
  • 2
    I would follow the recommendations in PEP8 http://www.python.org/dev/peps/pep-0008/ – Tim Hoffman Aug 23 '12 at 08:39
  • 4
    @TimHoffman: I've just skimmed through PEP 8. I couldn't find anything pertinent to this question there - could you point me to the relevant section? – Tim Pietzcker Aug 23 '12 at 08:42
  • Yeah, I thought this one was in the PEP8, but I must have read it somewhere else. I have never left trailing ',' in a function/method definition or calling them, but usually use it for dicts and lists. Sorry for the misdirection. – Tim Hoffman Aug 23 '12 at 09:41

5 Answers5

71

There's no technical reason to avoid trailing commas in function calls, but some people might find them distracting. Some may wonder: Hmmm, is that comma supposed to be there?

One effect of using trailing commas in conjunction with an indented style is to make version control diffs look a little bit cleaner when adding an argument.

For example, a function like this:

def my_fun(a, b, c=None):
    ...

...called like this:

my_fun(
    a='abc',
    b=123
)

...then changed to this:

my_fun(
    a='abc',
    b=123,
    c='def'
)

produces this diff in git:

$ git diff
...
 my_fun(
     a='abc',
-    b=123
+    b=123,
+    c='def'
 )

Whereas,

my_fun(
    a='abc',
    b=123,
)

changed to...

my_fun(
    a='abc',
    b=123,
    c='def',
)

produces this diff in git:

$ git diff
...
 my_fun(
     a='abc',
     b=123,
+    c='def',
 )
Jacob Wan
  • 2,521
  • 25
  • 19
  • @icarus74, it's pretty common when you have 80 columns per line limit. – coderek Sep 28 '15 at 18:47
  • 4
    +1 My 5 cents: Use trailing commas for multiline function calls, as you would for multiline lists and dictionaries. Note that combining trailing comma with *-args (e.g. `f(*args, a, b, )`) is only [allowed from Python 3.5.0 onwards](https://bugs.python.org/issue9232). – qff Jan 10 '17 at 13:08
  • 3
    Starting in python3.6: in functions with starargs (`*args`, `**kwargs`, `*, kw=...`) trailing commas are now allowed – anthony sottile Jul 18 '17 at 18:49
  • 8
    The diff example is a strong argument to use trailing commas in function calls – xssChauhan Jul 18 '18 at 11:26
  • what does flake8 do here? – Zaffer Jan 22 '23 at 15:28
37

I'll also leave my 2 cents here, even if this thread has been here for quite some time, it might benefit somebody :)

PEP8 actually does say when to use trailing commas and if you follow their recommendations (not mandatory, but definitely recommended) then the second one-liner example of yours can be ruled out, i.e:

No:

self.call(1, True, "hi",)

Yes:

self.call(
    1,
    True,
    "hi",
)

Usages in function calls (use sparingly to never) and here's why:


  • One of the coding principles is that a function should do one thing, and one thing only. So, seeing a trailing comma there, a lot of questions may arise, when they really shouldn't. Normally when you see a trailing comma somewhere, you expect that thing to change over time. So if it's a list, tuple, dict, etc. it usually indicates that whoever designed it, did it with the intention of physically adding or removing or switching lines in that data structure, and well... you don't see that with functions very often, or at least you shouldn't, and if you do, a better design should be considered.

  • As aforementioned, a function should also be very predictable, you don't design a function that sends mail and rockets to the moon at the same time, and leave a trailing comma when calling it to send mail because who knows when you might send rockets and you want less cluttered diff (it will only cause more confusion and its a poor design).

  • An arbitrary number of parameters (or even a fixed, but large number of parameters) usually indicates that either you are either instantiating an object there, or you are doing multiple things, when really what you should be doing is split your design into creating multiple smaller functions, that each do one thing, hence, no trailing comma needed.

  • Also consider, even if you did have a function, which you would be able to call with multiple number of parameters, think about how often would you do that and what it implies? Well that would imply something like:

    • Refactoring the code at the call place (which may be in another function, or in a module or somewhere) because usually the result from functions is stored in variables, and you need to use that new result, so that would imply refactoring.
    • If it doesn't imply refactoring then it means the function doesn't return anything, or it returns the same thing, in which case it means that it does multiple things with the extra arguments passed in the call, which, as previously said, is not very ideal.

Actual usages


  • Trailing commas make sense, like you said in data structures, data structures that are expected to change physically over time, because if you change it at run-time, well it wouldn't make any sense for anything that's in the editor, except for the definition which might as well be an empty structure [] xD

  • Where data structures (lists, dicts, sets, tuples, etc) are expected to change (physically, the source code) then trailing commas are actually recommended and actually useful (see the full PEP link, it has use cases and recommendations)

Conclusion:


  • Recommended in multi-line data structures that are expected to physically change
  • Rarely to never in function calls
  • Never in function definitions
Marius Mucenicu
  • 1,685
  • 2
  • 16
  • 25
  • 1
    I know this is old, but I think trailing commas are not at all related to code design. Think of [factory functions](https://stackoverflow.com/a/11977454/9997212), for example. It may take a lot of parameters to create the class' attributes, so it may change regularly. Think of functions that only do one thing but there are a lot of options, like [this one](https://pandas.pydata.org/docs/reference/api/pandas.read_csv.html), as well as functions that uses kwargs. These kinds of functions are changing regularly, and one can add a trailing comma in these calls to support future changes. – enzo Oct 19 '21 at 19:31
  • I would also agree with @enzo, in the real world it's not always possible to anticipate all the features and there is always someone to ask you for a new feature you didn't expect. So yes, there are many situations where you can expect your list of functions arguments to grow and where it should be acceptable to use trailing commas. – Aratz Oct 13 '22 at 07:09
16

In data structures, the trailing comma is "useful" for making it easier to add items:

a = [
      1,
      2,
      3,
    ]

is easier to change into

a = [
      1,
      2,
      3,
      4,
      5,
    ]

because you don't have to edit the line that says 3,.

But there is no such benefit in function calls which usually don't change in length. So I would discourage the use of a trailing comma.

Tim Pietzcker
  • 328,213
  • 58
  • 503
  • 561
  • 1
    +1 for the truth. That list bracket indenting style makes me want to rip out my hair though :) – orlp Aug 23 '12 at 08:39
  • 5
    If a function takes variable number of arguments, the trailing comma wouldn't hurt. – Kos Aug 23 '12 at 08:45
  • @TimPietzcker: you're explaing how data structures work. Besides, for the second 2 options I gave, it COULD be as useful as in data structures. My question is more about 'which one is not possible? which one is recommended?' – taper Aug 23 '12 at 08:46
  • @Kos: can you give an example? – taper Aug 23 '12 at 08:47
  • @Kos: It doesn't hurt with a fixed number of arguments either. But since the number of arguments used to call a function rarely changes *in source code* (whereas the length of a list/tuple regularly changes in source), I don't see any practical use, and it's definitely distracting. – Tim Pietzcker Aug 23 '12 at 08:50
  • @TimPietzcker: I personally simply use 4 spaces to indent lists if formatted like this. Example: https://gist.github.com/3434470 – orlp Aug 23 '12 at 09:05
  • @taper Way late to the discussion, but one (and just about the only) place where I use a trailing comma in a function call is for `setup()` in setup.py. It's almost a dict-like usage of a function call, and occasionally there's need to modify the parameters (e.g. you add new functionality that needs `extras_require`) – Dominick Pastore Apr 06 '21 at 15:13
10

I think, in this matter the same reasons apply as for lists and tuples, because the function argument list is exactly that.

Here's a quote from the FAQ on design decisions that were made for the language (c.f.):

Why does Python allow commas at the end of lists and tuples?

Python lets you add a trailing comma at the end of lists, tuples, and dictionaries:

[1, 2, 3,]
('a', 'b', 'c',)
d = {
    "A": [1, 5],
    "B": [6, 7],  # last trailing comma is optional but good style
}

There are several reasons to allow this.

When you have a literal value for a list, tuple, or dictionary spread across multiple lines, it’s easier to add more elements because you don’t have to remember to add a comma to the previous line. The lines can also be reordered without creating a syntax error.

Accidentally omitting the comma can lead to errors that are hard to diagnose. For example:

x = [
  "fee",
  "fie"
  "foo",
  "fum"
]

This list looks like it has four elements, but it actually contains three: “fee”, “fiefoo” and “fum”. Always adding the comma avoids this source of error.

Allowing the trailing comma may also make programmatic code generation easier.

moooeeeep
  • 31,622
  • 22
  • 98
  • 187
2

This is tool specific, but it actually makes code refactoring much easier in vim/Gvim even on single line function parameter lists.

def foo( a, b, c, e, d, ):

changed to

def foo( a, b, c, d, e, ):

When using vim, you can just delete the "e," or "d," with two keystrokes (dW) move to where you want to paste it in and press (p).

If you didn't have the ending comma, you end up having to remove it from your new last item and adding it to your old last item. Alternately, you'd have to be more careful deleting only up until the comma and pasting more precisely. With comma's everywhere, you can treat everything as uniform chunks that can be swapped around with ease.

Vim's apparently quite popular with python writers so this actually appears to have some merit: https://www.sitepoint.com/which-code-editors-do-pythonists-use/

horta
  • 1,110
  • 8
  • 17