I came across some code with a line similar to
我遇到了一些类似的代码
x[x<2]=0
Playing around with variations, I am still stuck on what this syntax does.
玩弄各种变化,我仍然坚持这种语法的作用。
Examples:
例子:
>>> 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]
5 个解决方案
#1
116
This only makes sense with NumPy arrays. The behavior with lists is useless, and specific to Python 2 (not Python 3). You may want to double-check if the original object was indeed a NumPy array (see further below) and not a list.
这只适用于NumPy阵列。列表的行为是无用的,并且特定于Python 2(不是Python 3)。您可能需要仔细检查原始对象是否确实是NumPy数组(请参见下文),而不是列表。
But in your code here, x is a simple list.
但在这里的代码中,x是一个简单的列表。
Since
以来
x < 2
is False i.e 0, therefore
因此,则为假,即0
x[x<2]
is x[0]
x [x <2]是x [0]
x[0]
gets changed.
x [0]改变了。
Conversely, x[x>2]
is x[True]
or x[1]
相反,x [x> 2]是x [True]或x [1]
So, x[1]
gets changed.
所以,x [1]改变了。
Why does this happen?
为什么会这样?
The rules for comparison are:
比较规则是:
-
When you order two strings or two numeric types the ordering is done in the expected way (lexicographic ordering for string, numeric ordering for integers).
当您订购两个字符串或两个数字类型时,排序以预期的方式完成(字符串的字典顺序,整数的数字排序)。
-
When you order a numeric and a non-numeric type, the numeric type comes first.
订购数字和非数字类型时,首先是数字类型。
-
When you order two incompatible types where neither is numeric, they are ordered by the alphabetical order of their typenames:
当您订购两个不兼容的类型(两者都不是数字)时,它们按类型名的字母顺序排序:
So, we have the following order
所以,我们有以下顺序
numeric < list < string < tuple
numeric
See the accepted answer for How does Python compare string and int?.
请参阅Python如何比较字符串和int?的已接受答案。
If x is a NumPy array, then the syntax makes more sense because of boolean array indexing. In that case, x < 2
isn't a boolean at all; it's an array of booleans representing whether each element of x
was less than 2. x[x < 2] = 0
then selects the elements of x
that were less than 2 and sets those cells to 0. See Indexing.
如果x是NumPy数组,那么由于布尔数组索引,语法更有意义。在这种情况下,x <2根本不是布尔值;它是一个布尔数组,表示x的每个元素是否小于2. x [x <2] = 0然后选择小于2的x元素并将这些单元格设置为0.请参阅索引。
>>> 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
#2
45
>>> x = [1,2,3,4,5]
>>> x<2
False
>>> x[False]
1
>>> x[True]
2
The bool is simply converted to an integer. The index is either 0 or 1.
bool简单地转换为整数。索引是0或1。
#3
14
The original code in your question works only in Python 2. If x
is a list
in Python 2, the comparison x < y
is False
if y
is an int
eger. This is because it does not make sense to compare a list with an integer. However in Python 2, if the operands are not comparable, the comparison is based in CPython on the alphabetical ordering of the names of the types; additionally all numbers come first in mixed-type comparisons. This is not even spelled out in the documentation of CPython 2, and different Python 2 implementations could give different results. That is [1, 2, 3, 4, 5] < 2
evaluates to False
because 2
is a number and thus "smaller" than a list
in CPython. This mixed comparison was eventually deemed to be too obscure a feature, and was removed in Python 3.0.
您的问题中的原始代码仅适用于Python 2.如果x是Python 2中的列表,则如果y是整数,则比较x
Now, the result of <
is a bool
; and bool
is a subclass of int
:
现在, <的结果是一个布尔;和bool是int的子类:< p>
>>> isinstance(False, int)
True
>>> isinstance(True, int)
True
>>> False == 0
True
>>> True == 1
True
>>> False + 5
5
>>> True + 5
6
So basically you're taking the element 0 or 1 depending on whether the comparison is true or false.
所以基本上你取的是0或1元素,这取决于比较是真还是假。
If you try the code above in Python 3, you will get TypeError: unorderable types: list() < int()
due to a change in Python 3.0:
如果您在Python 3中尝试上面的代码,您将获得TypeError:unorderable types:list()
Ordering Comparisons
订购比较
Python 3.0 has simplified the rules for ordering comparisons:
Python 3.0简化了排序比较的规则:
The ordering comparison operators (
<
,<=
,>=
,>
) raise aTypeError
exception when the operands don’t have a meaningful natural ordering. Thus, expressions like1 < ''
,0 > None
orlen <= len
are no longer valid, and e.g.None < None
raisesTypeError
instead of returningFalse
. A corollary is that sorting a heterogeneous list no longer makes sense – all the elements must be comparable to each other. Note that this does not apply to the==
and!=
operators: objects of different incomparable types always compare unequal to each other.当操作数没有有意义的自然顺序时,排序比较运算符(<,<=,> =,>)会引发TypeError异常。因此,诸如1“,0> None或len <= len的表达式不再有效,例如,无
引发typeerror而不是返回false。一个必然结果是,排序异构列表不再有意义>
There are many datatypes that overload the comparison operators to do something different (dataframes from pandas, numpy's arrays). If the code that you were using did something else, it was because x
was not a list
, but an instance of some other class with operator <
overridden to return a value that is not a bool
; and this value was then handled specially by x[]
(aka __getitem__
/__setitem__
)
有许多数据类型会使比较运算符超载以执行不同的操作(来自pandas,numpy的数组的数据帧)。如果你使用的代码做了别的事情,那是因为x不是一个列表,而是一个带有operator
#4
9
This has one more use: code golf. Code golf is the art of writing programs that solve some problem in as few source code bytes as possible.
这还有一个用途:代码高尔夫。 Code golf是编写程序的艺术,可以在尽可能少的源代码字节中解决一些问题。
return(a,b)[c<d]
is roughly equivalent to
大致相当于
if c < d:
return b
else:
return a
except that both a and b are evaluated in the first version, but not in the second version.
除了a和b都在第一个版本中评估,但在第二个版本中没有。
c<d
evaluates to True
or False
.(a, b)
is a tuple.
Indexing on a tuple works like indexing on a list: (3,5)[1]
== 5
.True
is equal to 1
and False
is equal to 0
.
c
(a,b)[c<d]
-
(A,B)并[c
] (a,b)[True]
- (A,B)[TRUE]
(a,b)[1]
- (A,B)[1]
b
- b
or for False
:
或者为假:
(a,b)[c<d]
-
(A,B)并[c
] (a,b)[False]
- (A,B)[FALSE]
(a,b)[0]
- (A,B)[0]
a
- 一个
There's a good list on the stack exchange network of many nasty things you can do to python in order to save a few bytes. https://codegolf.stackexchange.com/questions/54/tips-for-golfing-in-python
在堆栈交换网络上有一个很好的列表,您可以对python执行许多讨厌的事情以节省几个字节。 https://codegolf.stackexchange.com/questions/54/tips-for-golfing-in-python
Although in normal code this should never be used, and in your case it would mean that x
acts both as something that can be compared to an integer and as a container that supports slicing, which is a very unusual combination. It's probably Numpy code, as others have pointed out.
虽然在普通代码中不应该使用它,但在你的情况下,它意味着x既可以作为可以与整数进行比较的东西,也可以作为支持切片的容器,这是一种非常不寻常的组合。正如其他人所指出的那样,它可能是Numpy代码。
#5
6
In general it could mean anything. It was already explained what it means if x
is a list
or numpy.ndarray
but in general it only depends on how the comparison operators (<
, >
, ...) and also how the get/set-item ([...]
-syntax) are implemented.
一般来说,它可能意味着什么。已经解释了如果x是列表或numpy.ndarray意味着什么,但一般来说它只取决于比较运算符(<,>,...)以及get / set-item([... ] -syntax)已实施。
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!
Because:
因为:
-
x < value
is equivalent tox.__lt__(value)
- x <值相当于x .__ lt __(value)< li>
-
x[value]
is (roughly) equivalent tox.__getitem__(value)
- x [value](大致)等于x .__ getitem __(value)
-
x[value] = othervalue
is (also roughly) equivalent tox.__setitem__(value, othervalue)
. - x [value] = othervalue(也大致)等于x .__ setitem __(value,othervalue)。
This can be customized to do anything you want. Just as an example (mimics a bit numpys-boolean indexing):
这可以定制,以做任何你想做的事情。就像一个例子(模仿一点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
So now let's see what happens if you use it:
现在让我们看看如果你使用它会发生什么:
>>> 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])
Notice this is just one possibility. You are free to implement almost everything you want.
请注意,这只是一种可能性。你可以*地实现你想要的几乎所有东西。
#1
116
This only makes sense with NumPy arrays. The behavior with lists is useless, and specific to Python 2 (not Python 3). You may want to double-check if the original object was indeed a NumPy array (see further below) and not a list.
这只适用于NumPy阵列。列表的行为是无用的,并且特定于Python 2(不是Python 3)。您可能需要仔细检查原始对象是否确实是NumPy数组(请参见下文),而不是列表。
But in your code here, x is a simple list.
但在这里的代码中,x是一个简单的列表。
Since
以来
x < 2
is False i.e 0, therefore
因此,则为假,即0
x[x<2]
is x[0]
x [x <2]是x [0]
x[0]
gets changed.
x [0]改变了。
Conversely, x[x>2]
is x[True]
or x[1]
相反,x [x> 2]是x [True]或x [1]
So, x[1]
gets changed.
所以,x [1]改变了。
Why does this happen?
为什么会这样?
The rules for comparison are:
比较规则是:
-
When you order two strings or two numeric types the ordering is done in the expected way (lexicographic ordering for string, numeric ordering for integers).
当您订购两个字符串或两个数字类型时,排序以预期的方式完成(字符串的字典顺序,整数的数字排序)。
-
When you order a numeric and a non-numeric type, the numeric type comes first.
订购数字和非数字类型时,首先是数字类型。
-
When you order two incompatible types where neither is numeric, they are ordered by the alphabetical order of their typenames:
当您订购两个不兼容的类型(两者都不是数字)时,它们按类型名的字母顺序排序:
So, we have the following order
所以,我们有以下顺序
numeric < list < string < tuple
numeric
See the accepted answer for How does Python compare string and int?.
请参阅Python如何比较字符串和int?的已接受答案。
If x is a NumPy array, then the syntax makes more sense because of boolean array indexing. In that case, x < 2
isn't a boolean at all; it's an array of booleans representing whether each element of x
was less than 2. x[x < 2] = 0
then selects the elements of x
that were less than 2 and sets those cells to 0. See Indexing.
如果x是NumPy数组,那么由于布尔数组索引,语法更有意义。在这种情况下,x <2根本不是布尔值;它是一个布尔数组,表示x的每个元素是否小于2. x [x <2] = 0然后选择小于2的x元素并将这些单元格设置为0.请参阅索引。
>>> 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
#2
45
>>> x = [1,2,3,4,5]
>>> x<2
False
>>> x[False]
1
>>> x[True]
2
The bool is simply converted to an integer. The index is either 0 or 1.
bool简单地转换为整数。索引是0或1。
#3
14
The original code in your question works only in Python 2. If x
is a list
in Python 2, the comparison x < y
is False
if y
is an int
eger. This is because it does not make sense to compare a list with an integer. However in Python 2, if the operands are not comparable, the comparison is based in CPython on the alphabetical ordering of the names of the types; additionally all numbers come first in mixed-type comparisons. This is not even spelled out in the documentation of CPython 2, and different Python 2 implementations could give different results. That is [1, 2, 3, 4, 5] < 2
evaluates to False
because 2
is a number and thus "smaller" than a list
in CPython. This mixed comparison was eventually deemed to be too obscure a feature, and was removed in Python 3.0.
您的问题中的原始代码仅适用于Python 2.如果x是Python 2中的列表,则如果y是整数,则比较x
Now, the result of <
is a bool
; and bool
is a subclass of int
:
现在, <的结果是一个布尔;和bool是int的子类:< p>
>>> isinstance(False, int)
True
>>> isinstance(True, int)
True
>>> False == 0
True
>>> True == 1
True
>>> False + 5
5
>>> True + 5
6
So basically you're taking the element 0 or 1 depending on whether the comparison is true or false.
所以基本上你取的是0或1元素,这取决于比较是真还是假。
If you try the code above in Python 3, you will get TypeError: unorderable types: list() < int()
due to a change in Python 3.0:
如果您在Python 3中尝试上面的代码,您将获得TypeError:unorderable types:list()
Ordering Comparisons
订购比较
Python 3.0 has simplified the rules for ordering comparisons:
Python 3.0简化了排序比较的规则:
The ordering comparison operators (
<
,<=
,>=
,>
) raise aTypeError
exception when the operands don’t have a meaningful natural ordering. Thus, expressions like1 < ''
,0 > None
orlen <= len
are no longer valid, and e.g.None < None
raisesTypeError
instead of returningFalse
. A corollary is that sorting a heterogeneous list no longer makes sense – all the elements must be comparable to each other. Note that this does not apply to the==
and!=
operators: objects of different incomparable types always compare unequal to each other.当操作数没有有意义的自然顺序时,排序比较运算符(<,<=,> =,>)会引发TypeError异常。因此,诸如1“,0> None或len <= len的表达式不再有效,例如,无
引发typeerror而不是返回false。一个必然结果是,排序异构列表不再有意义>
There are many datatypes that overload the comparison operators to do something different (dataframes from pandas, numpy's arrays). If the code that you were using did something else, it was because x
was not a list
, but an instance of some other class with operator <
overridden to return a value that is not a bool
; and this value was then handled specially by x[]
(aka __getitem__
/__setitem__
)
有许多数据类型会使比较运算符超载以执行不同的操作(来自pandas,numpy的数组的数据帧)。如果你使用的代码做了别的事情,那是因为x不是一个列表,而是一个带有operator
#4
9
This has one more use: code golf. Code golf is the art of writing programs that solve some problem in as few source code bytes as possible.
这还有一个用途:代码高尔夫。 Code golf是编写程序的艺术,可以在尽可能少的源代码字节中解决一些问题。
return(a,b)[c<d]
is roughly equivalent to
大致相当于
if c < d:
return b
else:
return a
except that both a and b are evaluated in the first version, but not in the second version.
除了a和b都在第一个版本中评估,但在第二个版本中没有。
c<d
evaluates to True
or False
.(a, b)
is a tuple.
Indexing on a tuple works like indexing on a list: (3,5)[1]
== 5
.True
is equal to 1
and False
is equal to 0
.
c
(a,b)[c<d]
-
(A,B)并[c
] (a,b)[True]
- (A,B)[TRUE]
(a,b)[1]
- (A,B)[1]
b
- b
or for False
:
或者为假:
(a,b)[c<d]
-
(A,B)并[c
] (a,b)[False]
- (A,B)[FALSE]
(a,b)[0]
- (A,B)[0]
a
- 一个
There's a good list on the stack exchange network of many nasty things you can do to python in order to save a few bytes. https://codegolf.stackexchange.com/questions/54/tips-for-golfing-in-python
在堆栈交换网络上有一个很好的列表,您可以对python执行许多讨厌的事情以节省几个字节。 https://codegolf.stackexchange.com/questions/54/tips-for-golfing-in-python
Although in normal code this should never be used, and in your case it would mean that x
acts both as something that can be compared to an integer and as a container that supports slicing, which is a very unusual combination. It's probably Numpy code, as others have pointed out.
虽然在普通代码中不应该使用它,但在你的情况下,它意味着x既可以作为可以与整数进行比较的东西,也可以作为支持切片的容器,这是一种非常不寻常的组合。正如其他人所指出的那样,它可能是Numpy代码。
#5
6
In general it could mean anything. It was already explained what it means if x
is a list
or numpy.ndarray
but in general it only depends on how the comparison operators (<
, >
, ...) and also how the get/set-item ([...]
-syntax) are implemented.
一般来说,它可能意味着什么。已经解释了如果x是列表或numpy.ndarray意味着什么,但一般来说它只取决于比较运算符(<,>,...)以及get / set-item([... ] -syntax)已实施。
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!
Because:
因为:
-
x < value
is equivalent tox.__lt__(value)
- x <值相当于x .__ lt __(value)< li>
-
x[value]
is (roughly) equivalent tox.__getitem__(value)
- x [value](大致)等于x .__ getitem __(value)
-
x[value] = othervalue
is (also roughly) equivalent tox.__setitem__(value, othervalue)
. - x [value] = othervalue(也大致)等于x .__ setitem __(value,othervalue)。
This can be customized to do anything you want. Just as an example (mimics a bit numpys-boolean indexing):
这可以定制,以做任何你想做的事情。就像一个例子(模仿一点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
So now let's see what happens if you use it:
现在让我们看看如果你使用它会发生什么:
>>> 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])
Notice this is just one possibility. You are free to implement almost everything you want.
请注意,这只是一种可能性。你可以*地实现你想要的几乎所有东西。