Compare se duas variáveis ​​fazem referência ao mesmo objeto em python

Respostas:

133

Isso isé para quê : x is yretorna Truese xe yforem o mesmo objeto.

Jochen Ritzel
fonte
6
No exemplo, x is zretorna False. Mas se x e z forem atribuídos aos mesmos valores em vez de listas (por exemplo x, z = 13, 13), então x is zretorna True. Por que é que?
Bill
12
@Bill: Esse é um artefato de como o python lida com ints. Python aloca objetos inteiros para os quais xe zapontam. Uma vez que pequenos inteiros são comuns a falhas (-1 como um valor de erro, 0 sempre que você realmente indexar algo, pequenos números geralmente são valores padrão razoáveis) Python otimiza pré-alocando pequenos números (-5 a 256) e reutiliza o mesmo objeto inteiro. Portanto, seu exemplo só funciona para números neste intervalo. Tente atribuir algo maior, ou seja 270. Para mais informações olhada aqui
ted
1
@AndresR Não, isso está errado. isverifica se dois nomes fazem referência ao mesmo local de memória. Não tem nada a ver com o próprio objeto. É fácil ter objetos imutáveis, como strings iguais, mas não armazenadas no mesmo local, por exemplo, ''a'*10000 is 'a' * 10000é False.
Jochen Ritzel de
1
@JochenRitzel Você está totalmente certo, obrigado por este comentário! Então, eu não entendo o que está acontecendo com "af" is "af"ou () is ()... por que eles compartilham o mesmo local de memória?
AndresR de
2
@AndreasR Para strings / números literais no código, o compilador verifica se eles existem apenas uma vez e os reutiliza. Valores especiais como (), None, True, False etc também são definidos como singletons. Durante a execução, o tempo de execução também tenta reutilizar pequenos números e strings, mas no final é uma troca entre velocidade e memória e o que acontece depende de como o tempo de execução do Python foi implementado.
Jochen Ritzel
12

y is xserá True, y is zserá False.

Mark Rushakoff
fonte
11

Enquanto as duas soluções corretas x is ze id(x) == id(z)já foram postadas, quero ressaltar um detalhe de implementação de python. Python armazena inteiros como objetos, como uma otimização, ele gera um monte de pequenos inteiros em seu início (-5 a 256) e aponta CADA variável que contém um inteiro com um pequeno valor para esses objetos pré-inicializados. Mais informações

Isso significa que para objetos inteiros inicializados com os mesmos pequenos números (-5 a 256), verificar se dois objetos são iguais retornará verdadeiro ( ON C-Pyhon , pelo que estou ciente, este é um detalhe de implementação ), enquanto para maiores números, isso só retorna verdadeiro se um objeto for inicializado do outro.

> i = 13
> j = 13
> i is j
True

> a = 280
> b = 280
> a is b
False

> a = b
> a
280
> a is b
True
ted
fonte
python3.6: a = 98765; b = 98765; a é b => Verdadeiro. Aparentemente, algo mudou.
Mikhail Kalashnikov
@MikhailKalashnikov Nope. Eu testei no Python 3.6.2, isso ainda existe.
nix
ainda existe no python 3.7.7
Bill Huang
9

Você também pode usar id () para verificar a qual objeto único cada nome de variável se refere.

In [1]: x1, x2 = 'foo', 'foo'

In [2]: x1 == x2
Out[2]: True

In [3]: id(x1), id(x2)
Out[3]: (4509849040, 4509849040)

In [4]: x2 = 'foobar'[0:3]

In [5]: x2
Out[5]: 'foo'

In [6]: x1 == x2
Out[6]: True

In [7]: x1 is x2
Out[7]: False

In [8]: id(x1), id(x2)
Out[8]: (4509849040, 4526514944)
Conta
fonte
A nota de @ ted sobre o uso de id é bastante relevante aqui.
Leo Ufimtsev
2

Eu realmente gosto de ter um feedback visual, é por isso que às vezes apenas abro http://www.pythontutor.com/visualize.html#mode=edit para ver como a memória está alocada e o que está referenciando o quê.

insira a descrição da imagem aqui

Adicionado este gif incrível, pois esta resposta é sobre visualização.

user1767754
fonte
2

Isso é de docs.python.org: "Cada objeto tem uma identidade, um tipo e um valor. A identidade de um objeto nunca muda depois de ser criado; você pode considerá-lo como o endereço do objeto na memória. O operador 'é' compara a identidade de dois objetos; a função id () retorna um número inteiro que representa sua identidade. "

Aparentemente, toda vez que você altera o valor, o objeto é recriado conforme indicado pela alteração da identidade. A linha x = 3 seguida pela linha x = 3,14 não dá nenhum erro e dá diferentes identidades, tipos e valores para x.

Scott Woods
fonte
1
Excelente doc catch.
prosti