una separar repetidas por palabras palabra letras eliminar contar comparar caracteres caracter cadenas cadena python python-3.x operators object-identity

python - separar - el operador ''es'' se comporta de manera diferente al comparar cadenas con espacios



python separar string por caracter (5)

Empecé a aprender Python (Python 3.3) y estaba probando el operador is . Intenté esto:

>>> b = ''is it the space?'' >>> a = ''is it the space?'' >>> a is b False >>> c = ''isitthespace'' >>> d = ''isitthespace'' >>> c is d True >>> e = ''isitthespace?'' >>> f = ''isitthespace?'' >>> e is f False

Parece que el espacio y el signo de interrogación hacen que el comportamiento sea diferente. ¿Que esta pasando?

EDITAR: Sé que debería usar == , solo quería saber por qué is comporta así.


De hecho, su código equivale a comparar objetos id (es decir, su dirección física). Entonces en vez de tu es una comparación:

>>> b = ''is it the space?'' >>> a = ''is it the space?'' >>> a is b False

Tu puedes hacer:

>>> id(a) == id(b) False

Pero, tenga en cuenta que si ayb estuvieran directamente en la comparación, funcionaría.

>>> id(''is it the space?'') == id(''is it the space?'') True

De hecho, en una expresión hay intercambio entre las mismas cadenas estáticas. Pero, en la escala del programa, solo se comparten elementos similares a palabras (por lo tanto, ni espacios ni signos de puntuación).

No debe confiar en este comportamiento, ya que no está documentado en ningún lugar y es un detalle de la implementación.


El operador is basa en la función id , que se guaranteed to be unique among simultaneously existing objects. Específicamente, id devuelve la dirección de memoria del objeto. Parece que CPython tiene direcciones de memoria consistentes para cadenas que contienen solo caracteres az y AZ.

Sin embargo, esto parece ser solo el caso cuando la cadena ha sido asignada a una variable:

Aquí, la identificación de "foo" y la identificación de a son lo mismo. a se ha establecido en "foo" antes de verificar la identificación.

>>> a = "foo" >>> id(a) 4322269384 >>> id("foo") 4322269384

Sin embargo, la identificación de "barra" y la identificación de a son diferentes cuando se verifica la identificación de "barra" antes de establecer a valor igual a "barra".

>>> id("bar") 4322269224 >>> a = "bar" >>> id(a) 4322268984

Verificando el ID de "barra" nuevamente después de configurar a igual" a "barra" se devuelve la misma identificación.

>>> id("bar") 4322268984

Por lo tanto, parece que cPython mantiene direcciones de memoria consistentes para cadenas que contienen solo a-zA-Z cuando esas cadenas están asignadas a una variable. También es completamente posible que esto dependa de la versión: estoy ejecutando Python 2.7.3 en un macbook. Otros pueden obtener resultados completamente diferentes.


Para ampliar un poco la respuesta de Ignacio: El operador es el operador de identidad. Se usa para comparar la identidad del objeto . Si construye dos objetos con los mismos contenidos, generalmente la identidad del objeto no es verdadera. Funciona para algunas cadenas pequeñas porque CPython, la implementación de referencia de Python, almacena los contenidos por separado, haciendo que todos esos objetos hagan referencia al mismo contenido de cadena. Entonces, el operador is devuelve verdadero para esos.

Sin embargo, este es un detalle de implementación de CPython y generalmente no está garantizado para CPython ni para ninguna otra implementación. Así que usar este hecho es una mala idea, ya que puede romperse cualquier otro día.

Para comparar cadenas, use el operador == que compara la igualdad de objetos. Dos objetos de cadena se consideran iguales cuando contienen los mismos caracteres. Así que este es el operador correcto para usar cuando se comparan cadenas, y generalmente is debe evitar si no se desea explícitamente la identidad del objeto (ejemplo: a is False ).

Si está realmente interesado en los detalles, puede encontrar la implementación de las cadenas de CPython here . Pero otra vez: este es el detalle de la implementación, por lo que nunca debe exigir que esto funcione.


el operador ''is'' compara el objeto real.

c is d también debería ser falso. Supongo que Python hace algo de optimización y en ese caso, es el mismo objeto.


Advertencia: esta respuesta se trata de los detalles de implementación de un intérprete de Python específico. comparar cadenas con is == mala idea.

Bueno, al menos para cpython3.4 / 2.7.3, la respuesta es "no, no es el espacio en blanco". No solo el espacio en blanco:

  • Dos literales de cadena compartirán memoria si son alfanuméricos o residen en el mismo bloque (archivo, función, clase o comando de intérprete único)

  • Una expresión que se evalúa como una cadena dará como resultado un objeto que es idéntico al creado con un literal de cadena, si y solo si se crea utilizando constantes y operadores binarios / unarios, y la cadena resultante tiene menos de 21 caracteres.

  • Los personajes únicos son únicos.

Ejemplos

Los literales de cadena alfanuméricos siempre comparten memoria:

>>> x=''aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'' >>> y=''aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'' >>> x is y True

Los literales de cadena no alfanuméricos comparten memoria solo si comparten el bloque sintáctico adjunto:

(Interprete)

>>> x=''`!@#$%^&*() /][=-. >:"?<a''; y=''`!@#$%^&*() /][=-. >:"?<a''; >>> z=''`!@#$%^&*() /][=-. >:"?<a''; >>> x is y True >>> x is z False

(archivo)

x=''`!@#$%^&*() /][=-. >:"?<a''; y=''`!@#$%^&*() /][=-. >:"?<a''; z=(lambda : ''`!@#$%^&*() /][=-. >:"?<a'')() print(x is y) print(x is z)

Salida: True y False

Para las operaciones binarias simples, el compilador hace una propagación de constante muy simple (ver peephole.c ), pero con cadenas solo lo hace si la cadena resultante es más corta que 21 charcters. Si este es el caso, las reglas mencionadas anteriormente están vigentes:

>>> ''a''*10+''a''*10 is ''a''*20 True >>> ''a''*21 is ''a''*21 False >>> ''aaaaaaaaaaaaaaaaaaaaa'' is ''aaaaaaaa'' + ''aaaaaaaaaaaaa'' False >>> t=2; ''a''*t is ''aa'' False >>> ''a''.__add__(''a'') is ''aa'' False >>> x=''a'' ; x+=''a''; x is ''aa'' False

Los personajes únicos siempre comparten memoria, por supuesto:

>>> chr(0x20) is '' '' True