Имена переменных в Python — правила, соглашения и лучшие практики
Правила именования переменных в Python, соглашения PEP 8, зарезервированные ключевые слова и типичные ошибки — с примерами и пояснениями.
Имя переменной — это метка, по которой Python находит значение в памяти. Хорошие имена делают код читаемым почти как предложение; плохие — и через неделю вы сами с трудом разберёте собственный скрипт. В этой главе рассматриваются жёсткие правила Python, мягкие соглашения сообщества (PEP 8), ловушки вроде перекрытия встроенных имён и специальные паттерны с подчёркиванием — всё с запускаемыми примерами.
Жёсткие правила — что требует Python
Прежде чем говорить о соглашениях, разберём правила. Нарушение любого из них приводит к SyntaxError или NameError.
Допустимые символы
Имя переменной может содержать буквы (a-z, A-Z), цифры (0-9) и символы подчёркивания (_). Оно должно начинаться с буквы или символа подчёркивания — никогда с цифры. Пробелы, дефисы и специальные символы (%, #, @, -) не допускаются.
# Valid names
user_name = "Alice"
_private = 42
value1 = 3.14
MAX_RETRIES = 5
# Invalid names — these all raise SyntaxError
# 1user = "bad" # starts with a digit
# user-name = "bad" # hyphens are subtraction
# user name = "bad" # space is not allowedPython чувствителен к регистру
username, Username и USERNAME — это три совершенно разные переменные. Это частый источник ошибок у начинающих.
score = 10
Score = 20
SCORE = 30
print(score) # 10
print(Score) # 20
print(SCORE) # 30Зарезервированные ключевые слова нельзя использовать как имена
Python резервирует определённые слова для нужд языка. Использование одного из них в качестве имени переменной вызывает SyntaxError. Все зарезервированные ключевые слова можно посмотреть с помощью модуля keyword:
import keyword
print(keyword.kwlist)Вывод (Python 3.12):
['False', 'None', 'True', 'and', 'as', 'assert', 'async', 'await',
'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except',
'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is',
'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try',
'while', 'with', 'yield']Распространённые ошибки: использование list, str, int, type или input в качестве имён переменных — это встроенные имена, а не зарезервированные ключевые слова, поэтому Python не вызовет SyntaxError, но вы молча перекроете встроенное имя и получите непонятные ошибки позже (см. Перекрытие встроенных имён ниже).
Соглашения об именовании PEP 8
PEP 8 — официальный стайлгайд Python. Следование ему делает ваш код сразу понятным любому Python-разработчику.
Краткая сводка соглашений
| Что именуется | Соглашение | Пример |
|---|---|---|
| Переменная или функция | snake_case | user_age, get_total() |
| Константа | ALL_CAPS_SNAKE | MAX_RETRIES, PI |
| Класс | CapWords (PascalCase) | UserProfile, HttpError |
| Модуль / пакет | lowercase или snake_case | utils, data_parser |
| «Приватный» атрибут | _single_leading_underscore | _cache, _helper() |
| Атрибут с искажением имени | __double_leading_underscore | __secret |
| Специальный dunder | __double_both_sides__ | __init__, __str__ |
snake_case для переменных и функций
snake_case использует строчные буквы с символами подчёркивания между словами. Это стандарт для переменных и функций в Python.
# PEP 8 compliant
first_name = "Alice"
last_name = "Smith"
total_price = 9.99
items_in_cart = 3
# Not PEP 8 (camelCase) — works, but avoid for variables
firstName = "Alice" # JavaScript style, not PythonicALL_CAPS для констант
По соглашению, имя, написанное заглавными буквами, сигнализирует: «это значение не должно изменяться». Python не обеспечивает неизменяемость принудительно, но соглашение понятно всем.
MAX_CONNECTIONS = 100
TIMEOUT_SECONDS = 30
PI = 3.141592653589793
# Using the constant
if current_connections > MAX_CONNECTIONS:
print("Connection limit reached")CapWords для классов
Имена классов используют CapWords (также называемый PascalCase): каждое слово начинается с заглавной буквы, без символов подчёркивания.
class UserProfile:
pass
class HttpRequestError(Exception):
passОписательные и значимые имена
Лучшее имя переменной говорит следующему читателю что представляет значение, а не как оно хранится. Стремитесь к именам, которые делают строку кода похожей на предложение.
# Unclear
r = 5
a = 3.14159 * r ** 2
# Clear
radius = 5
circle_area = 3.14159 * radius ** 2
print(circle_area) # 78.53975Когда короткие имена допустимы
Однобуквенные имена (x, y, i, n) приемлемы в узких, хорошо понятных контекстах:
- Счётчики циклов:
for i in range(10): - Математические формулы:
y = m * x + b - Координаты:
(x, y)или(row, col)
За пределами этих контекстов предпочитайте описательные имена, даже если они длиннее.
Избегайте ненужных сокращений
Сокращения экономят нажатия клавиш, но снижают читаемость. Используйте полные слова, если сокращение не является общепринятым.
# Unclear abbreviations
usr_nm = "alice"
tot_amt = 49.95
n_itm = 7
# Clear full names
username = "alice"
total_amount = 49.95
number_of_items = 7Широко принятые сокращения, которые можно оставить: url, id, http, db, idx, num.
Паттерны с подчёркиванием
Python использует символы подчёркивания в именах переменных для передачи намерения. Понимание этих паттернов поможет вам читать любой Python-код.
_single_leading — для внутреннего использования
Имя, начинающееся с одного подчёркивания, сигнализирует другим разработчикам: «это деталь реализации; не полагайтесь на неё за пределами этого модуля или класса». Python не обеспечивает это принудительно — это чисто соглашение.
class DataLoader:
def __init__(self, path):
self.path = path
self._cache = {} # internal; not part of the public API
def load(self):
if self.path not in self._cache:
self._cache[self.path] = self._read_file()
return self._cache[self.path]
def _read_file(self):
# "private" helper
with open(self.path) as f:
return f.read()from module import * также пропускает имена, начинающиеся с _.
__double_leading — искажение имени
Два ведущих подчёркивания активируют механизм искажения имён в Python: __attr внутри класса Foo хранится как _Foo__attr. Это предотвращает случайное перезаписывание в подклассах.
class Base:
def __init__(self):
self.__secret = "hidden"
obj = Base()
# print(obj.__secret) # AttributeError
print(obj._Base__secret) # "hidden" — mangled nameИспользуйте искажение имён осторожно; оно усложняет отладку.
__dunder__ — специальные методы
Имена, окружённые двойными подчёркиваниями с обеих сторон, — это встроенные специальные («dunder») методы и атрибуты Python. Никогда не придумывайте собственные переменные __name__ — Python резервирует это пространство имён.
class Point:
def __init__(self, x, y): # called when an instance is created
self.x = x
self.y = y
def __repr__(self): # called by repr() and in the REPL
return f"Point({self.x}, {self.y})"
p = Point(3, 4)
print(p) # Point(3, 4)
print(repr(p)) # Point(3, 4)_ как одноразовая переменная
Одиночное подчёркивание _ используется по соглашению как «нам всё равно» переменная, когда нужно захватить значение, но не использовать его.
# Unpack a tuple but only use two of three values
x, _, z = (1, 2, 3)
print(x, z) # 1 3
# Loop counter when the index is not needed
for _ in range(5):
print("hello")Перекрытие встроенных имён
Встроенные имена Python (list, str, int, dict, type, input, print, id, min, max, sum, open, …) не являются ключевыми словами, поэтому Python молча позволяет повторно использовать их как имена переменных. Это почти всегда ошибка.
# Dangerous — shadows the built-in list type
list = [1, 2, 3]
print(list) # [1, 2, 3] — seems fine
new = list([4, 5]) # TypeError: 'list' object is not callableПосле присвоения list = [1, 2, 3] имя list в этой области видимости больше не ссылается на встроенный конструктор. Решение простое — выбрать другое имя.
# Safe
numbers = [1, 2, 3]
more_numbers = list([4, 5]) # list() still works
print(more_numbers) # [4, 5]Распространённые встроенные имена, которые случайно перекрываются: id, input, type, str, int, float, list, dict, set, tuple, min, max, sum, filter, map, open, print.
Область видимости и имена переменных
Имя переменной видно только в той области видимости, где оно определено. Две переменные в разных областях видимости могут иметь одно имя без конфликта — но это может вызвать путаницу.
total = 0 # module-level variable
def calculate(prices):
total = 0 # local variable — does NOT overwrite the module-level one
for price in prices:
total += price
return total
result = calculate([10, 20, 30])
print(result) # 60
print(total) # 0 — unchangedПодробнее о том, как Python разрешает имена (правило LEGB), см. в Python Scope. Чтобы понять глобальные переменные и ключевое слово global, см. Global Variables in Python.
Краткая справка
# Hard rules
user1 = "ok" # letters, digits, underscores — fine
_private = "ok" # leading underscore — fine
# 1user = "bad" # SyntaxError: starts with digit
# my-var = "bad" # SyntaxError: hyphens not allowed
# PEP 8 conventions
snake_case_var = 42 # variables and functions
MAX_VALUE = 100 # constants
# class names use CapWords (PascalCase)
# Underscore patterns
_internal = "internal use" # single leading: hint "private"
_ = "throwaway" # lone underscore: discard value
# What to avoid
# list = [] # shadows built-in
# str = "hello" # shadows built-in
# if = True # SyntaxError: reserved keywordДля более широкого введения в создание и присвоение переменных в Python см. Python Variables. О том, как группировать связанные переменные, см. Group Variables in Python.