Je suis tombé sur un code avec une ligne similaire à
Jouer avec des variations, je suis encore coincé sur ce qui fait de cette syntaxe.
Exemples :
Je suis tombé sur un code avec une ligne similaire à
Jouer avec des variations, je suis encore coincé sur ce qui fait de cette syntaxe.
Exemples :
Cela n'a de sens avec NumPy tableaux. Le comportement avec des listes est inutile, et spécifique à Python 2 (pas de Python 3). Vous pouvez double-vérifier si l'objet initial était en effet un tableau NumPy (voir ci-dessous) et non sur une liste.
Mais dans ton code ici, x est une simple liste.
Depuis
x < 2
est Faux j'.e 0, donc
x[x<2]
est x[0]
x[0]
est changé.
À l'inverse, x[x>2]
est x[True]
ou x[1]
Donc, x[1]
est changé.
Pourquoi est-ce arrivé?
Les règles à des fins de comparaison sont les suivants:
Lorsque vous commandez deux chaînes ou deux types numériques de la commande se fait en la manière prévue (lexicographique de commande pour la chaîne numérique de la commande pour les entiers).
Lorsque vous commandez un code numérique et non-numérique de type, le type numérique vient en premier.
Lorsque vous commandez deux types incompatibles où ni est numérique, ils sont classés par l'ordre alphabétique de leur typenames:
Donc, nous avons l'ordre suivant
numérique < list < string < tuple
Voir la accepté de répondre pour Comment Python comparer string et int?.
Si x est un tableau NumPy, la syntaxe a plus de sens en raison de booléen tableau d'indexation. Dans ce cas, x < 2
n'est pas un booléen à tous; c'est un tableau de booléens indiquant si chaque élément de l' x
a moins de 2. x[x < 2] = 0
puis sélectionne les éléments d' x
qui ont moins de 2 et jeux de ces cellules à 0. Voir L'Indexation.
>>> 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
Le code d'origine dans votre question ne fonctionne qu'en Python 2. Si x
est list
en Python 2, la comparaison x < y
est False
si y
est int
eger. C'est parce qu'il ne fait pas de sens de comparer une liste avec un nombre entier. Cependant en Python 2, si les opérandes ne sont pas comparables, la comparaison est basée dans Disponible sur l' ordre alphabétique des noms des types; en outre tous les numéros de la première place de mixte-type de comparaisons. Ce n'est même pas précisé dans la documentation de Disponible 2, et les différentes implémentations de Python 2 pourrait donner des résultats différents. C'est - [1, 2, 3, 4, 5] < 2
évalue False
car 2
est un nombre, et donc plus "petit" qu'un list
dans Disponible. Ce mixte de comparaison a finalement été jugée trop obscur d'une fonction, et a été supprimée en Python 3.0.
Maintenant, le résultat de l' <
est bool
; bool
est une sous-classe de int
:
>>> isinstance(False, int)
True
>>> isinstance(True, int)
True
>>> False == 0
True
>>> True == 1
True
>>> False + 5
5
>>> True + 5
6
Donc, fondamentalement, vous prenez l'élément 0 ou 1 selon que la comparaison est vraie ou fausse.
Si vous essayez le code ci-dessus en Python 3, vous obtiendrez TypeError: unorderable types: list() < int()
en raison d' un changement de Python 3.0:
La Commande De Comparaisons
Python 3.0 a simplifié les règles de classement des comparaisons:
La commande des opérateurs de comparaison (
<
,<=
,>=
,>
) posent unTypeError
exception lorsque les opérandes ne pas avoir un sens naturel de la commande. Ainsi, des expressions comme1 < ''
,0 > None
oulen <= len
"ne sont plus valables, et, par exemple,None < None
soulèveTypeError
au lieu de renvoyerFalse
. Un corollaire est que le tri d'un ensemble hétérogène de la liste n'a plus de sens – tous les éléments doivent être comparables les uns aux autres. Notez que ceci ne s'applique pas à l'==
et!=
opérateurs: les objets de différents incomparable types de comparer toujours inégaux les uns aux autres.
Il existe de nombreux types de données qui surcharge les opérateurs de comparaison à faire quelque chose de différent (dataframes de pandas, numpy de tableaux). Si le code que vous utilisiez fait autre chose, c'était parce qu' x
était pas un list
, mais une instance d'une autre classe avec l'opérateur <
substituée pour renvoyer une valeur qui n'est pas un bool
; et cette valeur a ensuite été traitées spécialement en x[]
(aka __getitem__
/__setitem__
)
Cela a une autre utilité: code de golf. Code de golf est l'art de l'écriture de programmes qui permettent de résoudre un certain problème en aussi peu de code source octets que possible.
return(a,b)[c<d]
est à peu près équivalent
if c < d:
return b
else:
return a
sauf que a et b sont évaluées dans la première version, mais pas dans la deuxième version.
c<d
évalue True
ou False
.(a, b)
est un n-uplet.
L'indexation sur un n-uplet de travaux tels que l'indexation sur une liste: (3,5)[1]
== 5
.True
est égal à 1
et False
est égal à 0
.
(a,b)[c<d]
(a,b)[True]
(a,b)[1]
b
ou pour False
:
(a,b)[c<d]
(a,b)[False]
(a,b)[0]
a
Il y a une bonne liste sur la pile réseau d'échange de beaucoup de vilaines choses que vous pouvez faire pour python afin d'économiser quelques octets. https://codegolf.stackexchange.com/questions/54/tips-for-golfing-in-python
Bien que dans le code, ce ne doit jamais être utilisé, et dans votre cas, cela signifierait que x
agit à la fois comme quelque chose qui peut être comparé à un entier et comme un conteneur qui prend en charge le découpage, ce qui est un très étrange combinaison. C'est probablement Numpy code, comme d'autres l'ont souligné.
En général cela pourrait signifier quelque chose. Il a été déjà expliqué ce que cela signifie si x
est list
ou numpy.ndarray
, mais en général, il ne dépend que de la façon dont les opérateurs de comparaison (<
, >
, ...) et aussi comment les get/set-point ([...]
-syntaxe) sont mis en œuvre.
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!
Parce que:
x < value
est équivalent à x.__lt__(value)
x[value]
est de (environ) équivalent à x.__getitem__(value)
x[value] = othervalue
est (environ) équivalent à x.__setitem__(value, othervalue)
.Ce qui peut être personnalisé pour faire tout ce que vous voulez. Juste à titre d'exemple (imite un peu numpys-boolean indexation):
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
Maintenant, nous allons voir ce qui se passe si vous l'utilisez:
>>> 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])
À noter que c'est juste une possibilité. Vous êtes libre de mettre presque tout ce que vous voulez.
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.