Recording loans of access cards to people in a company I'm fairly new to Python and currently building a small application to record loans of access cards to people in a company. I'm using wxPython for the GUI and SQLAlchemy for the CRUD. I'm loosely following Mike Driscoll's tutorial for a similar application but I want to add some extra things that he hasn't implemented (he has most controls in the same window, but I'm passing things a lot between dialogues and windows and it's starting to look messy).

Particularly concerned about the following method in dialogs.py:

def OnCardReturn(self, event):
    """
    Call the controller and get back a list of objects. If only one object
    return then set that loan as returned. If none returned then error, no
    loans currently on that card. If more than one returned something has 
    gone wrong somewhere, but present a list of the loans against that card
    for the user to pick the correct one to return.
    """

    value = self.txtInputGenericNum.GetValue()
    loans = controller.getQueriedRecords(self.session, "card", value)    #returns a list of objects
    numLoans = len(loans)
    if numLoans == 1:
        controller.returnLoan(self.session, value)    #returns nothing
        successMsg = "Card " + str(value) + " has been marked as returned"
        showMessageDlg(successMsg, "Success!")
    elif numLoans == 0:
        failureMsg = "Card " + str(value) + " is not currently on loan"
        showMessageDlg(failureMsg, "Failed", flag="error")
    elif numLoans &gt; 1:
        failureMsg = """
        More than one loan for " + str(value) + " exists. Please select
        the correct loan to return from the next screen.
        """
        showMessageDlg(failureMsg, "Failed", flag="error")
        selectReturnLoan = DisplayList(parent=self, loanResults=loans,
                                                        returnCard=True)
        selectReturnLoan.ShowModal()
        selectReturnLoan.Destroy()


The controller is still under construction, so no complete code yet, but I've commented in what is returned by the calls to it so it's still possible to see what the functionality is.
Inline comments should only be used sparingly, and definitely not on already long lines. Your #returns a list of objects is pretty unnecessary both because it's overly long, but also because it's inferrable and doesn't seem to matter. You only pass the loans on unchanged so the user doesn't care that they're a list of objects. You can infer that it's a collection of something because of the name loans and the len usage. And that's all you need to know in this function, so forget that comment.

You should also format your docstring so it contains just one line summarising the function, a blank line and then the further details. You just have one long block but it's hard to read from it what the function should do. Instead you detail the possible results.

Instead of using str and concatenation, just use str.format. It's a convenient way of formatting strings and coverting their type at the same time:

    successMsg = "Card {} has been marked as returned".format(value)


Also note that you haven't correctly inserted this value in the failureMsg of numLoans &gt; 1. You just have the string literal " + str(value) + ". You'd need the extra quotation marks to do it your way:

    failureMsg = """
    More than one loan for """ + str(value) + """ exists. Please select
    the correct loan to return from the next screen.
    """


But instead I'd suggest using str.format again.