由于python语言的简洁性,在判断一个容器是否为空的时候,比如列表,可以直接用if + 要判断的东西:
a = list()
if a:
print('不为空')
else:
print('列表为空')
如果是空会返回false,在有值的时候会返回true。
这是因为列表加在 if 后面构成判断语句时,python是能判断要做什么,针对空列表,以及列表本身为none都hi返回false。
而如果是dataframe的话,就会报错了:
def get_df(df=None):
res = df if df else pd.DataFrame()
print(res)
get_df(df)
看到这个报错有点蒙,分析下,我这里是把df作为一个参数传进来,而我想要的逻辑是如果df传入就采用传入的值,没有传的话就新建(这里只是为了说明问题)。但是这样写会报错,从报错信息来看,也就是python认为它不清楚我想要让它判断什么,它不清楚什么是我想要的真,什么是假。
根据它的提示,如果我要判断这个数据框是否是一个空的数据框,我应该用empty,判断布尔值,应该用bool。。。等等。所以这里应该明确告诉python我的意图,我只是想知道有没有这个参数。所以进行以下改造:
def get_df(df=None):
res = df if df is not None else pd.DataFrame()
print(res)
get_df(df)
明确指定要判断的事情就可以了。从这里我也发现,数据框和传统的容器是有一些不同的,套用传统的操作时,还是要多加注意。
后续研究结果:
python的if是在调用内置方法 __bool__(),并且优先使用它,如果没有布尔方法则去找 __len__()方法。
举个例子:
自定义一个类,定义__bool__方法和__len__方法。
实例化该类,并直接进行 if 判断该实例,它调用的实际是bool方法,结果为bool方法的返回值,false。
注释掉 bool 方法,可以看到它调用的是 len 方法,len 返回为1,只有0 为false,其他都是true,所以返回true。
由此可以得知,如果想让 if 逻辑判断自己定义的逻辑,需要定义bool方法,某种情况下 len也可以。
上述报错是因为dataframe继承自ndframe,而ndframe重写了__bool__()方法,将其指向为自定义方法:
__nonzero__()。
__bool__ = __nonzero__
在这个自定义方法里,什么都没有做,只是抛了一个异常:
def __nonzero__(self):
raise ValueError(
"The truth value of a {0} is ambiguous. "
"Use a.empty, a.bool(), a.item(), a.any() or a.all().".format(
self.__class__.__name__
)
)
目的,应该是为了避免直接使用 if df的写法。