在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]
被改变了。
为什么会这样呢?
比较规则是:
-
当您订购两个string或两个数字types时,按照预期的方式进行sorting(string的字典sorting,整数的数字sorting)。
-
当您订购一个数字和一个非数字types时,数字types首先。
-
当您订购两个不兼容的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
,则如果y
是int
eger,则比较x < y
是False
。 这是因为将一个列表与一个整数进行比较是没有意义的。 但是,在Python 2中,如果操作数不具有可比性,则比较将基于CPython中按types名称的字母顺序排列 ; 另外所有的数字在混合型比较中都是第一位的 。 这甚至没有在CPython 2的文档中详细说明,不同的Python 2实现可能会给出不同的结果。 即[1, 2, 3, 4, 5] < 2
计算结果为False
因为2
是一个数字,因此比CPython中的list
“小”。 这个混合的比较最终被认为是一个太模糊的function ,并在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
所以基本上,你要采取元素0或1取决于比较是真是假。
如果您在Python 3中尝试使用上面的代码,则会由于Python 3.0中的更改而得到TypeError: unorderable types: list() < int()
订购比较
Python 3.0简化了sorting比较的规则:
当操作数没有有意义的自然sorting时,sorting比较运算符(
<
,<=
,>=
,>
)会引发TypeError
exception。 因此,1 < ''
,0 > None
或len <= 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
评估为True
或False
。
(a, b)
是一个元组。
在一个元组上索引的工作就像索引在列表上: (3,5)[1]
== 5
。
True
等于1
, False
等于0
。
-
(a,b)[c<d]
-
(a,b)[True]
-
(a,b)[1]
-
b
或者False
:
-
(a,b)[c<d]
-
(a,b)[False]
-
(a,b)[0]
-
a
在堆栈交换networking上有一个很好的列表,你可以对python进行很多恶意的操作,以节省几个字节。 https://codegolf.stackexchange.com/questions/54/tips-for-golfing-in-python
虽然在正常的代码中不应该使用,在你的情况下,这意味着x
既可以作为一个可以比较一个整数和作为一个容器,支持切片,这是一个非常不寻常的组合。 正如其他人所指出的,这可能是Numpy代码。
一般来说,这可能意味着什么 。 它已经解释了这是什么意思,如果x
是一个list
或numpy.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])
注意这只是一种可能性。 你可以自由地实现你想要的一切。