← назад к разделу

Python привлекает тем, что код на нём читается почти как обычный текст: меньше скобок, меньше церемоний, больше смысла на строку. Но за этой простотой стоят несколько решений языка, которые лучше понять сразу — иначе легко словить неожиданное поведение. Разберём базовый синтаксис и систему типов с самого начала.

Отступы — это блоки кода

В большинстве языков блок кода выделяют фигурными скобками. В Python блок задаётся отступом — обычно четыре пробела. Двоеточие в конце строки открывает новый блок, а возврат на прежний уровень отступа его закрывает.

def greet(name):
    if name:                 # двоеточие открывает блок
        print(f"Привет, {name}")   # этот код внутри if
    else:
        print("Привет, гость")
    print("Готово")          # снова уровень функции, вне if/else

Из этого следует простое правило: отступы — не косметика, а синтаксис. Сместил строку на пробел — изменил смысл программы или получил ошибку. Не смешивай пробелы и табы; общепринятый стиль — четыре пробела.

Переменные и динамическая типизация

Переменную не нужно объявлять заранее и указывать её тип — достаточно присвоить значение. Тип определяется в момент присваивания и может меняться по ходу программы. Это и есть динамическая типизация.

x = 42        # сейчас x — целое число
x = "сорок"   # а теперь та же переменная ссылается на строку

Важно понимать, что переменная в Python — это не «коробка со значением», а имя, привязанное к объекту. Присваивание не копирует значение, а перенаправляет имя на другой объект. Узнать тип текущего значения можно функцией type:

n = 42
print(type(n))   # <class 'int'>

Динамическая типизация удобна для быстрой разработки, но за ней легко не заметить ошибку: переменная незаметно стала не тем, чем вы ожидали. Поэтому в серьёзных проектах добавляют подсказки типов (об этом — в отдельной статье).

Базовые типы

Минимальный набор, с которого всё начинается:

age = 30           # int — целое число произвольной длины
price = 19.99      # float — число с плавающей точкой
name = "Анна"      # str — строка (текст в кавычках)
active = True      # bool — логический тип: True или False
nothing = None     # None — «значения нет»

Несколько деталей, которые экономят время:

  • int не имеет фиксированного предела разрядности — большие числа не переполняются, Python расширяет их автоматически.
  • float — это та же двоичная плавающая точка, что и везде, со всеми её сюрпризами: 0.1 + 0.2 даст 0.30000000000000004, а не ровно 0.3. Для денег используют тип Decimal из модуля decimal.
  • bool на самом деле подвид int: True равен 1, False равен 0. Поэтому True + True вернёт 2 (так делать не стоит, но знать полезно).
  • None — единственное значение типа NoneType, означает «здесь ничего нет». Сравнивают с ним через is: if value is None.

f-строки: подстановка значений в текст

Самый удобный способ собрать строку из значений — f-строка: буква f перед кавычками включает подстановку выражений в фигурных скобках.

name = "Анна"
age = 30
print(f"{name}, возраст {age}")          # Анна, возраст 30
print(f"Через год будет {age + 1}")      # выражение тоже работает
print(f"Цена: {price:.2f}")              # форматирование: 19.99

Внутри {} можно писать любое выражение, а после двоеточия — спецификатор формата (например, :.2f — два знака после точки). f-строки читаемее и быстрее, чем старая конкатенация через + или метод format.

Операторы

Арифметика выглядит привычно, но есть пара особенностей:

print(7 / 2)    # 3.5   — обычное деление всегда даёт float
print(7 // 2)   # 3     — целочисленное деление (отбрасывает дробь)
print(7 % 2)    # 1     — остаток от деления
print(2 ** 10)  # 1024  — возведение в степень

Сравнения возвращают bool и их можно связывать в цепочку, как в математике:

x = 5
print(0 < x < 10)   # True — то же, что 0 < x and x < 10

Логические операторы пишутся словами: and, or, not. А оператор == сравнивает значения, тогда как is — это тот же самый объект в памяти. Для чисел и строк почти всегда нужен ==; is используют только с None.

Управляющие конструкции

Ветвления и циклы тоже опираются на отступы и двоеточие.

score = 75

if score >= 90:
    grade = "отлично"
elif score >= 60:           # elif — это «else if»
    grade = "нормально"
else:
    grade = "слабо"

Цикл for в Python перебирает элементы последовательности, а не считает индексы. Чтобы пройтись по диапазону чисел, берут range:

for i in range(3):          # 0, 1, 2
    print(i)

for letter in "abc":        # строку тоже можно перебирать
    print(letter)

Цикл while повторяет блок, пока условие истинно. Управляют циклами break (выйти) и continue (перейти к следующей итерации):

n = 0
while True:
    n += 1
    if n == 3:
        continue   # пропустить остаток итерации
    if n > 5:
        break      # выйти из цикла
    print(n)       # 1, 2, 4, 5

Всё в Python — объект

Ключевая идея языка: любое значение — это объект. Число, строка, функция, даже сам тип — у всего есть свой тип, свои методы и идентичность. Это значит, что функцию можно положить в переменную, передать в другую функцию или вернуть из неё.

def shout(text):
    return text.upper()

f = shout            # функция — обычный объект, кладём в переменную
print(f("привет"))   # ПРИВЕТ

Из этого же следует, что у строки или числа есть методы: "abc".upper(), (-5).__abs__(). Единообразие «всё — объект» делает язык предсказуемым: новые сущности ведут себя по тем же правилам, что и встроенные.

Изменяемые и неизменяемые типы

Это одно из самых важных различий, которое стоит усвоить сразу. Объекты бывают неизменяемые (immutable) — их нельзя поменять после создания, и изменяемые (mutable) — их содержимое можно править на месте.

  • Неизменяемые: int, float, bool, str, tuple, None.
  • Изменяемые: list, dict, set.

Что значит «нельзя поменять» для строки? Любая операция над ней создаёт новый объект, а старый остаётся нетронутым:

s = "abc"
s2 = s.upper()   # создаётся новая строка "ABC"
print(s)         # abc — исходная строка не изменилась

А список меняется на месте, и это легко приводит к неожиданностям, когда на один объект ссылаются два имени:

a = [1, 2, 3]
b = a            # b и a — это одно имя одного списка
b.append(4)
print(a)         # [1, 2, 3, 4] — изменился и a, ведь объект один

Короткая формула: присваивание копирует ссылку, а не объект. Если нужен независимый список, делают копию явно: b = a.copy() или b = list(a).

Отсюда же — частая ловушка новичка: нельзя использовать изменяемый объект как значение по умолчанию у параметра функции (def f(items=[])), потому что этот список создаётся один раз и сохраняется между вызовами. Подробнее об этом — в статье о функциях.

Коротко

  • Блоки кода задаются отступами (4 пробела) и двоеточием, а не скобками — отступ это синтаксис.
  • Типизация динамическая: тип привязан к значению, а переменная — это имя-ссылка на объект.
  • Базовые типы: int (без предела разрядности), float (двоичный, неточный для дробей), str, bool (подвид int), None.
  • f-строки (f"{value}") — основной способ собирать текст из значений.
  • / всегда даёт float, // — целочисленное деление; == сравнивает значения, is — идентичность (нужен для None).
  • Всё — объект: функции, типы и числа можно хранить в переменных и передавать.
  • Делите типы на неизменяемые (int, str, tuple) и изменяемые (list, dict, set); присваивание копирует ссылку, а не объект.

Что почитать дальше

  • Структуры данных Python — списки, словари, множества и кортежи подробно.
  • Функции и модули — как объявлять функции, аргументы по умолчанию и организация кода.
  • Инструментарий разработчика — окружения, пакеты и проверка типов на практике.