Naming conventions are standardized rules for naming variables, functions, classes, and other elements in your code. Good naming makes your code more readable, maintainable, and professional. It's like having a consistent style guide that helps everyone understand your code quickly.
Python follows the PEP 8 style guide, which provides official recommendations for how to name different elements in Python code.
example:
# Poor naming
x = "John"
y = 25
z = x + " is " + str(y) + " years old"
# Good naming following conventions
user_name = "John"
user_age = 25
greeting_message = f"{user_name} is {user_age} years old"
Python uses different naming styles for different types of identifiers:
# Variables
first_name = "Alice"
total_price = 199.99
is_logged_in = True
# Functions
def calculate_total_cost():
pass
def send_email_notification():
pass
# Module names
import user_authentication
import payment_processor
# Constants - values that never change
MAX_ATTEMPTS = 3
DEFAULT_TIMEOUT = 30
API_BASE_URL = "https://api.example.com"
PI = 3.14159
# Configuration values
DATABASE_HOST = "localhost"
DEFAULT_PAGE_SIZE = 20
# Class names
class UserAccount:
pass
class PaymentProcessor:
pass
class EmailValidator:
pass
class ShoppingCart:
pass
# This style is common in other languages but NOT recommended in Python
# Avoid: firstName, lastName, calculateTotal
# Use instead: first_name, last_name, calculate_total
# Poor - unclear what these variables represent
a = 3.14159
b = 5
c = a * b * b
# Good - clear and descriptive
pi = 3.14159
radius = 5
circle_area = pi * radius * radius
# Even better - with proper context
PI = 3.14159 # Constant
circle_radius = 5 # meters
circle_area = PI * circle_radius ** 2
# Poor abbreviations
usr_nm = "Sarah"
calc_tot = 150.75
temp_val = 42
# Better - full words
user_name = "Sarah"
calculated_total = 150.75
temperature_value = 42
# Exception: commonly understood abbreviations are okay
max_attempts = 3 # "max" is widely understood
min_password_length = 8 # "min" is acceptable
url = "https://example.com" # "url" is standard
# Poor - similar names that are confusing
user_data = {"name": "Tom", "age": 30}
user_info = {"email": "tom@email.com", "phone": "123-456-7890"}
user_details = {"address": "123 Main St", "city": "Boston"}
# Better - specific, meaningful names
user_profile = {"name": "Tom", "age": 30}
user_contact = {"email": "tom@email.com", "phone": "123-456-7890"}
user_address = {"street": "123 Main St", "city": "Boston"}
# Use verbs or adjectives that clearly indicate true/false
is_valid = True
has_permission = False
can_edit = True
should_save = False
user_authenticated = True
# Avoid ambiguous boolean names
# Poor
flag = True # What does this flag represent?
status = False # What status?
# Good
is_file_uploaded = True
email_sent_successfully = False
# Functions should describe what they do
def calculate_total_price(items):
"""Calculate the total price of items in cart."""
return sum(item['price'] for item in items)
def validate_email_address(email):
"""Check if email address format is valid."""
return '@' in email and '.' in email
def send_welcome_email(user_email):
"""Send welcome email to new user."""
# Email sending logic here
pass
def update_user_profile(user_id, new_data):
"""Update user profile with new information."""
# Database update logic here
pass
# Getter functions - retrieve information
def get_user_by_id(user_id):
"""Retrieve user information by ID."""
pass
def fetch_latest_orders():
"""Fetch the most recent orders from database."""
pass
# Setter functions - modify information
def set_user_password(user_id, new_password):
"""Set new password for user."""
pass
def update_inventory_count(item_id, new_count):
"""Update inventory count for specific item."""
pass
# Boolean return functions - start with is_, has_, can_, should_
def is_user_admin(user_id):
"""Check if user has admin privileges."""
return True # Example return
def has_valid_subscription(user_id):
"""Check if user has active subscription."""
return False # Example return
def can_user_edit_post(user_id, post_id):
"""Check if user has permission to edit post."""
return True # Example return
class User:
"""Represents a user in the system."""
def __init__(self, name, email):
self.name = name
self.email = email
class ShoppingCart:
"""Manages items in a shopping cart."""
def __init__(self):
self.items = []
class EmailValidator:
"""Validates email addresses."""
@staticmethod
def is_valid(email):
return '@' in email and '.' in email
class PaymentProcessor:
"""Handles payment processing operations."""
def process_payment(self, amount, payment_method):
# Payment processing logic
pass
class BankAccount:
"""Represents a bank account."""
# Class variables (shared by all instances)
minimum_balance = 0 # snake_case
ACCOUNT_TYPES = ['checking', 'savings', 'business'] # UPPER_CASE for constants
def __init__(self, account_holder, initial_balance):
# Public attributes (accessible from outside)
self.account_holder = account_holder # snake_case
self.balance = initial_balance
# Private attributes (internal use, start with underscore)
self._account_number = self._generate_account_number()
self._transaction_history = []
# "Protected" attributes (convention, not enforced)
self._creation_date = "2025-06-20"
def deposit(self, amount):
"""Public method - snake_case."""
if self._is_valid_amount(amount):
self.balance += amount
def _is_valid_amount(self, amount):
"""Private method - starts with underscore."""
return amount > 0
def _generate_account_number(self):
"""Private method for internal use."""
import random
return f"ACC{random.randint(10000, 99999)}"
# Application constants
APP_NAME = "Customer Management System"
VERSION = "1.2.3"
DEFAULT_LANGUAGE = "english"
# Mathematical constants
PI = 3.14159265359
SPEED_OF_LIGHT = 299792458 # meters per second
GOLDEN_RATIO = 1.618033988749
# Configuration settings
MAX_FILE_SIZE = 5242880 # 5MB in bytes
DEFAULT_TIMEOUT_SECONDS = 30
ALLOWED_FILE_TYPES = ['jpg', 'png', 'pdf', 'doc']
# Database configuration
DATABASE_HOST = "localhost"
DATABASE_PORT = 5432
MAX_CONNECTION_ATTEMPTS = 3
# API settings
API_BASE_URL = "https://api.example.com/v1"
REQUEST_TIMEOUT = 10
MAX_RETRIES = 3
# Option 1: Using a class as a namespace
class Colors:
"""Color constants for the application."""
RED = "#FF0000"
GREEN = "#00FF00"
BLUE = "#0000FF"
WHITE = "#FFFFFF"
BLACK = "#000000"
class HttpStatus:
"""HTTP status code constants."""
OK = 200
NOT_FOUND = 404
INTERNAL_ERROR = 500
UNAUTHORIZED = 401
# Usage
background_color = Colors.WHITE
response_code = HttpStatus.OK
# Option 2: Using module-level constants with prefixes
COLOR_RED = "#FF0000"
COLOR_GREEN = "#00FF00"
COLOR_BLUE = "#0000FF"
HTTP_OK = 200
HTTP_NOT_FOUND = 404
HTTP_INTERNAL_ERROR = 500
# Good module names (all lowercase, underscores if needed)
# user_authentication.py
# email_sender.py
# data_processor.py
# payment_utils.py
# Import examples
import user_authentication
import email_sender
from data_processor import clean_data
from payment_utils import calculate_tax
# Avoid
# UserAuthentication.py # Don't use PascalCase for modules
# email-sender.py # Don't use hyphens
# dataProcessor.py # Don't use mixedCase
# Project structure with good naming
my_web_app/
__init__.py
main.py
config.py
models/
__init__.py
user_model.py
product_model.py
views/
__init__.py
user_views.py
product_views.py
utils/
__init__.py
email_utils.py
validation_utils.py
date_helpers.py
# Simple loops - single letters are acceptable
for i in range(10):
print(i)
# List iterations - use descriptive names
students = ["Alice", "Bob", "Charlie"]
for student in students:
print(f"Hello, {student}")
# Dictionary iterations
user_scores = {"Alice": 95, "Bob": 87, "Charlie": 92}
for student_name, score in user_scores.items():
print(f"{student_name}: {score}")
# Nested loops - be more descriptive
grade_matrix = [[85, 90, 78], [92, 88, 95], [79, 83, 91]]
for student_index, student_grades in enumerate(grade_matrix):
for subject_index, grade in enumerate(student_grades):
print(f"Student {student_index}, Subject {subject_index}: {grade}")
# Exception variable naming
try:
result = int(user_input)
except ValueError as conversion_error:
print(f"Could not convert input: {conversion_error}")
try:
file_content = open("data.txt").read()
except FileNotFoundError as file_error:
print(f"File not found: {file_error}")
except PermissionError as permission_error:
print(f"Permission denied: {permission_error}")
# Acceptable temporary variable names for short-lived variables
def process_data(data_list):
# Temporary variables with clear context
temp_total = 0
temp_count = 0
for item in data_list:
temp_total += item['value']
temp_count += 1
average = temp_total / temp_count if temp_count > 0 else 0
return average
# Even better - avoid temp variables when possible
def process_data_improved(data_list):
if not data_list:
return 0
total_value = sum(item['value'] for item in data_list)
item_count = len(data_list)
return total_value / item_count
# Misleading - this function doesn't just calculate, it also saves
def calculate_user_score(user_id, test_answers):
score = evaluate_answers(test_answers)
save_score_to_database(user_id, score) # Unexpected side effect!
return score
# Better - name reflects all actions
def calculate_and_save_user_score(user_id, test_answers):
score = evaluate_answers(test_answers)
save_score_to_database(user_id, score)
return score
# Or separate the concerns
def calculate_user_score(test_answers):
return evaluate_answers(test_answers)
def save_user_score(user_id, score):
save_score_to_database(user_id, score)
# Inconsistent - mixing naming styles and terms
def getUserData(user_id): # mixedCase (not Python style)
pass
def get_user_info(user_id): # snake_case
pass
def fetchUserDetails(user_id): # mixedCase + different verb
pass
# Consistent - same style and pattern
def get_user_data(user_id):
pass
def get_user_profile(user_id):
pass
def get_user_preferences(user_id):
pass
# Avoid Python keywords and built-in function names
# Bad
list = [1, 2, 3] # Shadows built-in list() function
str = "hello" # Shadows built-in str() function
type = "user" # Shadows built-in type() function
# Good
item_list = [1, 2, 3]
user_name = "hello"
user_type = "admin"
# If you must use a keyword-like name, add underscore
class_ = "Math101" # Instead of using 'class'
from_ = "sender@email.com" # Instead of using 'from'
class Product:
"""Represents a product in the e-commerce system."""
# Class constants
PRODUCT_STATUSES = ['active', 'discontinued', 'out_of_stock']
DEFAULT_CATEGORY = 'general'
def __init__(self, product_name, product_price, category_name=None):
# Public attributes
self.product_name = product_name
self.product_price = product_price
self.category_name = category_name or self.DEFAULT_CATEGORY
self.is_available = True
# Private attributes
self._product_id = self._generate_product_id()
self._creation_timestamp = self._get_current_timestamp()
def update_product_price(self, new_price):
"""Update the product price with validation."""
if self._is_valid_price(new_price):
old_price = self.product_price
self.product_price = new_price
self._log_price_change(old_price, new_price)
return True
return False
def calculate_discounted_price(self, discount_percentage):
"""Calculate price after applying discount."""
if not self._is_valid_discount(discount_percentage):
raise ValueError("Invalid discount percentage")
discount_amount = self.product_price * (discount_percentage / 100)
discounted_price = self.product_price - discount_amount
return round(discounted_price, 2)
def _is_valid_price(self, price):
"""Private method to validate product price."""
return isinstance(price, (int, float)) and price >= 0
def _is_valid_discount(self, discount):
"""Private method to validate discount percentage."""
return 0 <= discount <= 100
def _generate_product_id(self):
"""Generate unique product ID."""
import uuid
return f"PROD_{uuid.uuid4().hex[:8].upper()}"
def _get_current_timestamp(self):
"""Get current timestamp for record keeping."""
import datetime
return datetime.datetime.now()
def _log_price_change(self, old_price, new_price):
"""Log price changes for audit trail."""
print(f"Price changed: {old_price} -> {new_price}")
class ShoppingCart:
"""Manages items in a customer's shopping cart."""
MAX_ITEMS_PER_CART = 50
def __init__(self, customer_id):
self.customer_id = customer_id
self.cart_items = []
self.total_amount = 0.0
self.item_count = 0
def add_product_to_cart(self, product, quantity=1):
"""Add product to cart with specified quantity."""
if not self._can_add_items(quantity):
raise ValueError(f"Cannot exceed {self.MAX_ITEMS_PER_CART} items")
cart_item = {
'product': product,
'quantity': quantity,
'item_total': product.product_price * quantity
}
self.cart_items.append(cart_item)
self._update_cart_totals()
def remove_product_from_cart(self, product_id):
"""Remove product from cart by product ID."""
original_length = len(self.cart_items)
self.cart_items = [
item for item in self.cart_items
if item['product']._product_id != product_id
]
if len(self.cart_items) < original_length:
self._update_cart_totals()
return True
return False
def calculate_cart_total(self):
"""Calculate total amount for all items in cart."""
return sum(item['item_total'] for item in self.cart_items)
def _can_add_items(self, quantity):
"""Check if items can be added without exceeding limit."""
return self.item_count + quantity <= self.MAX_ITEMS_PER_CART
def _update_cart_totals(self):
"""Update cart totals after modifications."""
self.total_amount = self.calculate_cart_total()
self.item_count = sum(item['quantity'] for item in self.cart_items)
# Usage example with good naming
def process_customer_order():
"""Process a customer order with proper naming throughout."""
# Create products with descriptive names
laptop_product = Product("Gaming Laptop", 1299.99, "Electronics")
mouse_product = Product("Wireless Mouse", 49.99, "Electronics")
# Create shopping cart
customer_cart = ShoppingCart("CUST_12345")
# Add products to cart
customer_cart.add_product_to_cart(laptop_product, quantity=1)
customer_cart.add_product_to_cart(mouse_product, quantity=2)
# Calculate totals
cart_total = customer_cart.calculate_cart_total()
item_count = customer_cart.item_count
print(f"Cart Total: ${cart_total:.2f}")
print(f"Total Items: {item_count}")
Good naming conventions make your code more professional and maintainable:
Key Python Naming Rules:
- Variables and functions: snake_case
- Classes: PascalCase
- Constants: UPPER_CASE
- Private attributes: _leading_underscore
- Modules: lowercase_with_underscores
Best Practices:
- Use descriptive, meaningful names
- Be consistent throughout your codebase
- Avoid abbreviations and single letters (except for short loops)
- Use verbs for functions, nouns for classes
- Follow the single responsibility principle in naming
- Make boolean variables clearly indicate true/false
Remember:
- Code is read more often than it's written
- Good names reduce the need for comments
- Consistency is more important than personal preference
- Follow PEP 8 guidelines for Python-specific conventions
Investing time in good naming conventions will make your code more professional, readable, and maintainable for yourself and other developers!