I'm working on a simple decorator that creates and manages a database cursor.  The goal is to 'inject' the cursor as the first argument of the function, but not expose it to the caller.Usage:import psycopg2@needsNewCursordef findItem(cursor, item_id):    cursor.execute('SELECT name FROM items WHERE id = %s', [item_id])    item_result = cursor.fetchone()    # ...    return item# caller only needs to know about the IDfindItem(1234)Decorator:def needsNewCursor(func):    def decorator(*args, **kargs):        print 'Creating new cursor'        # This is slightly different in the final code, but I'm only        # concerned about how I'm dealing with decorators, at the moment        cursor = createDefaultCursor()        if cursor:            with cursor:                # Pass the cursor in as the 1st param                return func(cursor, *args, **kargs)        # Give the function a chance to deal with fails        return func(None, *args, **kargs)    # QUESTION: Is this enough?    decorator.__name__ = func.__name__    return decoratorIs this a good approach?
Simple decorator for creating and managing a database cursor
python;beginner;cursor
No, I don't think this is a good approach. Anyone who sees the declaration def findItem(cursor, item_id): will call the function with two arguments and scratch one's head to no end when it does not work.You could just as well have cursor = createDefaultCursor() as the first line of each function that uses a cursor. The number of lines does not increase as you can omit the @needsNewCursor line.Even better might be to create a context manager to deal with opening and closing a cursor and start each function with a statement like with new_cursor() as cursor:. A context manager also has an opportunity to deal with exceptions raised in the with block.Anyway, when writing decorators, instead of assigning yourself decorator.__name__ = func.__name__ you can apply the functools.wraps decorator that also copies the docstring.One more thing: in your example needsNewCursor is a decorator. You should choose a different name for the inner function. 