Оператор is в Python — это оператор идентичности, который проверяет, указывают ли две переменные на один и тот же объект в памяти. В отличие от оператора ==, который сравнивает значения на равенство, is сравнивает идентичность объекта, проверяя, указывают ли две ссылки на одно и то же место в памяти. Это различие имеет решающее значение для написания правильного и эффективного кода Python.
IS vs == Оператор
Ключевое различие между is и == заключается в том, что == сравнивает значения (равенство), а is сравнивает идентичность (тот же объект в памяти).
Пример 1: Основное различие
# Value comparison with ==
a = [1, 2, 3]
b = [1, 2, 3]
print(a == b) # Output: True (same values)
print(a is b) # Output: False (different objects)
# Identity comparison
c = a
print(a is c) # Output: True (same object)
# Memory locations
print(f"id(a): {id(a)}")
print(f"id(b): {id(b)}")
print(f"id(c): {id(c)}") True False True id(a): 140234567890 id(b): 140234567920 id(c): 140234567890
Оператор == возвращает True, потому что оба списка имеют одинаковое содержимое, но is возвращает False, потому что это отдельные объекты в памяти.
Понимание идентичности объектов с id()
Функция id() возвращает уникальный идентификатор (адрес памяти) объекта, который оператор is использует для сравнения.
Пример: Использование функции id()
x = [1, 2, 3, 4, 5]
y = [1, 2, 3, 4, 5]
z = x
# Check identity with 'is'
print(x is z) # Output: True
print(x is y) # Output: False
# Verify with id()
print(f"id(x): {id(x)}")
print(f"id(y): {id(y)}")
print(f"id(z): {id(z)}")
# x and z have the same id
# y has a different id True False id(x): 140234567890 id(y): 140234567920 id(z): 140234567890
Функция id() возвращает уникальный идентификатор (адрес памяти) объекта, который оператор is использует для сравнения.
Оператор IS NOT
Оператор is not возвращает True, когда две переменные ссылаются на разные объекты в памяти.
Пример: Использование is not
a = [1, 2, 3, 4, 5]
b = [1, 2, 3, 4, 5]
c = a
# Using 'is not'
print(a is not c) # Output: False (they are the same object)
print(a is not b) # Output: True (different objects)
# Equivalent to: not (a is b)
print(not (a is b)) # Output: True False True True
Таблица сравнения операторов:
| Выражение | Значение | Случай использования |
|---|---|---|
a is b | Тот же объект в памяти | Проверить идентичность объекта |
a is not b | Разные объекты в памяти | Проверить различие объектов |
a == b | Равные значения | Проверить равенство значений |
a != b | Разные значения | Проверить неравенство значений |
Когда использовать оператор IS
Оператор is следует использовать в определенных сценариях, где идентичность объекта важнее равенства значений.
Случай использования 1: Проверка на None
def process_data(value):
# CORRECT: Always use 'is' with None
if value is None:
print("No data provided")
return
print(f"Processing: {value}")
# WRONG: Don't use == with None
def wrong_check(value):
if value == None: # Not Pythonic
print("This works but is not recommended")
process_data(None) # Output: No data provided
process_data(42) # Output: Processing: 42 Данные не предоставлены Обработка: 42
Всегда используйте is или is not при сравнении с None, так как это более явно и быстрее.
Случай использования 2: Проверка логических синглтонов
def check_flag(flag):
# Use 'is' for True/False when checking identity
if flag is True:
print("Flag is explicitly True")
elif flag is False:
print("Flag is explicitly False")
else:
print(f"Flag is truthy/falsy but not boolean: {flag}")
check_flag(True) # Flag is explicitly True
check_flag(1) # Flag is truthy/falsy but not boolean: 1
check_flag(False) # Flag is explicitly False
check_flag(0) # Flag is truthy/falsy but not boolean: 0 Флаг явно True Флаг истинен/ложен, но не логический: 1 Флаг явно False Флаг истинен/ложен, но не логический: 0
Случай использования 3: Проверка, ссылаются ли переменные на один и тот же список/словарь
def modify_list(original_list, new_list):
if original_list is new_list:
print("Warning: Same list reference, modifications will affect both")
return False
return True
my_list = [1, 2, 3]
same_ref = my_list
different_list = [1, 2, 3]
modify_list(my_list, same_ref) # Warning message
modify_list(my_list, different_list) # Returns True Предупреждение: Та же ссылка на список, изменения затронут оба
Интернирование целых чисел и строк в Python
Python автоматически интернирует небольшие целые числа и некоторые строки в качестве оптимизации, что может привести к удивительному поведению is.
Пример: Кэширование небольших целых чисел
# Small integers (-5 to 256) are cached
a = 256
b = 256
print(a is b) # Output: True
a = 257
b = 257
print(a is b) # Output: False (usually, depends on implementation)
# This is due to Python's integer interning optimization
print(id(256) == id(256)) # True
print(id(257) == id(257)) # May vary True False True True
Пример: Интернирование строк
# String interning
a = "TutorialsPoint"
b = a
print(f"id(a), id(b): {id(a)}, {id(b)}")
print(f"a is b: {a is b}") # Output: True
print(f"b is not a: {b is not a}") # Output: False
# Identical string literals are often interned
x = "hello"
y = "hello"
print(x is y) # Output: True (usually)
# But not always for dynamically created strings
x = "hello world"
y = "hello world"
print(x is y) # Output: May be True or False
# Strings with spaces/special chars may not be interned
x = "hello world!"
y = "hello world!"
print(x is y) # Output: False (typically) id(a), id(b): 140234567890, 140234567890 a is b: True b is not a: False True True False
Python автоматически интернирует небольшие целые числа и некоторые строки в качестве оптимизации, что может привести к удивительному поведению is. Никогда не полагайтесь на это поведение в производственном коде.
Распространенные ошибки и подводные камни
Понимание распространенных ошибок при использовании оператора is помогает избежать ошибок и писать более надежный код.
Mistake 1: Using IS for Value Comparison
# WRONG: Using 'is' to compare values
a = 1000
b = 1000
if a is b: # Unreliable!
print("Equal")
else:
print("Not equal") # Usually prints this
# CORRECT: Use == for value comparison
if a == b: # Reliable
print("Equal") # Always prints this for equal values Mistake 2: Relying on Integer Interning
# Don't rely on this behavior!
def bad_comparison(x, y):
if x is y: # Only works reliably for small integers
return True
return False
print(bad_comparison(5, 5)) # True (cached)
print(bad_comparison(500, 500)) # False (not cached)
# CORRECT approach
def good_comparison(x, y):
if x == y: # Always reliable
return True
return False
print(good_comparison(5, 5)) # True
print(good_comparison(500, 500)) # True Mistake 3: Misunderstanding Mutable vs Immutable Types
# Immutable types (int, str, tuple)
a = 42
b = 42
print(a is b) # May be True (depends on interning)
# Mutable types (list, dict, set)
x = [1, 2]
y = [1, 2]
print(x is y) # Always False (different objects)
# Assignment creates reference, not copy
z = x
print(x is z) # True (same object)
# Use copy to create new object
import copy
w = copy.copy(x)
print(x is w) # False (different objects)
print(x == w) # True (same values) Лучшие практики
Следование лучшим практикам при использовании оператора is обеспечивает надежный и питонический код.
Практика 1: Всегда используйте IS с None
# GOOD: Checking for None
if value is None:
handle_none()
# BAD: Using == with None
if value == None: # Works but not Pythonic
handle_none() Всегда используйте <code>is</code> и <code>is not</code> при сравнении с <code>None</code>.
Практика 2: Используйте == для сравнения значений
# GOOD: Value comparison
if count == 0:
print("Empty")
# BAD: Using 'is' for value comparison
if count is 0: # Unreliable!
print("Empty") Используйте <code>==</code> для сравнения значений в большинстве других случаев.
Практика 3: Используйте IS для объектов-синглтонов
# GOOD: Checking if same list
if original_list is modified_list:
print("Same object")
# GOOD: Checking if equal values
if list1 == list2:
print("Equal contents") Используйте <code>is</code> для объектов-синглтонов (<code>None</code>, <code>True</code>, <code>False</code>) и для проверки, ссылаются ли две переменные на один и тот же изменяемый объект.
Практика 4: Никогда не полагайтесь на интернирование
# BAD: Relying on integer interning
if x is 256: # May work, but unreliable
do_something()
# GOOD: Use == for value comparison
if x == 256: # Always reliable
do_something() Никогда не полагайтесь на интернирование целых чисел или строк в производственном коде.>
Примеры из реальной жизни
Эти примеры демонстрируют практическое использование оператора is в реальных сценариях.
Пример 1: Реализация паттерна Singleton
class DatabaseConnection:
_instance = None
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
print("Creating new database connection")
return cls._instance
# Test singleton
db1 = DatabaseConnection()
db2 = DatabaseConnection()
print(db1 is db2) # Output: True (same instance)
print(id(db1) == id(db2)) # Output: True Создание нового подключения к базе данных True True
Пример 2: Реализация кэша
class Cache:
def __init__(self):
self._cache = {}
self._MISSING = object()
def get(self, key, default=None):
result = self._cache.get(key, self._MISSING)
if result is self._MISSING:
print(f"Cache miss for key: {key}")
return default
print(f"Cache hit for key: {key}")
return result
def set(self, key, value):
self._cache[key] = value
# Usage
cache = Cache()
cache.set('user_1', {'name': 'Alice'})
cache.get('user_1') # Cache hit
cache.get('user_2') # Cache miss
cache.get('user_2', {}) # Cache miss, returns {} Попадание в кэш для ключа: user_1 Промах кэша для ключа: user_2 Промах кэша для ключа: user_2
Пример 3: Обнаружение защитного копирования
def modify_list_safely(original, new_items):
# Check if caller passed the same list
if original is new_items:
raise ValueError("Cannot pass same list for both arguments")
original.extend(new_items)
return original
my_list = [1, 2, 3]
additional = [4, 5]
result = modify_list_safely(my_list, additional)
print(result) # [1, 2, 3, 4, 5]
try:
modify_list_safely(my_list, my_list) # Raises ValueError
except ValueError as e:
print(f"Error: {e}") [1, 2, 3, 4, 5] Ошибка: Нельзя передать один и тот же список для обоих аргументов
Попробуйте сами
Практикуйте то, что вы узнали, изменяя код ниже. Попробуйте изменить значения и условия, чтобы увидеть разные результаты!
// Нажмите "Запустить код" чтобы увидеть результаты
Связанные темы
Часто задаваемые вопросы
В чем разница между 'is' и '==' в Python?
Оператор is проверяет, указывают ли две переменные на один и тот же объект в памяти (идентичность), а == проверяет, имеют ли два объекта одинаковое значение (равенство). Например, [1, 2] is [1, 2] — это False (разные объекты), но [1, 2] == [1, 2] — это True (одинаковые значения).
Когда мне следует использовать 'is' вместо '=='?
Всегда используйте is или is not при сравнении с None, True или False. Используйте is, когда вам нужно проверить, ссылаются ли две переменные на один и тот же объект в памяти. Используйте == для сравнения значений в большинстве других случаев.
Почему '256 is 256' возвращает True, но '257 is 257' может возвращать False?
Python кэширует небольшие целые числа (обычно от -5 до 256) для оптимизации производительности. Это означает, что 256 is 256 возвращает True, потому что они ссылаются на один и тот же кэшированный объект. Однако 257 is 257 может возвращать False, потому что большие целые числа не кэшируются. Никогда не полагайтесь на это поведение в производственном коде.
Должен ли я использовать 'if x is None:' или 'if x == None:'?
Всегда используйте if x is None: вместо if x == None:. Оператор is более явный, быстрее и является питоническим способом проверки None. Использование == с None работает, но не рекомендуется.
Могу ли я использовать 'is' для сравнения строк?
Вы можете использовать is со строками, но это ненадежно, поскольку Python может интернировать некоторые строки, но не другие. Всегда используйте == для сравнения значений строк. Используйте is со строками только тогда, когда вам нужно специально проверить, ссылаются ли две переменные на один и тот же строковый объект.
В чем разница между 'is' и 'is not'?
Оператор is возвращает True, когда две переменные указывают на один и тот же объект, а is not возвращает True, когда они указывают на разные объекты. a is not b эквивалентно not (a is b).