Object-oriented student library
In addition to the below, I recommend reading Maarten Fabré's answer.



Edge case

Consider the following scenario:

book_tracking = StudentDatabase()
book_tracking.return_book("Student A", "Moby Dick")
# KeyError: 'Student A'


However, we don't need to do a try-except block to catch the student who never handled books before trying to return a book; Python provides defaultdict in the collections module to help us with this very problem:

from collections import defaultdict

class StudentDatabase:
    def __init__(self):
        self._books = defaultdict(list)

    # ...


Now, if anything tries to access an unassigned key of _books, it will simply return an empty list. This can subsequently simplify borrow_book():

    def borrow_book(self, name, book):
        self._books[name].append(book)


Interclass operability

Library and StudentDatabase don't seem to interact at all. If they're related, the student database listing book borrows should inform the library when a book is borrowed or returned. The most versatile way to do this at this stage is to add a library parameter to relevant methods.

class StudentDatabase:
    # ...

    def borrow_book(self, name, book, library):
        if library.lend_book(book):
            self._books[name].append(book)

    def return_book(self, name, book, library):
        if book not in self._books[name]:
            print("You don't seem to have borrowed \"%s\"" % book)
        else:
            library.add_book(book)
            self._books[name].remove(book)


This will require returning False when the book is not found:

class Library:

    # ...

    def lend_book(self, requested_book):
        if requested_book in self._books:
            print("You have now borrowed \"%s\" " % requested_book)
            self._books.remove(requested_book)
            return True

        else:
            print("Sorry, \"%s\" is not there in our library at the moment" % requested_book)
            return False


The implementation you currently have is very simple, so there's not much else to discuss in terms of design: it becomes more relevant when you have more moving parts. I do find it somewhat odd that it's only tracking by student, and not by book (i.e. Library could know how many copies of each book it had (int), to whom it's checked (a list perhaps with a custom CheckedOut class to store the person and the due date), and any other information pertaining to that book. A BookStatus class could store everything related to each book; the library would then contain a list of BookStatus objects.

Checking if a sequence is empty.

(Note I previously advocated using len(self._books) &gt; 0 until Maarten Fabré (along with three people upvoting his comment) pointed out this suggestion contradicted PEP-8) The relevant passage is excerpted below.


  For sequences, (strings, lists, tuples), use the fact that empty sequences are false.


Format string literals

You seem to be using printf-style string formatting. In Python 3, format strings are more flexible and would probably be considered more Pythonic. Python 3.6 adds format string literals, which are very compact. Here are some example uses:


Original: "You have now borrowed \"%s\" " % requested_book


With f-string: f"You have now borrowed \"{requested_book}\"."

Original: "Sorry, \"%s\" is not there in our library at the moment" % requested_book


With f-string: f"Sorry, \"{requested_book}\" is not there in our library at the moment"

Original: "You don't seem to have borrowed \"%s\"" % book


With f-string: f"You don't seem to have borrowed \"{book}\""

Original: "%s: %s" % (name, books)


With f-string: f"{name}: {books}"



Result

from collections import defaultdict

class Library:
    def __init__(self):
        self._books = []

    def add_book(self, new_book):
        self._books.append(new_book)

    def display_books(self):
        if len(self._books) &gt; 0:
            print("The books we have made available in our library are:\n")
            for book in self._books:
                print(book)
        else:
            print("Sorry, we have no books available in the library at the moment")

    def lend_book(self, requested_book):
        if requested_book in self._books:
            print(f"You have now borrowed \"{requested_book}\".")
            self._books.remove(requested_book)
            return True

        else:
            print(f"Sorry, \"{requested_book}\" is not there in our library at the moment")
            return False

class StudentDatabase:
    def __init__(self):
        self._books = defaultdict(list)

    def get_student(self, name):
        if name not in self._books:
            return "Not Found"

        return self._books[name]

    def borrow_book(self, name, book, library):
        if library.lend_book(book):
            self._books[name].append(book)

    def return_book(self, name, book, library):
        if book not in self._books[name]:
            print(f"You don't seem to have borrowed \"{book}\"")
        else:
            library.add_book(book)
            self._books[name].remove(book)

    def display_students_with_books(self):
        for name, books in self._books.items():
            if books:
                print(f"{name}: {books}")