什么是x [x< 2] = 0表示Python?

时间:2016-04-13 15:27:16

标签: python python-2.7 numpy

我遇到了一些类似于

的代码
x[x<2]=0

使用各种变体,我仍然坚持这种语法的作用。

示例:

>>> 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 个答案:

答案 0 :(得分:117)

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

但是在你的代码中,x是一个简单的列表。

由于

x < 2

是假的 即0,因此

x[x<2]x[0]

x[0]变了。

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

因此,x[1]会发生变化。

为什么会这样?

比较规则是:

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

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

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

  4. 所以,我们有以下顺序

    数字&lt;列表&lt;字符串&lt;元组

    请参阅 How does Python compare string and int? 的接受答案。

    如果x是NumPy数组,则由于布尔数组索引,语法更有意义。在这种情况下,x < 2根本不是布尔值;它是一组布尔值,表示x的每个元素是否小于2. x[x < 2] = 0然后选择小于2的x元素并将这些单元格设置为0 。请参阅 Indexing

    >>> 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
    

答案 1 :(得分:45)

>>> x = [1,2,3,4,5]
>>> x<2
False
>>> x[False]
1
>>> x[True]
2

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

答案 2 :(得分:14)

您问题中的原始代码仅适用于Python 2.如果{2}是{2}} {2},那么x的比较list x < y Falsey eger。这是因为将列表与整数进行比较是没有意义的。但是在Python 2中,如果操作数不具有可比性,则比较基于alphabetical ordering of the names of the types上的CPython;另外所有数字在混合型比较中排在第一位。这甚至没有在CPython 2的文档中详细说明,并且不同的Python 2实现可能会给出不同的结果。这是int评估为[1, 2, 3, 4, 5] < 2,因为False是一个数字,因此比CPython中的2“更小”。这种混合比较最终是deemed to be too obscure a feature,并在Python 3.0中被删除。

现在,list的结果是<;和bool is a subclass of int

bool

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

如果您在Python 3中尝试上面的代码,由于a change in Python 3.0,您将获得>>> isinstance(False, int) True >>> isinstance(True, int) True >>> False == 0 True >>> True == 1 True >>> False + 5 5 >>> True + 5 6

  

订购比较

     

Python 3.0简化了排序比较的规则:

     

当操作数没有有意义的自然时,排序比较运算符(TypeError: unorderable types: list() < int()<<=>=)会引发>异常排序。因此,TypeError1 < ''0 > None等表达式不再有效,例如len <= len提升None < None而不是返回TypeError。一个必然结果是,对异构列表进行排序不再有意义 - 所有元素必须相互比较。请注意,这不适用于False==运算符:不同无比类型的对象总是相互比较不相等。

有许多数据类型重载比较运算符来执行不同(来自pandas,numpy数组的数据帧)。如果您使用的代码执行了其他操作,那是因为!= 不是x ,而是覆盖了运算符list的其他类的实例返回不是<的值;然后,bool(又名x[] / __getitem__)专门处理此值

答案 3 :(得分:9)

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

return(a,b)[c<d]

大致相当于

if c < d:
    return b
else:
    return a

除了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
  5. False

    1. (a,b)[c<d]
    2. (a,b)[False]
    3. (a,b)[0]
    4. a
    5. 在堆栈交换网络上有一个很好的列表,你可以对python执行许多讨厌的事情以节省几个字节。 https://codegolf.stackexchange.com/questions/54/tips-for-golfing-in-python

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

答案 4 :(得分:6)

一般来说,它可能意味着任何。已经解释了xlistnumpy.ndarray时的含义,但一般情况下它只取决于比较运算符(<>的方式, ...)以及如何实现get / set-item([...] - 语法)。

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!

由于:

  • 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

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

>>> 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])

请注意,这只是一种可能性。你可以自由地实现你想要的一切。