逻辑判断

一般的逻辑判断

一般的逻辑判断,主要是 等于不等于大于小于大于等于小于等于in 这些。具体的参考下面的代码:

>>> 5 >= 5.0
True
>>> 5 <= 3
False
>>> 1 > 2
False
>>> 1 < 2
True
>>> 1 == 1.0
True
>>> 1 != 2
True
>>> 1 == 1.0 == 1.0*1
True
>>> 1 != 5 != 6
True
>>> 1 == 1.0 != 6
True
>>> 1 in ['1', 2, 3]
False

使用 if、elif、else

逻辑判断,通常是联动的。在 Python 中,一般会使用到 ifelifelse 这样的语法。
可以只有一个 if,可以 if + else,可以 if + 一个 elif + else,也可以 if + 很多个 if + else,这个视具体情况。但要注意,当代码缩进处于同一级的,意味着这些条件是一体的,比如下面代码中,a=13,它 > 10> 5,但是程序逐行执行下来,在遇到 > 10 的时候,就满足了条件,就会退出这一块的逻辑了。

a = 13
# 下面所有代码是一个整体
if a > 20:
    print('a > 20')
elif a > 10:
    print('a > 10')
elif a > 5:
    print('a > 5')
else:
    print('a <= 5')

if True

在代码中, 如果这样,那么... 或者 如果不这样,那么,是很常见的逻辑。True/False 作为 bool 类型,天生用于这种场景下的判断。而 Python 中,对条件的判断容忍度很高,参考代码:

>>> if '': print ('yes')
...  # 没有输出 yes
>>> if '?': print ('yes')
...
yes
>>> if 123: print ('yes')
...
yes
>>> if 0: print ('yes')
...
>>> if []: print ('yes')
...
>>> if [1]: print ('yes')
...
yes
>>> if None: print ('yes')
...
>>>

if 面前,空字符、0、空列表、None,相当于 False,非空字符、非 0 数、非空列表,相当于 True,一般其它数据对象,也会视为 True。本质上,相当于 bool(xxx) 先运行了一次,获得最终的 True/False。
由于 if 有这么大的包容度,有时候我们需要对当前的值进行更精准的判断,比如 if value is None 这样可以确保只有 None 的时候才能继续运行。
加上之前讲到 float 类型的精度问题,参考下面的代码:

>>> True == 1 == 1.00000000000000000001
True
>>> True is 1
False

is 固然一个更精准的判断逻辑,但并不适宜扩大应用,比如写成 6 is 6 获得 True 没有什么意义,而 6.0 is 6 获得 False,又很可能并不是自己需要的结果。而像上面 True == 1 这样的结果记住就好,具体写代码中知道规避这种现象就可以了。
注:True == 1 其实是因为 bool 是 int 的子类,对于 int 的 1 而言,True 也是另外一种形式的 1,而 False 则是 0。

and 与 or

记不记得在 《FirstWeb》开篇中说的 技术逻辑?里面就介绍了 or 的思路。
and 与 or,并不会特意返回 True/False 这个布尔值。
and 返回的是 第一个能匹配为『否』 的元素, or返回的是 第一个匹配为 『是』 的元素,如果都未匹配,就返回最后一个元素。听起来比较拗口,也不用去管它,如果你原来想当然认为 and 与 or 会返回 True/False,那就更新下概念,比对的时候,替换为临近的元素就好了。
当然,一般情况下,and 与 or 使用场景中,也不用在意其最后返回什么,当做普通的 True/False 来对待,问题也不大。

and 与 or 的参考代码:

>>> 5 and 6 and 0
0
>>> 5 or 6 or 0
5

andor 会有 拦截 的效果,如果它认为自己需要返回 (值)了就会有这个现象。为了说明这个拦截效果,我们扩展了下面的一个示例代码,简单的来说, a = 0 or call_function() 时,后面的这个 call_function 并不一定会执行。

参考代码:

def func(name=''):
    print('function is running for %s' % name)
    return None

print('- '*10 + ' or' + ' - '*10)
1 or func(1)
0 or func(0)

print('\n'*2)
print('- '*10 + ' and' + ' - '*10)

1 and func(1)
0 and func(0)

print('\n'*2)
print('- '*10 + ' and & or' + ' - '*10)
1 and 0 and func(1)
- - - - - - - - - -  or -  -  -  -  -  -  -  -  -  - 
function is running for 0

- - - - - - - - - -  and -  -  -  -  -  -  -  -  -  - 
function is running for 1

- - - - - - - - - -  and & or -  -  -  -  -  -  -  -  -  - 

注意: or 与 and 连用时,是存在优先级的,and 的优先级高于 or,如果不处理好优先级,可能某个逻辑就被拦截了。但是,代码有时自己也要看晕的,把 or/and 对应的条件直接 () 包裹起来! 那就不用太在乎什么优先级了,代码清晰代码好看 更重要!

并不绝对的 Magic Method

我们要扩展下上文的 if True 内容,因为它并不绝对,在 Magic Methods 中,有一个属性叫 __nonzero__ ( Python 3 中为 __bool__),如果重写了这个 method,那么对当前数据对象进行 bool 化的过程则完全由你自己控制。
可以尝试运行下面代码,看结果如何,是否符合自己的预期?

class FakeInt(int):
    def __nonzero__(self): # for Python2
        return False
    def __bool__(self):  # for Python3
        return False

number = int(10)
fake_number = FakeInt(10)

if number:
    print('number works')
else:
    print('number does not work')


if fake_number:
    print('fake_number does not works')
else:
    print('fake_number works')

此处介绍了 Magic Methods,也深知有可能会导致,我们在学习基础时,产生分裂感:明明已经接受你说的技术逻辑了,然后一转身,又说刚才的话也不全对……
当然,也不是为了避免未来被指摘『传授了不正确的概念』,而尽可能全面地把一件事情说清楚。全面,有时是有很大的负面价值。
明知山有虎,偏向虎山行。
原因,其实简单: 在这么多年 Python 亲身实践的过程中,这些 Magic Methods 在具体场景中,是非常有用的;如果你不知道它们的存在,并不是说会陷入什么概念性的陷阱,而是会导致,我们从一开始,就缺失了解决问题的一个重要工具。