Encontré un código con una línea similar a
x[x<2]=0
Jugando con variaciones, todavía estoy atascado en lo que hace esta sintaxis.
Ejemplos:
>>> x = [1,2,3,4,5]
>>> x[x<2]
1
>>> x[x<3]
1
>>> x[x>2]
2
>>> x[x<2]=0
>>> x
[0, 2, 3, 4, 5]
python
python-2.7
numpy
aberger
fuente
fuente
TypeError: unorderable types: list() < int()
.Respuestas:
Esto solo tiene sentido con matrices NumPy . El comportamiento con listas es inútil y específico de Python 2 (no Python 3). Es posible que desee volver a verificar si el objeto original era de hecho una matriz NumPy (ver más abajo) y no una lista.
Pero en su código aquí, x es una lista simple.
Ya que
x < 2
es falso, es decir, 0, por lo tanto
x[x<2]
esx[0]
x[0]
se cambia.Por el contrario,
x[x>2]
esx[True]
ox[1]
Entonces,
x[1]
se cambia.¿Por qué pasó esto?
Las reglas de comparación son:
Cuando ordena dos cadenas o dos tipos numéricos, el orden se realiza de la forma esperada (ordenamiento lexicográfico para cadenas, ordenamiento numérico para enteros).
Cuando solicita un tipo numérico y uno no numérico, el tipo numérico es lo primero.
Cuando ordena dos tipos incompatibles donde ninguno es numérico, se ordenan por orden alfabético de sus nombres de tipo:
Entonces, tenemos el siguiente orden
numérico <lista <cadena <tupla
Vea la respuesta aceptada para ¿Cómo compara Python string e int? .
Si x es una matriz NumPy , entonces la sintaxis tiene más sentido debido a la indexación de la matriz booleana . En ese caso,
x < 2
no es un booleano en absoluto; es una matriz de valores booleanos que representan si cada elemento dex
era menor que 2.x[x < 2] = 0
luego selecciona los elementos dex
que eran menores que 2 y establece esas celdas en 0. Consulte Indexación .>>> x = np.array([1., -1., -2., 3]) >>> x < 0 array([False, True, True, False], dtype=bool) >>> x[x < 0] += 20 # All elements < 0 get increased by 20 >>> x array([ 1., 19., 18., 3.]) # Only elements < 0 are affected
fuente
import
numpy.[0 if i < 2 else i for i in x]
,.) ¿O es este estilo fomentado en Numpy?x[x<2]
devolverá una matriz numpy, mientras que[0 if i<2 else i for i in x]
devuelve una lista. Esto se debe a quex[x<2]
es una operación de indexación (a la que se hace referencia en numpy / scipy / pandas como una operación de corte debido a la capacidad de enmascarar datos), mientras que la comprensión de la lista es una nueva definición de objeto. Ver indexación NumPy>>> x = [1,2,3,4,5] >>> x<2 False >>> x[False] 1 >>> x[True] 2
El bool simplemente se convierte en un número entero. El índice es 0 o 1.
fuente
x
y2
están " ordenados de forma coherente pero arbitraria " y que el orden puede cambiar en diferentes implementaciones de Python.x<2 == false
?bool
no se convierte en un número entero,bool
en Python es un número enterobool
es una subclase deint
.El código original de su pregunta solo funciona en Python 2. Si
x
es unlist
en Python 2, la comparaciónx < y
esFalse
siy
es unint
eger. Esto se debe a que no tiene sentido comparar una lista con un número entero. Sin embargo, en Python 2, si los operandos no son comparables, la comparación se basa en CPython en el orden alfabético de los nombres de los tipos ; además, todos los números aparecen primero en las comparaciones de tipo mixto . Esto ni siquiera está detallado en la documentación de CPython 2, y diferentes implementaciones de Python 2 podrían dar resultados diferentes. Eso se[1, 2, 3, 4, 5] < 2
evalúaFalse
porque2
es un número y, por lo tanto, "más pequeño" quelist
en CPython. Esta comparación mixta fue finalmentese consideró una característica demasiado oscura y se eliminó en Python 3.0.Ahora, el resultado de
<
es abool
; ybool
es una subclase deint
:>>> isinstance(False, int) True >>> isinstance(True, int) True >>> False == 0 True >>> True == 1 True >>> False + 5 5 >>> True + 5 6
Básicamente, estás tomando el elemento 0 o 1 dependiendo de si la comparación es verdadera o falsa.
Si prueba el código anterior en Python 3, obtendrá
TypeError: unorderable types: list() < int()
debido a un cambio en Python 3.0 :Hay muchos tipos de datos que sobrecargan los operadores de comparación para hacer algo diferente (marcos de datos de pandas, matrices de numpy). Si el código que estaba usando hizo algo más, fue porque no
x
era unlist
, sino una instancia de otra clase con el operador<
anulado para devolver un valor que no es unbool
; y este valor fue manejado especialmente porx[]
(también conocido como__getitem__
/__setitem__
)fuente
+False
Hola Perl, hola JavaScript, ¿cómo están?UNARY_POSITIVE
código de operación que llama al__pos__
__setitem__
lugar de__getitem__
en su última sección. También espero que no le importe que mi respuesta se haya inspirado en esa parte de su respuesta.__getitem__
aunque igualmente podría haber sido__setitem__
y__delitem__
Esto tiene un uso más: código golf. Code golf es el arte de escribir programas que resuelven algún problema en el menor número posible de bytes de código fuente.
return(a,b)[c<d]
es aproximadamente equivalente a
if c < d: return b else: return a
excepto que tanto a como b se evalúan en la primera versión, pero no en la segunda versión.
c<d
evalúa aTrue
oFalse
.(a, b)
es una tupla.Indexar en una tupla funciona como indexar en una lista:
(3,5)[1]
==5
.True
es igual1
yFalse
es igual a0
.(a,b)[c<d]
(a,b)[True]
(a,b)[1]
b
o para
False
:(a,b)[c<d]
(a,b)[False]
(a,b)[0]
a
Hay una buena lista en la red de intercambio de pilas de muchas cosas desagradables que puede hacer con Python para ahorrar unos pocos bytes. /codegolf/54/tips-for-golfing-in-python
Aunque en el código normal, esto nunca debería usarse, y en su caso significaría que
x
actúa tanto como algo que se puede comparar con un número entero como un contenedor que admite el corte, que es una combinación muy inusual. Probablemente sea código Numpy, como han señalado otros.fuente
Code Golf is the art of writing programs
: ')En general, podría significar cualquier cosa . Ya era explicó lo que significa que si
x
es unalist
onumpy.ndarray
pero en general sólo depende de cómo los operadores de comparación (<
,>
también cómo, ...) y el / puesta a punto get ([...]
se implementan -Sintaxis).x.__getitem__(x.__lt__(2)) # this is what x[x < 2] means! x.__setitem__(x.__lt__(2), 0) # this is what x[x < 2] = 0 means!
Porque:
x < value
es equivalente ax.__lt__(value)
x[value]
es (aproximadamente) equivalente ax.__getitem__(value)
x[value] = othervalue
es (también aproximadamente) equivalente ax.__setitem__(value, othervalue)
.Esto se puede personalizar para hacer lo que desee. Solo como ejemplo (imita una indexación numpys-booleana):
class Test: def __init__(self, value): self.value = value def __lt__(self, other): # You could do anything in here. For example create a new list indicating if that # element is less than the other value res = [item < other for item in self.value] return self.__class__(res) def __repr__(self): return '{0} ({1})'.format(self.__class__.__name__, self.value) def __getitem__(self, item): # If you index with an instance of this class use "boolean-indexing" if isinstance(item, Test): res = self.__class__([i for i, index in zip(self.value, item) if index]) return res # Something else was given just try to use it on the value return self.value[item] def __setitem__(self, item, value): if isinstance(item, Test): self.value = [i if not index else value for i, index in zip(self.value, item)] else: self.value[item] = value
Así que ahora veamos qué pasa si lo usas:
>>> a = Test([1,2,3]) >>> a Test ([1, 2, 3]) >>> a < 2 # calls __lt__ Test ([True, False, False]) >>> a[Test([True, False, False])] # calls __getitem__ Test ([1]) >>> a[a < 2] # or short form Test ([1]) >>> a[a < 2] = 0 # calls __setitem__ >>> a Test ([0, 2, 3])
Note que esta es solo una posibilidad. Eres libre de implementar casi todo lo que quieras.
fuente