带有“== True”和“为真”的表达式会产生不同的结果

问题描述 投票:6回答:5

我有以下MCVE

#!/usr/bin/env python3                                           

import pandas as pd

df = pd.DataFrame([True, False, True])

print("Whole DataFrame:")
print(df)

print("\nFiltered DataFrame:")
print(df[df[0] == True])

输出如下,我期望:

Whole DataFrame:
     0
  0  True
  1  False
  2  True

Filtered DataFrame:
     0
  0  True
  2  True

好吧,但PEP8风格似乎是错误的,它说:E712与True的比较应该是if cond is Trueif cond。所以我把它更改为is True而不是== True,但现在它失败了,输出是:

Whole DataFrame:
    0
0   True
1  False
2   True

Filtered DataFrame:
0     True
1    False
2     True
Name: 0, dtype: bool

到底是怎么回事?

python pandas pep8
5个回答
2
投票

这里的问题是在df[df[0] == True],你没有比较对象与True

正如其他答案所说,==pandas超负荷生产一个Series而不是像往常那样的bool[]也被重载,以解释Series并给出过滤结果。代码基本上等同于:

series = df[0].__eq__(True)
df.__getitem__(series)

所以,你不要在这里留下==来违反PEP8。


从本质上讲,pandas给出了熟悉的语法异常语义 - 这就是引起混淆的原因。

Accoring to Stroustroup(sec.3.3.3),运算符重载自从它的发明以来一直引起麻烦(他必须仔细思考是否将它包含在C ++中)。加斯克斯沃斯,高斯林在Java中跑向另一个极端,完全禁止它,事实证明这是一个极端。

总而言之,现代语言和代码往往会使运算符重载,但要密切注意不要过度使用它,并保持语义保持一致。


5
投票

在python中,Seeing even more abuse of it in C++测试一个对象是否与另一个对象相同。 is==定义为元素方式,pandas.Series不是。

因此,is比较df[0] is Truedf[0]是否是同一个对象。结果是True,反过来等于False,所以你在做0时得到0


2
投票

这是对MaxNoe答案的详细说明,因为这篇文章很长,可以包含在评论中。

正如他所指出的那样,df[df[0] is True]评估为df[0] is True,然后被强制为False,它对应于一个列名。有趣的是,如果你跑了

0

这开始有点令人困惑(至少对我而言),但与>>>df = pd.DataFrame([True, False, True]) >>>df[False] KeyError Traceback (most recent call last) <ipython-input-21-62b48754461f> in <module>() ----> 1 df[False] >>>df[0] 0 True 1 False 2 True Name: 0, dtype: bool >>>df[False] 0 True 1 False 2 True Name: 0, dtype: bool 如何利用缓存有关。如果你看看如何解决pandas,它看起来像

df[False]

由于 /home/matthew/anaconda/lib/python2.7/site-packages/pandas/core/frame.py(1975)__getitem__() -> return self._getitem_column(key) /home/matthew/anaconda/lib/python2.7/site-packages/pandas/core/frame.py(1999)_getitem_column() -> return self._get_item_cache(key) > /home/matthew/anaconda/lib/python2.7/site-packages/pandas/core/generic.py(1343)_get_item_cache() -> res = cache.get(item) 只是一个普通的python cache,在运行dict后,df[0]看起来像

cache

因此,当我们查找>>>cache {0: 0 True 1 False 2 True Name: 0, dtype: bool} 时,python将此强制转换为False。如果我们还没有使用0启动缓存,那么df[0]res,它在generic.py的第1345行触发None

KeyError

1
投票

我认为在def _get_item_cache(self, item): 1341 """Return the cached item, item represents a label indexer.""" 1342 cache = self._item_cache 1343 -> res = cache.get(item) 1344 if res is None: 1345 values = self._data.get(item) 比较只适用于pandas,结果是==。随着boolean Series输出是is。有关更多信息False

is

0
投票

一个解决方法是没有来自linters的投诉,但仍然有合理的子设置语法可能是:

print df[0] == True
0     True
1    False
2     True
Name: 0, dtype: bool

print df[df[0]]
      0
0  True
2  True

print df[df[0] == True]
      0
0  True
2  True

print df[0] is True
False

print df[df[0] is True]
0     True
1    False
2     True
Name: 0, dtype: bool

两者也需要同一时间。

此外,对于数据帧,可以使用s = pd.Series([True] * 10 + [False]) s.loc[s == True] # bad comparison in Python's eyes s.loc[s.isin([True])] # valid comparison, not as ugly as s.__eq__(True)

query
© www.soinside.com 2019 - 2024. All rights reserved.