Модуль 6 · Функции и модули

Справочник по Python · модуль 6 · функции и модули

Глава 6.13

6.13

Объект None:
отсутствие значения

В Python «ничего» — это тоже объект. None обозначает отсутствие значения: его возвращает функция без return, им отмечают ещё не заполненную переменную и им сообщают, что результата не нашлось.

Категория
Функции
Уровень
Базовый
Связанные темы
Возврат значений, аргументы по умолчанию
Зачем это знать
Отличать «нет значения» от нуля и пустой строки

§1Что означает None

None — специальное значение, которое означает «ничего» или «значения нет». Это не ноль, не пустая строка и не False: те говорят «значение есть, и оно пустое», а None говорит «значения не существует».

Разница важная. Ноль градусов — это измеренная температура. None в поле температуры — датчик не ответил. Оба «пустые» на вид, но означают разное, и путать их нельзя.

§2Тип NoneType и единственный объект

None — экземпляр класса NoneType, и это единственный объект такого типа во всей программе.

main.pyтип и единственность
print(type(None))
print(None is None)
Выводдругих None не бывает
<class 'NoneType'>
True

Такой объект в единственном экземпляре называют синглтоном. Сколько бы имён на него ни ссылалось, в памяти он один — и именно поэтому его проверяют оператором is, а не сравнением.

§3Функция без return

Функция, которая ничего не возвращает явно, всё равно возвращает значение — None.

main.pyфункция печатает, но не возвращает
def greet(name):
    print("Привет,", name)

result = greet("Аня")
print(result)
Выводвторая строка — результат вызова
Привет, Аня
None

То же самое верно для return без значения. И для встроенных функций: print() печатает текст, но возвращает None — поэтому x = print("текст") кладёт в x вовсе не строку.

§4Проверка через is

Правильный способ проверить, что значение отсутствует, — оператор is.

main.pyдве проверки дают один результат
value = None

if value is None:
    print("значения нет")

print(value == None, value is None)
Выводформально работают оба варианта
значения нет
True True

== спрашивает «равны ли значения», а is — «это один и тот же объект». Поскольку None существует в единственном экземпляре, вопрос об идентичности здесь и точнее, и быстрее: он не зависит от того, как чужой класс определил своё сравнение. Проверка отсутствия пишется как is None, наличия — как is not None.

§5None в логическом контексте

None относится к ложным значениям — тем самым, о которых шла речь в главе 3.16.

main.pyприведение к логическому типу
print(bool(None))

if not None:
    print("None считается ложным")
ВыводNone — falsy
False
None считается ложным

§6Почему if value недостаточно

Раз None ложно, кажется соблазнительным писать просто if value:. Но ложны и ноль, и пустая строка, и пустой список.

main.pyзначение есть, и оно равно нулю
temperature = 0

if not temperature:
    print("условие сработало")

if temperature is None:
    print("эта строка не напечатается")
Выводноль принят за «нет данных»
условие сработало

Ноль градусов — реальное измерение, а не отсутствие данных. Когда нужно отличить «нет значения» от «значение пустое», проверка обязана быть именно is None.

§7None как значение по умолчанию

Частая роль None — умолчание для необязательного аргумента, о которых шла речь в главе 6.5.

main.pyаргумент можно не передавать
def example(arg=None):
    if arg is None:
        print("Аргумент не передан")
    else:
        print("Аргумент передан:", arg)

example()
example(42)
Выводфункция различает два случая
Аргумент не передан
Аргумент передан: 42

Такое умолчание честнее любого другого: оно не притворяется осмысленным значением, а прямо сообщает, что параметр не задавали.

§8Ловушка изменяемого умолчания

У None в этой роли есть ещё одна причина. Значение по умолчанию вычисляется один раз — при объявлении функции, а не при каждом вызове. Для списка это оборачивается сюрпризом.

main.pyтак делать не надо
def append_value(lst=[]):
    lst.append(42)
    return lst

print(append_value())
print(append_value())
Выводсписок общий для всех вызовов
[42]
[42, 42]

Все вызовы используют один и тот же список, и он растёт от вызова к вызову. Лечение — умолчание None и создание нового объекта внутри функции.

main.pyправильный вариант
def append_value(lst=None):
    if lst is None:
        lst = []
    lst.append(42)
    return lst

print(append_value())
print(append_value())
Выводкаждый вызов получает свой список
[42]
[42]

Правило простое: изменяемый объект (список, словарь, множество) никогда не ставят значением по умолчанию. Ставят None, а сам объект создают в теле функции.

§9None как «результата нет»

Функция поиска возвращает None, когда искать было нечего.

main.pyвозврат-маркер
def find_in_list(lst, value):
    if value in lst:
        return lst.index(value)
    return None

result = find_in_list([1, 2, 3], 4)
if result is None:
    print("Значение не найдено")
Выводиндекса нет
Значение не найдено

Так же поступает встроенный метод словарей: d.get("ключ") возвращает None вместо исключения, если ключа нет. Обратите внимание, почему здесь нельзя проверять через if not result: индекс 0 — законный результат, а он тоже ложен.

§10Заглушка для будущего значения

Имя иногда нужно создать заранее, хотя настоящее значение появится позже и не при всех условиях.

Схемапеременная объявлена, значения ещё нет
value = None          # переменная пока не имеет значения

if some_condition:
    value = 42

print(value)

Без первой строки ветка else оставила бы имя несуществующим, и обращение к нему вызвало бы NameError. None здесь означает «сюда ещё ничего не записали».

§11None внутри коллекции

В списке или словаре None отмечает пропущенный элемент, не сбивая длину и нумерацию.

main.pyтретье измерение не получено
data = [1, 2, None, 4]

print(len(data))
print(sum(x for x in data if x is not None))
Выводэлементов четыре, суммируются три
4
7

Если бы пропуск просто выбросили, четвёртое измерение сдвинулось бы на третью позицию, и связь с моментом времени потерялась. None сохраняет структуру данных.

§12Типичная авария: AttributeError

Главная ошибка при работе с None — забыть проверить результат и сразу его использовать.

main.pyфункция вернула None
def get_data():
    return None

data = get_data()
print(data.upper())
Ошибкау None нет методов строк
AttributeError: 'NoneType' object has no attribute 'upper'

Это одно из самых частых сообщений в Python, и читать его нужно так: «где-то выше функция вернула None, а я обращаюсь с ним как со строкой». Лечится проверкой перед использованием.

main.pyпроверка перед обращением
if data is not None:
    print(data.upper())

§13None и аннотации типов

В аннотациях из главы 6.11 возможность отсутствия записывают явно.

main.pyфункция возвращает либо число, либо None
def find_index(lst: list, value) -> int | None:
    if value in lst:
        return lst.index(value)
    return None

print(find_index(["a", "b"], "b"))
Выводаннотация ничего не проверяет, но предупреждает читателя
1

Запись int | None — сигнал тому, кто вызывает функцию: результат придётся проверить. Функция, которая ничего не возвращает, аннотируется как -> None.

§14Частые ошибки

Что написаноЧто произойдётКак правильно
if value: для проверки отсутствияноль, пустая строка и пустой список тоже сочтутся отсутствиемif value is None:
def f(lst=[])список общий для всех вызовов и накапливает данныеdef f(lst=None) и создание внутри
использовать результат функции без проверкиAttributeError или TypeError на NoneTypeif result is not None:
x = print("текст")в x попадёт None, а не строкаx = "текст", печатать отдельно
return в одной ветке и ничего в другойвторая ветка молча вернёт Noneвернуть значение из всех веток осознанно
None == 0 как признак пустотыFalse: это разные объекты разных типовсравнивать с None только через is

§15Проверьте себя

Чем None отличается от 0 и пустой строки?

None означает, что значения нет вовсе. Ноль и пустая строка — существующие значения, просто «пустые» по содержанию.

Что вернёт функция, в которой нет return?

None. То же самое вернёт return без значения.

Почему проверяют is None, а не == None?

None существует в единственном экземпляре, поэтому корректнее спрашивать об идентичности объекта. Такая проверка быстрее и не зависит от того, как чужой класс определил сравнение.

Чем плохо def f(lst=[])?

Значение по умолчанию создаётся один раз при объявлении функции, поэтому все вызовы работают с одним списком и он накапливает изменения.

О чём говорит AttributeError: 'NoneType' object has no attribute ...?

Что переменная содержит None, хотя ожидался объект с методами: скорее всего, выше функция не нашла результат и вернула None.

§16Шпаргалка

Проверка отсутствияif value is None:
Проверка наличияif value is not None:
Типtype(None) → NoneType
Умолчаниеdef f(arg=None):
Аннотация-> int | None

Итог главы

None — единственный объект типа NoneType, обозначающий отсутствие значения. Его возвращает функция без return, им отмечают необязательные аргументы, пропуски в данных и отрицательный результат поиска. Проверять его нужно оператором is, а не общей проверкой на истинность: иначе ноль и пустая строка будут приняты за отсутствие данных. И главное практическое правило главы: изменяемый объект не ставят значением по умолчанию — там всегда стоит None.

Глава 6.13 · Объект None · Справочник по Python Автор: Макаров Максим Николаевич