Всё — объект: id, type, ссылки, is и ==

⏱ 30 мин · 🧩 заданий: 6

Всё — объект

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

import math
for obj in [42, "hi", [1, 2], None, len, math, int, type]:
    print(f"{obj!r:40.40} тип: {type(obj).__name__}")

У каждого объекта есть:

Характеристика Как узнать Может меняться?
идентичность id(obj) (в CPython — адрес в памяти) нет
тип type(obj) нет
значение само содержимое только у изменяемых объектов

Переменная — ссылка

Переменная хранит не объект, а ссылку на него. Присваивание = привязывает имя к объекту и никогда не копирует:

a = [1, 2, 3]
b = a              # теперь у одного списка два имени (псевдонимы)
print(id(a), id(b), a is b)
b.append(4)
print(a)

c = [1, 2, 3, 4]   # другой объект с таким же значением
print(a == c, a is c)

Нажмите 👣 Пошагово и посмотрите на номера объектов: a и b указывают на #1, а c — на #2.

a ──┐ ├──▶ #1 list [1, 2, 3, 4] b ──┘ c ─────▶ #2 list [1, 2, 3, 4]

is и ==

  • a == b — равенство значений: вызывает a.__eq__(b).
  • a is b — идентичность: это один и тот же объект? (id(a) == id(b)). Переопределить нельзя.
class AlwaysEqual:
    def __eq__(self, other):
        return True

x = AlwaysEqual()
print(x == None, x is None)      # == можно «обмануть», is — нет

Когда использовать is

Только для синглтонов: x is None, x is not None, иногда x is True/x is False или собственный объект-маркер _MISSING = object(). Во всех остальных случаях — ==.

Кеширование малых объектов

CPython заранее создаёт целые числа от −5 до 256 и переиспользует их. Поэтому is для маленьких чисел «работает», а для больших — нет:

a = 256
b = 256
print(a is b)              # True — один закешированный объект

x = int("1000")
y = int("1000")
print(x == y, x is y)      # True False — два разных объекта

Это деталь реализации, на которую нельзя полагаться — один из любимых вопросов «что выведет код». Подробнее — в уроке «Истинность, сравнение и кеширование объектов».

Ссылки и сборка мусора

У каждого объекта есть счётчик ссылок. Когда он становится нулём, объект удаляется:

import sys

data = [1, 2, 3]
print(sys.getrefcount(data))   # на 1 больше: сам вызов getrefcount временно держит ссылку
alias = data
print(sys.getrefcount(data))
container = [data, data]
print(sys.getrefcount(data))
del alias                       # удаляем ИМЯ, а не объект
print(sys.getrefcount(data), data)

del x удаляет имя x. Объект живёт, пока на него ссылается хоть что-то: другие имена, элементы списков, атрибуты объектов, замыкания.

class Noisy:
    def __init__(self, name):
        self.name = name
    def __del__(self):
        print(f"объект {self.name} удалён")

a = Noisy("A")
b = a
del a
print("после del a объект ещё жив, его держит b")
del b
print("конец")

Аргументы функций — тоже ссылки

При вызове функции параметр становится ещё одним именем того же объекта. Поэтому функция может изменить переданный изменяемый объект:

def add_item(items, x):
    items.append(x)         # меняет тот самый список

shopping = ["хлеб"]
add_item(shopping, "молоко")
print(shopping)

Подробно — в следующем уроке.

Функции и классы — тоже объекты

def greet():
    return "привет"

print(id(greet), type(greet), greet.__name__)
f = greet                 # ещё одна ссылка на функцию
print(f is greet, f())
print(type(int), type(type), isinstance(int, object), isinstance(greet, object))

Итог

  • Каждый объект имеет идентичность (id), тип (type) и значение.
  • Переменные — ссылки; = связывает имя с объектом и не копирует; несколько имён одного объекта — псевдонимы.
  • == сравнивает значения, is — идентичность; is — только для None и других синглтонов.
  • Малые int кешируются (−5…256) — деталь реализации.
  • Объект удаляется, когда на него не остаётся ссылок; del удаляет имя.

Практика решено 0 из 6

Вы не вошли — ответы проверяются, но прогресс не сохранится. Войти или зарегистрироваться.
Задание 1 Один вариант ответа

Какие три характеристики есть у каждого объекта в Python?

Задание 2 Один вариант ответа

Что выведет код?

a = [1, 2, 3]
b = [1, 2, 3]
c = a
print(a == b, a is b, a is c)
Задание 3 Программа на Python

Напишите функцию same_object(x, y), которая возвращает строку: "один объект", если x и y — один и тот же объект; "равны", если разные, но равные по значению; иначе "разные".

Какие тесты проверяют код (3)
a = [1]; assert same_object(a, a) == "один объект"
assert same_object([1], [1]) == "равны"
assert same_object([1], [2]) == "разные"
Задание 4 Один вариант ответа

Почему с None сравнивают через is, а не через ==?

Задание 5 Один вариант ответа

Что делает del x?

Задание 6 Заполнить таблицу

Что выведет print(x is y)?

TrueFalse
x = None; y = None
x = [1]; y = x
x = [1]; y = x[:]
x = (1, 2); y = tuple(x)
x = {}; y = {}
Отметьте ячейку — «+», пустая — «−».

Войдите, чтобы отмечать пройденные уроки.