Search code examples
pythonclasspython-importpython-modulenaming

Explicit naming or explicit path, what is the more pythonic way of naming and using classes?


I'm working on a project where we currently design a bunch of repositories to abstract the database access.

We found mainly two different ways of naming, structuring and using the newly design repository interfaces and implementations.

Our questions is: Which way is more pythonic and which is more commonly used?

Option A

Give classes and module very explicit names but have a lot of redundancy in the combination of module and class naming. See below.

Files

# Hierarchy of files and folders:
.
├── repositories/
│   price_forecast_repository_interface.py  # Contains PriceForecastRepositoryInterface
│   ├── sql/
│   │   price_forecast_sql_repository.py    # Contains PriceForecastSqlRepository
├── domain/
│   price_forecast.py                       # Contains the PriceForecast business model

Usage

from repositories.sql import PriceForecastSqlRepository
from repositories import PriceForecastRepositoryInterface
from domain import PriceForecast

foo = PriceForecastSqlRespoitory(...)
business_model = PriceForecast(1, 2, 3)

Option B

Call everything the same, but distinguish it by the package/module it comes from.

Files

# Hierarchy of files and folders:
.
├── repositories/
│   price_forecast.py        # Contains PriceForecast as an ABC
│   ├── sql/
│   │   price_forecast.py    # Contains PriceForecast as an SQL implementation
├── domain/
│   price_forecast.py        # Contains the PriceForecast business model

Usage

import repositories.sql
import repositories
import domain

foo = repositories.sql.PriceForecast(...) 
business_model = domain.PriceForecast(1, 2, 3)

We see that both options would work perfectly, if we are consistent and strict – so it is likely more a question or style, but:

Are there major draw-backs to one solution? I ask, because we see pros and cons but no clear swing into one direction.

Which way is more pythonic and which is more commonly used?


Solution

  • As you said, you could make any of these work, and many projects handle it different ways. There is a little guidance here from the PEP 8 style guide though:

    Modules should have short, all-lowercase names. Underscores can be used in the module name if it improves readability. Python packages should also have short, all-lowercase names, although the use of underscores is discouraged.

    For the purpose of clarity and readability, you should probably use a combination of A and B. price_forecast_repository_interface.py clearly violates PEP 8 by being far too long, but naming all of your files the exact same thing is going to cause even more issues by making it more difficult to trace errors, communicate with other developers, and keep track of what is where. Maybe you could try something like forecast_interface, forecast_sql, and forecast_model, if that makes sense for your application.

    For the class names, I would definitely recommend using the class names you suggested in option A. The only guideline PEP 8 gives for class names is that they should be in PascalCase (they call it CapWords), but having clear names for classes is very important.

    To make it less annoying to type out when you're using these classes in other files, when you import the modules, you can use the import x as y syntax to shorten the names without sacrificing readability. Many Python libraries do this as a standard. For example, the numpy library always uses import numpy as np in their example code, and all of their documentation uses np in code snippets instead of the full name. In your case, maybe you could use

    from repositories.sql import PriceForecastSqlRepository as SqlRepository 
    

    or something similar.