9.python的布尔类型与流程控制
布尔类型其实可以算是一种特殊的数字,下面是 help() 函数得到的帮助信息:
Help on class bool in module __builtin__: class bool(int) | bool(x) -> bool | | Returns True when the argument x is true, False otherwise. | The builtins True and False are the only two instances of the class bool. | The class bool is a subclass of the class int, and cannot be subclassed. | | Method resolution order: | bool | int | object | | Methods defined here: | | __and__(...) | x.__and__(y) <==> x&y | | __or__(...) | x.__or__(y) <==> x|y | | __rand__(...) | x.__rand__(y) <==> y&x | | __repr__(...) | x.__repr__() <==> repr(x) | | __ror__(...) | x.__ror__(y) <==> y|x | | __rxor__(...) | x.__rxor__(y) <==> y^x | | __str__(...) | x.__str__() <==> str(x) | | __xor__(...) | x.__xor__(y) <==> x^y | | ---------------------------------------------------------------------- | Data and other attributes defined here: | | __new__ = <built-in method __new__ of type object> | T.__new__(S, ...) -> a new object with type S, a subtype of T | | ---------------------------------------------------------------------- | Methods inherited from int: | | __abs__(...) | x.__abs__() <==> abs(x) | | __add__(...) | x.__add__(y) <==> x+y | | __cmp__(...) | x.__cmp__(y) <==> cmp(x,y) | | __coerce__(...) | x.__coerce__(y) <==> coerce(x, y) | | __div__(...) | x.__div__(y) <==> x/y | | __divmod__(...) | x.__divmod__(y) <==> divmod(x, y) | | __float__(...) | x.__float__() <==> float(x) | | __floordiv__(...) | x.__floordiv__(y) <==> x//y | | __format__(...) | | __getattribute__(...) | x.__getattribute__('name') <==> x.name | | __getnewargs__(...) | | __hash__(...) | x.__hash__() <==> hash(x) | | __hex__(...) | x.__hex__() <==> hex(x) | | __index__(...) | x[y:z] <==> x[y.__index__():z.__index__()] | | __int__(...) | x.__int__() <==> int(x) | | __invert__(...) | x.__invert__() <==> ~x | | __long__(...) | x.__long__() <==> long(x) | | __lshift__(...) | x.__lshift__(y) <==> x<<y | | __mod__(...) | x.__mod__(y) <==> x%y | | __mul__(...) | x.__mul__(y) <==> x*y | | __neg__(...) | x.__neg__() <==> -x | | __nonzero__(...) | x.__nonzero__() <==> x != 0 | | __oct__(...) | x.__oct__() <==> oct(x) | | __pos__(...) | x.__pos__() <==> +x | | __pow__(...) | x.__pow__(y[, z]) <==> pow(x, y[, z]) | | __radd__(...) | x.__radd__(y) <==> y+x | | __rdiv__(...) | x.__rdiv__(y) <==> y/x | | __rdivmod__(...) | x.__rdivmod__(y) <==> divmod(y, x) | | __rfloordiv__(...) | x.__rfloordiv__(y) <==> y//x | | __rlshift__(...) | x.__rlshift__(y) <==> y<<x | | __rmod__(...) | x.__rmod__(y) <==> y%x | | __rmul__(...) | x.__rmul__(y) <==> y*x | | __rpow__(...) | y.__rpow__(x[, z]) <==> pow(x, y[, z]) | | __rrshift__(...) | x.__rrshift__(y) <==> y>>x | | __rshift__(...) | x.__rshift__(y) <==> x>>y | | __rsub__(...) | x.__rsub__(y) <==> y-x | | __rtruediv__(...) | x.__rtruediv__(y) <==> y/x | | __sub__(...) | x.__sub__(y) <==> x-y | | __truediv__(...) | x.__truediv__(y) <==> x/y | | __trunc__(...) | Truncating an Integral returns itself. | | bit_length(...) | int.bit_length() -> int | | Number of bits necessary to represent self in binary. | >>> bin(37) | '0b100101' | >>> (37).bit_length() | 6 | | conjugate(...) | Returns self, the complex conjugate of any int. | | ---------------------------------------------------------------------- | Data descriptors inherited from int: | | denominator | the denominator of a rational number in lowest terms | | imag | the imaginary part of a complex number | | numerator | the numerator of a rational number in lowest terms | | real | the real part of a complex number
首先,请注意这一行:
其父类为 int 而且其内置方法也是一模一样,也就是说布尔类型也是可以和整型一样进行各种运算的,但一般没有人那么做。
布尔类型只有两个值: True 和 False ,或者说只返回两个值。
注意:python是严格区分大小写的,别写错了。
一般布尔值是用于流程控制的,下面我们来讲讲python中的流程控制是怎么样的。
但是,在这之前,我们要先了解python的缩进和编程风格。
首先,python代码的执行是从上往下逐一解释的,而如果大家开头都是对齐的话:
大家都是同级的,就会逐条执行,这个例子还说明了什么叫逐条执行,当我执行的 print d 时,d的赋值操作却在后面,所以进行打印操作的时候,没找到这个变量的值,所以抛出了给变量没定义的错误。
而我们要进行流程控制的操作的时候,我们希望的效果是这样的:
a = 1
if a == 1: #如果a的值等于1的话,注意赋值运算符和比较运算符号的差别 print a #我就打印出a的值
假设这里没有语法问题,python从第一句开始执行,当判断完 if 之后,又换行继续执行。
本来我们是想让 if 来控制 print 执行的,但 print 表示不服,大家都是同一级的,你 if 凭什么管我?
当然,这种写法是一种语法错误。
所以,我们可以认为缩进是python控制优先级的,它规定了代码间的管辖问题。(这是我自己总结的)
但是,当我们学到函数,学到类的写法的时候,发现其也是要进行缩进的,而函数中又有一个作用域的问题(到时候详细讲),在函数作用域中又有一个现象,函数内外的变量是不能互相访问的(当然也有强制的方法),此时有人就会搞混了,是不是我这里流程控制使用缩进分了内外分层后,内层的变量在外层也是不能访问的?
不是,下面是实例:
a = 1 if a == 1: b = 1 else: b = 0 print b
是可以访问的,注意作用域是函数的东西,不要混到流程控制里面起来,为了方便大家了解,我画了下面这幅图:
是这为了方便大家了解才画的图,具体python内部是不是这样处理的我也不知道。
在缩进的时候可以使用制表符(tab键)和空格,官方推荐是4个空格,但这两种缩进方式是不能混用的。
但是,如果我们使用IDE编程(部分,pycharm中是这样)的话,当我们按下 tab 键的时候,IDE会输入若干个空格(默认个数也因IDE不同而不同),也就是我们认为我们输入的是 tab 键的制表符,其实输入的是空格,这点要注意。
关于python中的编程风格可以总结为:
Python 使用硬回车来分割语句(一句一行,一行写不下用 \ 换行),使用冒号(:)和缩进来分割代码块。同一层次的语句必须有相同的缩进(每一组这样的语句称为一个块),而C语言风格的编程语言(Java/C#/C++)则使用分号来分割语句,花括号来分割代码块。
1.if 语句
python中使用 if...elif...else... 来实现条件判断:
a = 1 if a == 1: b = 1 elif a == 2: b = 2 elif a == 3: b = 3 else: b = 0 print b
python会从上到下进行判断,如何条件为真,即布尔值为 True ,其内层的代码才会被执行。
这里比较运算符返回了布尔值,但是如果条件不是布尔值或者没有返回布尔值要怎么判断。
其实,当我们用某个作为判断条件是,其实已经隐性地声明要使用 bool() 函数将条件强制转换为布尔值了。
我们可以将不是bool类型的数据强制转换成bool值。那究竟它们之间的转换关系是什么呢?
下面是一些关于布尔值为假的总结:
1.数字0(0.0等浮点型也是)
2.空的数据(包括空的字符串,空元祖,空列表,空字典,空集合等)
3.None(空的对象)
除了上面为假之外,其他均为真。
注意,虽说在将布尔值强行转换成数字的时候:
True转换成 1,但并不是说只有数字中只有 1 为真,只要不为0的数字都是真。
讲完布尔值的问题是时候分析语法了,首先,语法和核心就是使用关键字判断其布尔值是否为真,若为真,则执行内层的代码。
if 和 elif 里面都可以放条件,而 else 则表示如果上面的条件都不为真,则执行这里面的。
但要注意几个问题,一个判断组有且至少有一个 if ,可以有0个或多个 elif ,0个或1个else。(判断组也是我总结的东西,我也不知道python中有没有关于判断组的定义)
a = 1 b = 0 if a == 0: b = 1 if a == 1: c = 1 else: b = 3 print b print c
即为第一组的 if 判断失败后,不能去执行第二组判断的 else。
另外,还有这种情况:
有两个条件是一样的,这种情况会怎么样,我们先看看结果:
很明显只有第一个为真的有效果了,所以我们可以得出以下结论:
一个判断组里面,一旦条件为真,这个判断组内剩下的判断就不继续进行了,当然我相信应该没有会写两个一样的条件吧。
三元运算
在讲完if语句之后,我们就可以学习三元运算了。
何为三元运算,这个名字看起来很高端,但其实是为了满足:我要为一个变量赋值,当满足一个条件时,这个变量的值应该是123,不满足的话值为456。
a = ??? if a == 1: b = 1 eles: b = 2
但这样写还是太烦,有没有简单点的写法?
有,我们可以使用三元运算:
b = 1 if a==1 else 2
总结起来就是:
b = 值1 if 条件 else 值2
这就是三元运算,就是这么简单,so easy。 说白了就是一种高级的赋值方式,就算不用三元运算,用原始的写法也是可以的。
2. while循环
本来while循环应该放到循环里面讲的,但是while循环和bool值的关系比较密切,就在这里一并讲了。
首先 while 循环的意思是,当给定的条件为真的时候,就会对其内层的代码循环执行,从内层第一句执行到最后一句。执行完以后又回到while中继续判断条件,若还是为真,则继续执行,如此往复,直到条件为假。
a = 1 while a <= 5: a += 1 print a print '----',a
注意,最后一句 print '----',a 不在while的内层,不受while的控制,只要while执行完了,就一定会执行它。
这个时候,有同学要问,如果我给的条件永远为真, while True: 那会怎么样?
那么,这时候要恭喜你,你进入了传说中的死循环,这个循环永远执行不完了,其后面的代码也不会执行了,这个时候连退出都要用 ctrl+c 强制退出了。
正是因为while循环这么危险,所以有两个关键字可以用来跳过循环 :
continue 跳过本次循环
break 跳出整个while循环,当然有多个 while 嵌套时,只跳出当前这层
那么什么叫本次,什么叫整个,什么叫当前这层呢?
假如,有一天你在街上摆摊,生意很好,人们都排队来买,这个人买完就下一个。但是,此时你看到一个人长得奇丑无比,你不想卖给他,没办法,有钱任性呗。这是你大喊一声:东西不卖你,下一个继续(continue),这就是跳过本次循环,遇到这句时,下面的代码不继续执行了,继续回到循环的第一句执行。当然那个被你拒卖的人后来会不会找人揍你,这就不在考虑范围了。这个时候,又来个一个客人,你定睛一看,我去,城管!赶紧跑!这个时候你摆摊的行为就结束了,也就是 while 循环结束了,就算你的指定条件是到下午5点收摊的也没办法,这就是 break。但虽然摆摊结束了,但你还得继续生活呀,生活也是一个循环,不能因为一个城管就结束掉整个生活的循环呀,这就是只结束当前这层循环。
a = 1 while a <= 10: a += 1if a == 5: continue if a == 8: break
print a
另外,while循环也可以和 if 一样使用 else。
a = 0 while a<= 5: print a a+=1 else: print '条件为假了'
不过一般很少这样用了,因为while循环条件为假是会自动跳出循环,此时会自动执行下面的同级代码,所以直接写在while的下面的同级处就可以了。
但是,这样写能够提供代码的可读性,具体如何选择看个人需要。
剩下的 for 循环会在后面另起一篇说明。
关于布尔值和流程控制暂时就是这些,后续有需求的话,我会进行补充说明。