Python中x [x <2] = 0的含义是什么?

abe*_*ger 84 python numpy python-2.7

我遇到了一些代码类似的代码

x[x<2]=0
Run Code Online (Sandbox Code Playgroud)

玩弄各种变化,我仍然坚持这种语法的作用.

例子:

>>> 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]
Run Code Online (Sandbox Code Playgroud)

tra*_*t0r 118

这只适用于NumPy数组.列表的行为是无用的,并且特定于Python 2(不是Python 3).您可能需要仔细检查原始对象是否确实是NumPy数组(请参见下文)而不是列表.

但是在这里的代码中,x是一个简单的列表.

以来

x < 2
Run Code Online (Sandbox Code Playgroud)

因此,是假,即0

x[x<2]x[0]

x[0] 变了.

相反,x[x>2]x[True]x[1]

所以,x[1]改变了.

为什么会这样?

比较规则是:

  1. 当您订购两个字符串或两个数字类型时,排序以预期的方式完成(字符串的字典顺序,整数的数字排序).

  2. 当您订购数字和非数字类型时,数字类型首先出现.

  3. 当您订购两个不兼容的类型(两者都不是数字)时,它们按其类型名的字母顺序排序:

所以,我们有以下顺序

numeric <list <string <元组

请参阅Python的比较字符串和int的接受答案.

如果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
Run Code Online (Sandbox Code Playgroud)

  • 鉴于OP特别说"我遇到了一些像这样的代码......",我认为你的答案描述了numpy布尔索引是非常有用的 - 可能值得指出,如果OP滚动他们看到的代码,他们'我几乎肯定会看到一个'导入'为numpy. (11认同)
  • @TimPederick:在NumPy中使用列表推导是一个非常糟糕的主意.它慢了几十到几百倍,它不适用于任意维数组,它更容易搞定元素类型,它创建一个列表而不是数组.布尔数组索引完全正常,并且在NumPy中是预期的. (6认同)
  • 肯定是一个过于聪明的方法吗?(与之比较,比如,`[0如果我<2其他我在x中我是].)或者这是Numpy鼓励的风格? (2认同)

Kar*_*ath 45

>>> x = [1,2,3,4,5]
>>> x<2
False
>>> x[False]
1
>>> x[True]
2
Run Code Online (Sandbox Code Playgroud)

bool简单地转换为整数.索引为0或1.

  • `bool`没有转换为整数,Python中的`bool`是一个整数** (15认同)
  • 你可以添加更多细节,为什么`x <2 == false`? (11认同)
  • 你可能会提到`x`和`2`是["*一致但是任意排序*"](https://docs.python.org/2/library/stdtypes.html#comparisons),并且排序可能会改变不同的Python实现. (7认同)
  • 我还要补充一点,这是一种*聪明的做事方式,在我看来应该避免.明确地做 - OP不得不问这个问题支持我的观点. (2认同)
  • 为了澄清@AnttiHaapala对其他任何人的陈述,`bool`*是`int`的子类*. (2认同)

Ant*_*ala 14

在你的问题的原代码只能在Python 2.如果xlist在Python 2中,比较x < yFalse,如果yint埃格尔.这是因为将列表与整数进行比较是没有意义的.但是在Python 2中,如果操作数不具有可比性,则比较基于CPython对类型名称字母顺序进行排序 ; 此外,所有数字首先出现在混合型比较中.这甚至没有在CPython 2的文档中详细说明,并且不同的Python 2实现可能会给出不同的结果.这是[1, 2, 3, 4, 5] < 2计算结果为False,因为2是一个数字,因此多了一个"小" list的CPython的.这种混合比较最终被认为是一个过于模糊的特征,并在Python 3.0中被删除.


现在,结果<bool; 并且bool是一个子类int:

>>> isinstance(False, int)
True
>>> isinstance(True, int)
True
>>> False == 0
True
>>> True == 1
True
>>> False + 5
5
>>> True + 5
6
Run Code Online (Sandbox Code Playgroud)

所以基本上你取的是0或1元素,这取决于比较是真还是假.


如果您尝试了上述在Python 3的代码,你会得到TypeError: unorderable types: list() < int()由于在Python 3.0的变化:

订购比较

Python 3.0简化了订购比较的规则:

排序比较操作符(<,<=,>=,>)提出一个TypeError例外,当操作数没有意义的自然顺序.因此,这样的表达式1 < '',0 > None或者len <= len不再有效,并且如None < None提高TypeError,而不是返回False.一个必然结果是,对异构列表进行排序不再有意义 - 所有元素必须相互比较.请注意,这不适用于==!=运算符:不同无比类型的对象总是相互比较不相等.


有许多数据类型会使比较运算符超载以执行不同的操作(来自pandas,numpy的数组的数据帧).如果您使用的代码执行了其他操作,那是因为x不是alist,而是一个其他类的实例,其中运算符<被覆盖以返回不是a的值bool; 然后这个值特别由x[](aka __getitem__/ __setitem__)处理

  • `+ False`嗨Perl,嘿JavaScript,你们怎么样? (6认同)

Fil*_*und 9

这还有一个用途:代码高尔夫.Code golf是编写程序的艺术,可以在尽可能少的源代码字节中解决一些问题.

return(a,b)[c<d]
Run Code Online (Sandbox Code Playgroud)

大致相当于

if c < d:
    return b
else:
    return a
Run Code Online (Sandbox Code Playgroud)

除了a和b都在第一个版本中评估,但在第二个版本中没有.

c<d评估为TrueFalse.
(a, b)是一个元组.
对元组进行索引就像在列表上建立索引一样:(3,5)[1]== 5.
True等于1False等于0.

  1. (a,b)[c<d]
  2. (a,b)[True]
  3. (a,b)[1]
  4. b

或者False:

  1. (a,b)[c<d]
  2. (a,b)[False]
  3. (a,b)[0]
  4. a

在堆栈交换网络上有一个很好的列表,您可以对python执行许多令人讨厌的事情,以节省几个字节.https://codegolf.stackexchange.com/questions/54/tips-for-golfing-in-python

虽然在普通代码中不应该使用它,但在你的情况下,这意味着x它既可以作为可以与整数进行比较的东西,也可以作为支持切片的容器,这是一种非常不寻常的组合.正如其他人所指出的那样,这可能是Numpy代码.

  • `Code Golf是编写程序的艺术`:') (6认同)

MSe*_*ert 6

一般来说它可能意味着什么.这是已经解释这是什么意思,如果xlistnumpy.ndarray,但一般只取决于如何比较运算符(<,>,...),以及如何获取/设置项([...]-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!
Run Code Online (Sandbox Code Playgroud)

因为:

  • x < value 相当于 x.__lt__(value)
  • x[value] 是(大致)相当于 x.__getitem__(value)
  • x[value] = othervalue是(也粗略地)相当于x.__setitem__(value, othervalue).

这可以定制,以做任何你想做的事情.就像一个例子(模仿一点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
Run Code Online (Sandbox Code Playgroud)

现在让我们看看如果你使用它会发生什么:

>>> 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])
Run Code Online (Sandbox Code Playgroud)

请注意,这只是一种可能性.你可以自由地实现你想要的几乎所有东西.