Найти - Пользователи
Полная версия: оператор IS, сравнение данных
Начало » Python для новичков » оператор IS, сравнение данных
1 2
sergey.program
a = "string"
b = "string"

print(a is b) #отдаёт True
print(a == b) #отдаёт True
версия питона 3.2
вопрос таков, почему отдаёт True? ведь если сравниваем к примеру
a = ["one", 1, "three-2"]# разное
b = ["one", 1, "three-2"]# разное

def oper(a, b):
if a is b:
print(True)
else:
print(False)


oper(a, b)#отдаёт False
a = b
oper(a, b)#отдаёт True
тут вроде всё нормально пишет
с чем это может быть связано?
s0rg
- это конструктор списка:
In [1]: a = 'string'

In [2]: b = 'string'

In [3]: a, id(a), b, id(b)
Out[3]: ('string', 3074100736L, 'string', 3074100736L)

In [4]: a = [1]

In [5]: b = [1]

In [6]: a, id(a), b, id(b)
Out[6]: ([1], 153051884, [1], 153139276)
sergey.program
спасибо :) увидел - понял
mimo
Учусь по книге Марка Саммерфилда “Программирование на Python 3”, в ней пример:

>>> a = "many paths"
>>> b = "many paths"
>>> a is b
False
>>> a == b
True

Я задаю то же самое, но без пробела, и получаю следующее:

>>> a = "manypaths"
>>> b = "manypaths"
>>> a is b
True

Почему такие результаты получаются?
old_monty
mimo
Я задаю то же самое, но без пробела, и получаю следующее:

>>> a = “manypaths”
>>> b = “manypaths”
>>> a is b
True

Почему такие результаты получаются?
В целях повышения эффективности кода Python делает кэширование малых целых чисел и небольших строк. Хотя проверка a is b возвращает True, можно легко убедиться, что ссылки a и b указывают все же не на один и тот же объект. Если бы a и b указывали на один объект, то при изменении b на какое-либо другое значение точно такое же значение должно было бы получаться у а. Но этого не происходит:
>>> x = "hello"
>>> y = "hello"
>>> x is y
True
>>> y = "world"
>>> print(x)
hello

Чтобы точно знать, сколько ссылок указывает на данный объект, можно применять функцию getrefcount() из модуля sys:
>>> import sys
>>> sys.getrefcount("manypaths")
4
Вообще, в случае малых целых чисел и небольших строк не следует полагаться в своем коде на оператор is. Даже если вы нигде не объявляли ссылку на малое число, оно может быть в кэше, и на него могут иметься десятки и даже сотни ссылок:
>>> sys.getrefcount(2)
112
mimo
Спасибо.
py.user.next
old_monty
Хотя проверка a is b возвращает True, можно легко убедиться, что ссылки a и b указывают все же не на один и тот же объект.
Это не так. Если is возвращает True, то они связаны с одним объектом. А кто они? Они - это имена.
То есть ты неправильно сказал, потому что не знаешь механизма связывания имён с объектами.

old_monty
Если бы a и b указывали на один объект, то при изменении b на какое-либо другое значение точно такое же значение должно было бы получаться у а. Но этого не происходит:
Ты не изменил значение строки y, а создал новую строку и привязал y к ней. И забыл проверить is снова.

А то, что ты где-то прочитал, касалось мутабельных объектов.
>>> a = [1]
>>> b = a
>>> a is b
True
>>> a
[1]
>>> b
[1]
>>> a.append(2)
>>> a
[1, 2]
>>> b
[1, 2]
>>> a is b
True
>>>


mimo
Почему такие результаты получаются?
Это зависит от интерпретатора, он может оптимизировать, а может не оптимизировать. Так что у автора книги они не оптимизировались, а у тебя оптимизируются. Поэтому строки можно сравнивать только через ==.
JOHN_16
я бы сказал так, оператор is сравнивает Python объекты, а не их значения. Т.е. оператор is не нужно применять в задачах когда нужно сравнить значения двух переменных.
old_monty
Хотя проверка a is b возвращает True, можно легко убедиться, что ссылки a и b указывают все же не на один и тот же объект.
Вот вам из справки по Питону:
The operators is and is not test for object identity: x is y is true if and only if x and y are the same object
Ну и py.user.next вам уже разъяснил вашу ошибку.
old_monty
py.user.next, JOHN_16
Посыпал голову пеплом и ушел читать документацию.
mimo
Так. Мне становится ясно, что ничего не ясно. )
Цитирую Саммерфилда:
“В языке Python нет переменных как таковых - вместо них используются ссылки на объекты. …интерпретатор создает объект, а затем создает ссылку на объект.

Поскольку все переменные в языке Python фактически являются ссылками, иногда возникает необходимость определить, не ссылаются ли две или более ссылок на один и тот же объект. Оператор is - это двухместный оператор, который возвращает True, если ссылка слева указывает на тот же самый объект, что и ссылка справа.

…сравниваются ссылки на объекты, а не сами объекты. Оператор is сравнивает только адреса памяти, в которых располагаются объекты - если адреса равны, следовательно, ссылки указывают на один и тот же объект.”
Python 3.5.0 (v3.5.0:374f501f4567, Sep 13 2015, 02:27:37) [MSC v.1900 64 bit (AMD64)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> import sys
>>> #пример из книги
>>> a = "many paths"
>>> b = "many paths"
>>> id(a), id(b)    #подсмотрено в посте №2
(56237168, 56237232)
>>> sys.getrefcount("many paths")    #совет из поста №5
2
>>> a is b
False
>>> a == b
True
>>> 
>>> #повторяю без пробела
>>> a = "manypaths"
>>> b = "manypaths"
>>> id(a), id(b)
(56236976, 56236976)
>>> sys.getrefcount("manypaths")
4
>>> a is b
True
>>> a == b
True
Интерпретатор в первом случае создал два объекта, а во втором один? Почему?
old_monty
Чтобы точно знать, сколько ссылок указывает на данный объект, можно применять функцию getrefcount() из модуля sys

Почему sys.getrefcount(“manypaths”) отдает 4?
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB