Constructions
What if we need something more complex than just a custom init or new method?
Constructors, as most classmethods would be considered, are a common sight in other languages. They’re less common in Python but still really useful. I highly recommend playing around with them outside of this course and getting comfortable with them.
As for staticmethods, they’re…weird. A staticmethod is a method that doesn’t require an instance self
or a class cls
. So they belong to a class because, logically, they belong there. Most of the time, though, you’re better served by just creating a function in the same module as your class.
So, would it be possible to do create_bookcase without it being a classmethod? Yes and no. We could write the exact same method with a few differences, like using self instead of cls, and then leave off the decorator. We’d have to create an instance of the class first, though. It’d look something like this:
def create_bookcase(self, book_list):
for author, title in book_list:
self.append(Book(author, title))
return self
We could leave off that last line, too, but it’s generally a best practice to always have functions and methods return. Our use of it becomes a little weird to write out, though.
>>> Bookcase().create_bookcase([("Eric Matthes", "Crash Course Python")])
We have to create the instance first, with Bookcase() and then call the method. By using a class method, we move the instance creation into the method where it makes more sense. It’s a small and fairly subtle design decision but it makes for a nicer interaction in the end.
Example: Bookcase of Books
class Book:
def __init__(self, title, author):
self.title = title
self.author = author
def __str__(self):
return '{} by {}'.format(self.title, self.author)
class Bookcase:
def __init__(self, books=None):
self.books = books
@classmethod
def create_bookcase(cls, book_list):
books = []
for title, author in book_list:
books.append(Book(title, author))
return cls(books)
Testing
>>> bc = Bookcase.create_bookcase([('Title1','Author1'), ('Title2','Author2')])
>>> bc
<books.Bookcase object at 0x7f565ac0>
>>> str(bc.books[0])
'Title1 by Author1'