В Python всегда ли это выражение «(a есть b) == (id (a) == id (b))» возвращает True? - PullRequest
1 голос
/ 28 марта 2020

В Python выражение (a is b) == ( id(a) == id(b) ), кажется, всегда возвращает True, где a и b - переменные, ссылающиеся на некоторый объект, поскольку функция id возвращает память, в которой они хранятся, и is используется для идентификации объекта.

Есть ли исключения?

Ответы [ 2 ]

4 голосов
/ 28 марта 2020
(a is b) == ( id(a) == id(b) )

Это выражение всегда True. Есть два возможных пути: 1. Оба a и b ссылаются на один и тот же объект

>>>a='Hello'
>>>b=a
>>> a is b
True
>>> id(a)==id(b)
True
И 'a', и 'b' относятся к разным объектам.
>>>a='hello'
>>>b='world'
>>>a is b
False
>>>id(a)==id(b)
False

id(a)==id(b) делает то, что делает a is b.

Теперь Incase1 (a is b) == ( id(a) == id(b) ) this равен True==True, что возвращает True. Во втором случае (a is b) == ( id(a) == id(b) ) это False==False, который возвращает True

Из Документов :

Операторы is и is not test для идентификатора объекта: x - это y - истина, если и только если x и y - это один и тот же объект. Идентичность объекта определяется с помощью функции id(). x не равно y дает значение обратной истинности.

1 голос
/ 28 марта 2020

Если вы используете is только для сравнения с None, что, как я полагаю, следует сделать, тогда вопрос не имеет значения, поскольку None имеет четко определенный адрес

>>> id(None)
10306432
>>> id(None)
10306432
>>> a = None
>>> id(a)
10306432

У меня еще нет чтобы столкнуться с ситуацией, когда a is b дает результат, отличный от id(a) == id(b), но вы все еще не хотите использовать is небрежно:

>>> a = 1
>>> b = 1
>>> id(a), id(b), id(1)
(10914496, 10914496, 10914496)

# 1 has a single address, is fails to recognize that a and b were created separately.

>>> a = 500
>>> b = 500
>>> id(a), id(b), id(500)
(140251806972464, 140251806973200, 140251806973744)

# Unlike the previous case, 500 is created multiple times, each with a different address

>>> a, b = 500, 500
>>> id(a), id(b), id(500)
(140251806972336, 140251806972336, 140251806972464)

# Several instances during the same initialization are created with a single address

>>> a, b = 500, 5*100
>>> id(a), id(b), id(500)
(140251806973104, 140251806973200, 140251806971280)

# However it only works if all are created in the same manner...

>>> a, b = 5*100, 5*100
>>> id(a), id(b), id(500)
(140251806971920, 140251806973392, 140251806973104)

# ... and they have to be created explicitely.


>>> a = 500 ; b = 500
>>> id(a), id(b), id(500)
(140251806973104, 140251806973104, 140251806972464)

# Separating with a semicolon does not change this fact...

>>> 500 is 500
True
>>> a is b
True
>>> a = 500
>>> a is 500
False
>>> a = 500 ; a is 500
True

# However being in the same line is not a basis for always having the same address, even if all values were created explicitly :

>>> any([a is 500 for a in [500]])
False

У других объектов есть свои ошибки c поведение:

>>> a = 'hello'
>>> b = 'hello'
>>> id(a), id(b), id('hello')
(140251789045408, 140251789045408, 140251789045408)

>>> a = 'hello' + ' '
>>> b = 'hello' + ' '
>>> id(a), id(b), id('hello' + ' ')
(140251789044344, 140251789012472, 140251789012920)

>>> a = []
>>> b = []
>>> id(a), id(b), id([])
(140251789066632, 140251789069704, 140251789174216)

Я бы пришел к выводу, что поведение is и id слишком ненадежно для (a is b) == (id(a) == id(b)), чтобы быть полезным , даже если бы оно было истинным , по крайней мере, в случай неизменяемых объектов.

Лично я никогда бы не подумал об использовании is в любом случае, кроме

if x is None:
    pass

, и я резервирую id только для изменяемых объектов или пользовательских классов.

...