On Thu, Sep 29, 2016 at 09:43:57PM -0500, boB Stepp wrote: > I believe I understand the barebone mechanics on how to do this. But > I do not understand the rationale of why Python does it the way it > does. Say > > def f(g, *args): > g(*args)
Right. This says: - Define a function called "f", which takes one named parameter, "g", and collect any other arguments under the name "args". - For the body of "f", simply call that argument "g" with all the other arguments. You probably want `return g(*args)` rather than just `g(*args)`. > def g(*args): > # Do something. > > do_things = f(g, *args) As it stands now, f() is a middle-man that adds nothing to the picture. In practice, to be worth calling f() rather than just calling g() directly, you would want it to do some sort of additional processing: either manipulate the arguments, or the result returned by g(). > is the outline of how I understand the mechanics of doing this. But > noob boB initially want to do instead: > > def f(g(*args)): > g(*args) [...] > which, of course, will give me a syntax error. Of course. I'm not sure what you think a parameter called "g(*args)" even means. When you write this: def f(x): return x+1 do you feel the need to write: def f(x+1): return x+1 instead? I expect not. Can you see how the two situations are equivalent? My example uses +1, your example uses "call the function with these arguments" instead, but the two are otherwise equivalent. In common English, there is a simple name for the +1 part of x+1, namely "plus one" or "add one" or similar. But I don't know of any simple name for the `(*args)` part of `g(*args)`. "Call g with given arguments" perhaps, but that's not really simple. The situations are conceptually the same: + is a binary (two argument) operator that takes the object on the left, x, and the object on the right, 1, and adds them together; () is an n-ary (n arguments) operator (or perhaps "pseudo-operator" if you prefer) that takes the object on the left, g, and the multiple arguments inside the brackets, *args, and applies the arguments to function g. > Also, I note that if I just type a function name without the > parentheses in the interpreter, I will get something like this: > > >>> def f(): > pass > > >>> f > <function f at 0x000001F775A97B70> > > So the impression I am getting is that a function name by itself (with > no parentheses) is the function *object*. Correct. > But why does Python require > separating the function object from its parameters when it is being > passed as an argument to another function? If you pass the function arguments to the function *first*, then it gets evaluated before the second function gets to see it. Let's investigate: def g(*args): print("Calling function g with arguments {}".format(args)) return 999 def f(func, *args): print("f received first argument: {}".format(func)) print("f received additional arguments: {}".format(args)) return func(*args) Let's try it the right way: py> f(g, 1, 2, 3) f received first argument: <function g at 0xb7ac965c> f received additional arguments: (1, 2, 3) Calling function g with arguments (1, 2, 3) 999 And the wrong way: py> f(g(1, 2, 3)) Calling function g with arguments (1, 2, 3) f received first argument: 999 f received additional arguments: () Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 4, in f TypeError: 'int' object is not callable Does this help? -- Steve _______________________________________________ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor