Me deparei com um código com uma linha semelhante a
x[x<2]=0
Brincando com variações, ainda estou preso no que essa sintaxe faz.
Exemplos:
>>> 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]
Me deparei com um código com uma linha semelhante a
x[x<2]=0
Brincando com variações, ainda estou preso no que essa sintaxe faz.
Exemplos:
>>> 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]
TypeError: unorderable types: list() < int().
Respostas:
Isso só faz sentido com matrizes NumPy . O comportamento com listas é inútil e específico para Python 2 (não Python 3). Você pode querer verificar novamente se o objeto original era de fato um array NumPy (veja mais abaixo) e não uma lista.
Mas em seu código aqui, x é uma lista simples.
Desde a
x < 2
é falso, ou seja, 0, portanto
x[x<2] é x[0]
x[0] é alterado.
Por outro lado, x[x>2]é x[True]oux[1]
Então, x[1]é alterado.
Por que isso acontece?
As regras de comparação são:
Quando você pede duas strings ou dois tipos numéricos, a ordenação é feita da maneira esperada (ordenação lexicográfica para string, ordenação numérica para inteiros).
Quando você pede um tipo numérico e um não numérico, o tipo numérico vem primeiro.
Quando você ordena dois tipos incompatíveis onde nenhum é numérico, eles são ordenados pela ordem alfabética de seus nomes de tipo:
Então, temos a seguinte ordem
numérico <lista <string <tupla
Veja a resposta aceita para Como o Python compara string e int? .
Se x for um array NumPy , a sintaxe faz mais sentido por causa da indexação do array booleano . Nesse caso, x < 2não é booleano; é uma matriz de booleanos que representam se cada elemento de xera menor que 2. x[x < 2] = 0então seleciona os elementos de xque eram menores que 2 e define essas células como 0. Veja Indexação .
>>> 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
importpara entorpecido.
[0 if i < 2 else i for i in x],.) Ou esse estilo é encorajado no Numpy?
x[x<2]retornará um array numpy, enquanto [0 if i<2 else i for i in x]retorna uma lista. Isso ocorre porque x[x<2]é uma operação de indexação (referida em numpy / scipy / pandas como uma operação de corte devido à capacidade de mascarar dados), enquanto a compreensão de lista é uma nova definição de objeto. Consulte a indexação NumPy
>>> x = [1,2,3,4,5]
>>> x<2
False
>>> x[False]
1
>>> x[True]
2
O bool é simplesmente convertido em um número inteiro. O índice é 0 ou 1.
xe 2são " ordenados de forma consistente, mas arbitrária " e que a ordem pode mudar em diferentes implementações Python.
x<2 == false?
boolnão é convertido em um inteiro, a boolem Python é um inteiro
bool é uma subclasse de int.
O código original em sua pergunta funciona apenas no Python 2. Se xfor um listno Python 2, a comparação x < yé Falsese yfor um integer. Isso ocorre porque não faz sentido comparar uma lista com um inteiro. No entanto, no Python 2, se os operandos não são comparáveis, a comparação é baseada no CPython na ordem alfabética dos nomes dos tipos ; além disso, todos os números vêm primeiro em comparações de tipos mistos . Isso nem mesmo está explicitado na documentação do CPython 2, e diferentes implementações do Python 2 podem dar resultados diferentes. Isso é [1, 2, 3, 4, 5] < 2avaliado como Falseporque 2é um número e, portanto, "menor" que a listno CPython. Esta comparação mista foi eventualmenteconsiderado um recurso muito obscuro e foi removido no Python 3.0.
Agora, o resultado de <é um bool; e boolé uma subclasse deint :
>>> isinstance(False, int)
True
>>> isinstance(True, int)
True
>>> False == 0
True
>>> True == 1
True
>>> False + 5
5
>>> True + 5
6
Então, basicamente, você está pegando o elemento 0 ou 1, dependendo se a comparação é verdadeira ou falsa.
Se você tentar o código acima no Python 3, obterá TypeError: unorderable types: list() < int()devido a uma alteração no Python 3.0 :
Comparações de pedidos
Python 3.0 simplificou as regras para comparações de pedidos:
Os operadores de comparação ordenação (
<,<=,>=,>) levantar umaTypeErrorexceção quando os operandos não têm uma ordenação natural significativa. Assim, expressões como1 < '',0 > Noneoulen <= lennão são mais válidas e, por exemplo,None < Noneaumenta emTypeErrorvez de retornarFalse. Um corolário é que classificar uma lista heterogênea não faz mais sentido - todos os elementos devem ser comparáveis entre si. Observe que isso não se aplica aos operadores==e!=: objetos de diferentes tipos incomparáveis sempre se comparam de forma desigual.
Existem muitos tipos de dados que sobrecarregam os operadores de comparação para fazer algo diferente (dataframes de pandas, matrizes de numpy). Se o código que você estava usando fazia outra coisa, era porque nãox era umlist , mas uma instância de alguma outra classe com operador <substituído para retornar um valor que não é um bool; e este valor foi então tratado especialmente por x[](aka __getitem__/ __setitem__)
+FalseOlá, Perl, ei JavaScript, como estão?
UNARY_POSITIVEopcode que chama o__pos__
__setitem__vez de __getitem__em sua última seção. Além disso, espero que você não se importe que minha resposta tenha sido inspirada por essa parte de sua resposta.
__getitem__embora igualmente poderia ter sido __setitem__e__delitem__
Isso tem mais uma utilidade: código de golfe. O golfe do código é a arte de escrever programas que resolvam alguns problemas com o mínimo possível de bytes de código-fonte.
return(a,b)[c<d]
é aproximadamente equivalente a
if c < d:
return b
else:
return a
exceto que tanto a quanto b são avaliados na primeira versão, mas não na segunda versão.
c<davalia para Trueou False.
(a, b)é uma tupla.
A indexação em uma tupla funciona como a indexação em uma lista: (3,5)[1]== 5.
Trueé igual a 1e Falseé igual a 0.
(a,b)[c<d](a,b)[True](a,b)[1]bou para False:
(a,b)[c<d](a,b)[False](a,b)[0]aHá uma boa lista na rede de troca de pilha de muitas coisas desagradáveis que você pode fazer no python para economizar alguns bytes. /codegolf/54/tips-for-golfing-in-python
Embora no código normal isso nunca deva ser usado, no seu caso significaria que xatua tanto como algo que pode ser comparado a um inteiro e como um contêiner que suporta o fatiamento, o que é uma combinação muito incomum. Provavelmente é um código Numpy, como outros apontaram.
Code Golf is the art of writing programs: ')
Em geral, pode significar qualquer coisa . Ele já foi explicado o que significa que se xé um listou numpy.ndarraymas em geral ele só depende de como os operadores de comparação ( <, >...) e também como o get / set-item ( [...]-syntax) são implementadas.
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 é equivalente a x.__lt__(value)x[value] é (aproximadamente) equivalente a x.__getitem__(value) x[value] = othervalueé (também aproximadamente) equivalente a x.__setitem__(value, othervalue).Isto pode ser personalizado para fazer qualquer coisa que quiser. Apenas como exemplo (imita uma indexação bit numpys-boolean):
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
Então, agora vamos ver o que acontece se você usá-lo:
>>> 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])
Observe que esta é apenas uma possibilidade. Você é livre para implementar quase tudo o que quiser.