Python naming conventions for interfaces and abstract classes?
I'm not aware of any community-wide standards in that regard apart from PEP8, which doesn't address this specifically.
I'd suggest to do whatever your team is most comfortable with, but above all else be consistent.
I think naming an interface with an I
prefix is perfectly acceptable.
e.g.:
IFoo
IPublishable
A few years back I used Zope Interfaces. I noticed most codebases used this convention. Our team did too.
We preferred IFoo
vs. FooInterface
or IFooInterface
I would look towards the number tower (from numbers
), the collection ABCs (from collections.abc
), or the other core ABCs (such as importlib.abc
) for the most "Pythonic" way to do this.
The consensus from this is to just name them as-is, and let human understanding recognize them as abstract.
TL;DR
If you don't care about type hints, name them whatever you like. Otherwise, ABC
s are your API for other developers. Their names should be clean without any clutter. The concrete implementation should tell you why it is special.
Call your abstract class User
and the implementing classes ServerUser
and LocalUser
Why would we need such a convention in the first place?
The first one should ask themselves is, why would we care about naming of classes?
In statically typed languages (which python is not), the names of your Interfaces represent an API through which other developers interact with your code. So the caller of a function should quickly understand the meaning of parameters and return types. An example from Java (where prefixing Interfaces has fallen out of fashion some time ago..) would be:
public void signupUsers(Collection<User> users) {
// TODO: do something with users
}
Here we want the name to be as pure as possible. We accept any Collection
and any User
. It might be an ArrayList
, HashSet
, LocalUser
or a ServerUser
, we don't care.
Why is there no such standard in Python?
This was not relevant in python, since it is a dynamically typed language. In the following code, you don't care how the classes are called:
def signup_users(users):
pass # TODO: do something with users
The name would have only been relevant when creating a class and checking its type, which are not common enough to justify a full blown naming convention
Why would someone care about naming of classes in Python nowadays?
But things are changing, because of the introduction of the typing module. You can now explicitly state types. If we want to embrace this new feature, we should consider the naming of our classes.
So what names should our classes get?
By the same logic as to why other languages are ditching the prefixes for interfaces, I believe ABC
s (if they play a similar role to interfaces) should have a clean name. A name like User
is much nicer to read than IUser
. If you have a concrete implementation of your user, the name of that implementation should tell you what is special about it. Is it a user which data is updated with data from a server? Call it ServerUser
. Do you store the user data locally? Call it LocalUser
.
def signup_users(users: Iterable[User]) -> None:
pass # TODO: do something with users
The "ugly" code which cares about the implementation details would look like this:
lovelace = LocalUser("Aida", "Lovelace", 1815)
babbage = ServerUser("htts://some_service.com/users/charles_babbage")
signup_users([aida, babbage])
This puts the burden of dealing with convoluted names on the caller who has to deal with the implementation - as it should