在Python中,x = 0是什么意思?

我碰到一些类似于代码的代码

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] 

这只对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. 当您订购两个string或两个数字types时,按照预期的方式进行sorting(string的字典sorting,整数的数字sorting)。

  2. 当您订购一个数字和一个非数字types时,数字types首先。

  3. 当您订购两个不兼容的types时,它们都是按照其types名称的字母顺序sorting的:

所以,我们有以下的顺序

数字<列表<string<元组

请参阅Python如何比较string和int的接受答案

如果x是一个NumPy数组 ,那么由于布尔数组索引 ,语法更有意义。 在这种情况下, x < 2根本不是布尔值。 它是一个布尔值数组,表示x每个元素是否小于x[x < 2] = 0然后selectx[x < 2] = 0的元素,并将这些单元格设置为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 
 >>> x = [1,2,3,4,5] >>> x<2 False >>> x[False] 1 >>> x[True] 2 

布尔简单地转换为一个整数。 索引是0或1。

您的问题中的原始代码仅适用于Python 2.如果x是Python 2中的list ,则如果yint eger,则比较x < yFalse 。 这是因为将一个列表与一个整数进行比较是没有意义的。 但是,在Python 2中,如果操作数不具有可比性,则比较将基于CPython中按types名称字母顺序排列 ; 另外所有的数字在混合型比较中都是第一位的 。 这甚至没有在CPython 2的文档中详细说明,不同的Python 2实现可能会给出不同的结果。 即[1, 2, 3, 4, 5] < 2计算结果为False因为2是一个数字,因此比CPython中的list “小”。 这个混合的比较最终被认为是一个太模糊的function ,并在Python 3.0中被删除。


现在, <的结果是bool ; 而boolint一个子类

 >>> isinstance(False, int) True >>> isinstance(True, int) True >>> False == 0 True >>> True == 1 True >>> False + 5 5 >>> True + 5 6 

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


如果您在Python 3中尝试使用上面的代码,则会由于Python 3.0中的更改而得到TypeError: unorderable types: list() < int()

订购比较

Python 3.0简化了sorting比较的规则:

当操作数没有有意义的自然sorting时,sorting比较运算符( <<=>=> )会引发TypeErrorexception。 因此, 1 < ''0 > Nonelen <= len等expression式不再有效,例如None < None引发TypeError而不返回False 。 一个推论就是sorting一个异构列表不再有意义 – 所有的元素必须是可比较的。 请注意,这不适用于==!=运算符:不同types的对象总是比较不相等。


有许多数据types重载比较运算符来做一些不同的事情(来自pandas,numpy的数组的数据框)。 如果你正在使用的代码做了其他的事情,那是因为x 不是一个list ,而是一个其他类的一个实例,它的操作符被覆盖,返回一个不是bool ; 然后这个值被x[] (又名__getitem__ / __setitem__ )特别处理

这有一个更多的用途:代码高尔夫。 代码高尔夫是编写程序的艺术,它尽可能less的源代码字节来解决一些问题。

 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

或者False

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

在堆栈交换networking上有一个很好的列表,你可以对python进行很多恶意的操作,以节省几个字节。 https://codegolf.stackexchange.com/questions/54/tips-for-golfing-in-python

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

一般来说,这可能意味着什么 。 它已经解释了这是什么意思,如果x是一个listnumpy.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]) 

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