Execute Program

Python for Programmers: Naming Conventions

Welcome to the Naming Conventions lesson!

This lesson is shown as static text below. However, it's designed to be used interactively. Click the button below to start!

  • Most Python identifiers (the names of variables, functions, methods, etc.) follow the snake_case convention: all lowercase, with underscores between words.

  • >
    number_of_snakes = 10
    eggs_per_snake = 5

    def get_egg_count():
    return number_of_snakes * eggs_per_snake

    get_egg_count()
    Result:
    50Pass Icon
  • The snake_case convention also applies to strings that are only intended for programmers. For example, strings used as dictionary keys normally follow snake_case.

  • >
    settings_dict = {
    "max_temperature": 40,
    "power_mode": "performance",
    }
    settings_dict.get("min_temperature", 20)
    Result:
    20Pass Icon
  • There are three notable exceptions to the snake_case convention: classes, constants, and private attributes. First, Python classes are normally UpperCamelCased.

  • >
    class WaterTank:
    def __init__(self, starting_amount):
    self.remaining_amount = starting_amount

    def drain(self, amount):
    if amount > self.remaining_amount:
    raise ValueError("Not enough water left in the tank")
    self.remaining_amount -= amount

    water_tank = WaterTank(1000)
    water_tank.drain(200)
    water_tank.remaining_amount
    Result:
    800Pass Icon
  • In JavaScript and many other languages, function calls and instantiation are clearly separated by the new keyword: user() calls a function, while new User() instantiates an object.

  • In Python, these use exactly the same syntax. Without additional context, we can't tell whether f() is calling a function named f or instantiating a class named f. UpperCamelCased class names reduce the ambiguity: user() is probably a function call, but User() is probably instantiating a class.

  • The second exception to snake_case is that constants are conventionally SHOUTED.

  • >
    INCHES_PER_FOOT = 12

    def feet_to_inches(feet):
    return feet * INCHES_PER_FOOT

    feet_to_inches(5)
    Result:
    60Pass Icon
  • The third exception is private attributes and methods, which shouldn't be accessed from outside of their class. The convention is to prefix private attribute and method names with an underscore, like _my_private_method. For example, we might have a FixedSizeBuffer class with a private _max_size attribute.

  • >
    # A class that only remembers up to n values at a time. When we add more than n
    # values, it drops the oldest ones to make room.
    class FixedSizeBuffer:
    def __init__(self, max_size):
    self._max_size = max_size
    self.values = []

    def add(self, value):
    self.values.append(value)
    if len(self.values) > self._max_size:
    self.values = self.values[-self._max_size:]
  • Note: this code example reuses elements (variables, etc.) defined in earlier examples.
    >
    buffer = FixedSizeBuffer(2)
    buffer.add("Amir")
    buffer.add("Betty")
    buffer.add("Cindy")
    buffer.values
    Result:
    ['Betty', 'Cindy']Pass Icon
  • It's important to note that constants and private methods are only naming conventions that Python programmers agree on. They're not language features, and Python doesn't enforce them!

  • If a name is UPPERCASE, then we all agree that its value shouldn't change. If an attribute starts with an _, then we all agree that we won't call it from outside the class.

  • However, Python will let us reassign "constants".

  • >
    # In Python, constants are SHOUTED by convention. But it's only a convention,
    # and Python will let us change the value of a "constant".
    PI = 3.14
    PI = 12
    PI
    Result:
    12Pass Icon
  • It will also let us read the "private" _max_size attribute from outside the class.

  • Note: this code example reuses elements (variables, etc.) defined in earlier examples.
    >
    # In Python, attributes and methods whose names begin with `_` are private, but
    # it's only a convention. Python will let us access "private" attributes.
    buffer = FixedSizeBuffer(2)
    buffer._max_size
    Result:
    2Pass Icon
  • (Python does have a separate language feature for private attributes. It's similar to the naming convention that we already saw: if an attribute name starts with __, Python will make some weak attempts to prevent access from outside of the class. But this is only a weak guarantee, and the feature is rarely used, so we won't discuss it in detail. We recommend sticking to a single underscore for private attributes and methods: self._max_size, not self.__max_size.)

  • There's one last naming convention issue to discuss. As in most languages, we can't use keywords like class, def, and while as variable names. However, we might write a function that takes a class as an argument, then does something with the class.

  • The convention is to append an underscore to the argument name: class_. Some Python code uses klass instead. We recommend the trailing underscore, since that pattern works for any keyword, not just class.

  • Note: this code example reuses elements (variables, etc.) defined in earlier examples.
    >
    def instantiate_class(class_, *args, **kwargs):
    return class_(*args, **kwargs)

    buffer = instantiate_class(FixedSizeBuffer, 3)
    buffer.add(1)
    buffer.add(2)
    buffer.add(3)
    buffer.add(4)
    buffer.values
    Result:
    [2, 3, 4]Pass Icon
  • We've seen a total of five conventions in this lesson:

    • snake_case variable and method names
    • CamelCaseClasses
    • CONSTANTS
    • _private_attributes
    • class_/klass
  • The Python community follows these conventions quite closely, but Python itself sometimes violates them.

  • Some parts of the standard library use camelCase, like the unittest module's .assertEquals method. That's because unittest copied the older JUnit API long ago. It was originally written in Java where camelCase is the norm.

  • In other cases, Python's evolution over time has left inconsistencies. For example, many built-in "functions" like int, range, etc. are actually classes, even though they're lower-cased. In earlier versions of Python, these were truly functions. When they were changed into classes, the Python core team maintained backwards compatibility by leaving the original lowercase names in place.

  • Sometimes, Python is just plain inconsistent. For example, dictionaries' .setdefault and .popitem methods both combine two words without an underscore. (.set_default and .pop_item would be more consistent.)

  • But Python's biggest inconsistency is probably True and False. They're not classes, but they're named like classes!

  • If you want to learn about all of the conventions, Python has an official style guide: PEP 8. ("PEPs" are "Python Enhancement Proposals", similar to RFCs.)

  • Complying with PEP 8 is relatively easy. The Black Python formatting tool is very popular, and it formats code to be PEP 8 compliant.

  • Although there are exceptions, Python code is still more consistent than most languages. PEP 8 is almost universally followed, so you're likely to see snake_cased methods and UpperCamelCased classes in any Python project.