3

For example, I have a function which does something to data, and takes a name as an optional argument. If the name is not supplied, I want to call another argument to create the name. So the alternatives seem to be either

def do_something(data, name=get_name()):
    ...

or

def do_something(data, name=None):
    if name is None: 
        name=get_name()
    ...

The first one seems better to me, but am I missing something?

user6072577
  • 339
  • 5
  • 11
  • 10
    Yes: you are missing the fact that `get_name` will only ever be called once. See http://stackoverflow.com/questions/1132941/least-astonishment-and-the-mutable-default-argument – Daniel Roseman Feb 27 '17 at 15:06
  • Of course, that may be what you want... – Daniel Roseman Feb 27 '17 at 15:07
  • You can slightly shorten the second example as `name = name or get_name()`. But Daniel is right- the first example runs a risk of introducing very subtle bugs. – abought Feb 27 '17 at 15:09

2 Answers2

4

It's not the same thing.

get_name() is evaluated at function definition for the first case, and dynamically for the second case.

There are cases where you cannot use the first method anyway, like when using the return of a method call (self.method())

So stick to the second version. I don't know if it's more pythonic, but at least it is a good recipe and it works.

Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
0

I would write:

def do_something(data, func=get_name):
    func()

You pass the function and call it later. This is in-line with the function-is-an-object-thing in python and, therefore, is safe

jnsod
  • 66
  • 5
  • This assumes the caller is supposed to pass a function for this argument, which is not what the OP is doing. But for other situations where one is supposed to pass a function to a function this is a good solution. – SethMMorton Feb 27 '17 at 16:11
  • Right. Then I need if func == get_name: func = func() before calling func, which looks funny. I'd prefer the second option from the OP. – jnsod Feb 27 '17 at 16:32