2

I'm currently learning curses in python, and I found this piece of code online that is confusing me.

import curses

def draw_menu(stdscr):
    # do stuff
    # if you want more code just let me know


def main():
    curses.wrapper(draw_menu)


if __name__ == "__main__":
    main()

When I run this I don't get the expected missing 1 required positional argument error, since there is no parameter being passed in the curses.wrapper(draw_menu) line. Is this a curses thing? Any help is greatly appreciated.

Have a nice day
  • 1,007
  • 5
  • 11
  • `curses.wrapper(draw_menu)` passes a parameter. The parameter is the function `draw_menu` itself. Important: It is the function, not the result of calling the function. This function might be called somewhere in `curses.wrapper` and `curses.wrapper` has to provide a parameter for that call. – Matthias Feb 18 '21 at 22:51
  • You aren't calling the function anywhere, so you shouldn't expect that error. – juanpa.arrivillaga Feb 18 '21 at 23:02

3 Answers3

2

A function is a datatype, just as much as strings, integers, and so on.

def my_function(txt):
  print(txt)

here type(my_function) # => <class 'function'>

You invoke the code inside the function when you call it with parenthesis : my_function('hello') # => prints hello

Until then you can perfectly pass a function as an argument to another function. And that last one can call the one you passed giving it some parameters.

Like in your case, I'd guess that curses.wrapper() creates a screen interface that it passes as argument your draw_menu() function. And you can probably use that screen object to build your curse app.

See this : Python function as a function argument?

Loïc
  • 11,804
  • 1
  • 31
  • 49
1

There's a big difference between curses.wrapper(draw_menu) and curses.wrapper(draw_menu()). curses.wrapper(draw_menu) calls curses.wrapper and passes the function draw_menu into it as an argument. In contrast, curses.wrapper(draw_menu()) would call draw_menu and pass its return value into curses.wrapper.

curses.wrapper will call the function you pass it. From that link:

Initialize curses and call another callable object, func, which should be the rest of your curses-using application.

E.g., it will call draw_menu when curses is completely initialized.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
0

Here is the signature for curses.wrapper from here.

curses.wrapper(func, /, *args, **kwargs)

It says that you need to give curses.wrapper a function reference argument followed by zero or more arguments and keyword arguments. Your code satisfies those requirements.

Python allows function signatures like this to enable developers a lot of flexibility regarding what can be passed in by the caller.

rhurwitz
  • 2,557
  • 2
  • 10
  • 18