05、Python 教程 - 条件、循环及其他语句

再谈print和import

print现在实际上是一个函数

1,打印多个参数

逗号分隔,打印多个表达式
sep自定义分隔符,默认空格
end自定义结束字符串,默认换行

print("beyond",'yanyu',23)#结果为:beyond yanyu 23

a = "beyond,"
b = "yanyu"
c = 23
print(a, b, c)#结果为:beyond, yanyu 23
print(a, b + ',' ,c)#结果为:beyond, yanyu, 23

print("I","love","the","beyond","band",sep="_")#结果为:I_love_the_beyond_band
print('Hello,', end='')结果为:Hello,   不会换行

2,导入时重命名as

导入整个模块并给它指定别名

import math as beyond
beyond.sqrt(4)#结果为:2.0

导入特定函数并给它指定别名

from math import sqrt as beyond
beyond(4)#结果为:2.0

赋值魔法

1,序列解包

序列解包(或可迭代对象解包):将一个序列(或任何可迭代对象)解包,并将得到的值存储到一系列变量中

#可同时(并行)给多个变量赋值
x, y, z = 1, 2, 3
print(x,y,z,sep="-")#结果为:1-2-3

#交换多个变量的值
x, y = y, x
print(x,y,z,sep=",")#结果为:2,1,3

beyond = 1,2,3
beyond#结果为:(1, 2, 3)
x,y,z = beyond
x#结果为:1
y#结果为:2
z#结果为:3

假设要从字典中随便获取(或删除)一个键-值对,可使用方法popitem,随便获取一个键-值对并以元组的方式返回,接下来,可直接将返回的元组解包到两个变量中

beyond ={
   
     "name":"huangjiaju","age":31}
key,value = beyond.popitem()
key#结果为:name
value#结果为:huangjiaju

左右两边列出的目标个数必须相同,否则会报异常
可使用星号运算符(*)来收集多余的值,这样无需确保值和变量的个数相同
带星号的变量最终包含的总是一个列表

x, y, z = 1, 2#结果为:报错
x, y, z = 1, 2, 3, 4#结果为:报错

a, b, *c= [1, 2, 3, 4]
c#结果为:[3, 4]
a, b, c#结果为:(1, 2, [3, 4])

name = "I like the beyond band"
x, *y, z = name.split()
x#结果为:'I'
y#结果为:['like', 'the', 'beyond']
z#结果为:'band'

2,链式赋值

将多个变量关联到同一个值

x = y = beyond()

等价于
y = beyond() 
x = y

不等价!!!
x = beyond() 
y = beyond()

3,增强赋值

将右边表达式中的运算符移到赋值运算符的前面

x = 2
x += 1
x#结果为:3
x *= 2
x#结果为:6

yy = "beyond"
yy += "huangjiaju"
yy#结果为:'beyondhuangjiaju'
yy *= 2
yy#结果为:'beyondhuangjiajubeyondhuangjiaju'

代码块:缩进的乐趣

代码块其实并不是一种语句,代码块是一组语句,代码块是通过缩进代码(即在前面加空格)来创建的
在Python中,使用冒号(:)指出接下来是一个代码块

条件和条件语句

1,布尔值

假(0):False None 0 "" () [] {},其他则为真(1)
虽然[]""都为假,但它们并不相等(即[] != ""
布尔值True和False属于类型bool
于任何值都可用作布尔值

True + False + 42#结果为:43   1+0+42=43
bool(42)#结果为:True
bool('')#结果为:False
bool(0)#结果为:False

2,有条件的执行和if语句

如果条件(if和冒号之间的表达式)为前面定义的真,就执行后续代码块(这里是一条print语句);如果条件为假,就不执行

name = input('What is your name? ') 
if name.endswith('beyond'):以beyond结尾的名字为真
	print('Hello, Mr. beyond')

name = input('What is your name?') 
if name.endswith('yanyu'):以yanyu结尾的名字为真
	print('Hello, Mr. yanyu') 
else: 
	print('Hello, stranger')

3,else子句

条件表达式——C语言中三目运算符的Python版本
"语句1" if 条件 else "语句2"如果条件为真,则执行语句1,否则执行语句2

name = input('What is your name?') 
status = "friend" if name.endswith("beyond") else "stranger"

4,elif 子句

要检查多个条件,可使用elif,elif是else if的缩写

num = int(input('Enter a number: ')) 
if num > 0: 
	print('The number is positive') 
elif num < 0: 
	print('The number is negative') 
else: 
	print('The number is zero')

5,代码块嵌套

name = input('What is your name? ') 
if name.endswith('Gumby'):以Gumby结尾都为真
	if name.startswith('Mr.'):以Mr.开始都为真
		print('Hello, Mr. Gumby') 
	elif name.startswith('Mrs.'): 
		print('Hello, Mrs. Gumby') 
	else: 
		print('Hello, Gumby') 
else: 
	print('Hello, stranger')

6,更复杂的条件

1,比较运算符

在条件表达式中,最基本的运算符可能是比较运算符,它们用于执行比较

表达式 描述
x == y x等于y
x < y x小于y
x > y x大于y
x >= y x大于或等于y
x <= y x小于或等于y
x != y x不等于y
x is y x和y是同一个对象
x is not y x和y是不同的对象
x in y x是容器(如序列)y的成员
x not in y x不是容器(如序列)y的成员

1,相等运算符#

比较运算符,用两个等号(==)表示
一个等号是赋值运算符,用于修改值

"foo" == "foo"#结果为:True
"foo" == "bar"#结果为:False

"foo" = "foo"#报错

2,is:相同运算符#

'''
变量x和y指向同一个列表
而z指向另一个列表(其中包含的值以及这些值的排列顺序都与前一个列表相同)
'''
x = y = [1, 2, 3] 
z = [1, 2, 3] 
x == y结果为:True 
x == z结果为:True 
x is y结果为:True 
x is z结果为:False

==用来检查两个对象是否相等
is用来检查两个对象是否相同(是同一个对象)

3,in:成员资格运算符#

name = input('What is your name?') 
if 's' in name:
	print('Your name contains the letter "s".')
else: 
	print('Your name does not contain the letter "s".')

4,字符串和序列的比较#

根据字符的字母排列顺序进行比较的

"alpha" < "beta"#结果为:True

要获悉字母的顺序值,可使用函数ord
这个函数的作用与函数chr相反

ord("🐕")#结果为:128021
chr(128021)#结果为:🐕

可使用字符串方法lower对设计大写字母的字符串进行比较

"a".lower() < "B".lower()#结果为:True
'FnOrD'.lower() == 'Fnord'.lower()#结果为:True

[1, 2] < [2, 1]#结果为:True
[2, [1, 4]] < [2, [1, 5]]#结果为:True

2,布尔运算符

读取一个数,并检查这个数是否位于1~10(含)

number = int(input('Enter a number between 1 and 10: ')) 
if number <= 10 and number >= 1: 
	print('Great!') 
else: 
	print('Wrong!')

运算符and是一个布尔运算符,还有另外两个布尔运算符:or和not
布尔运算符有个有趣的特征:只做必要的计算

7,断言

使用关键字assert,要求某些条件得到满足
assert语句充当检查点

age = 10 
assert 0 < age < 100 

age = -1 
assert 0 < age < 100#结果为:报错!!!

还可在条件后面添加一个字符串,对断言做出说明
age = -1
assert 0 < age < 100, 'The age must be realistic'#结果为:AssertionError: The age must be realistic

循环

1,while 循环

打印1-100

x = 1 
while x <= 100: 
	print(x)  
	x += 1

name = '' 
while not name: 
	name = input('Please enter your name: ') 
print('Hello, {}!'.format(name))

2,for 循环

可迭代对象是可使用for循环进行遍历的对象

words = ['this', 'is', 'an', 'ex', 'parrot'] 
for word in words: 
	print(word)

numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 
for number in numbers: 
	print(number)

鉴于迭代(也就是遍历)特定范围内的数是一种常见的任务
函数range可实现迭代,左闭右开
如果只提供了一个位置,将把这个位置视为结束位置,并假定起始位置为0

range(0, 10)#结果为:range(0, 10)
list(range(0, 10))#结果为:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
range(10)#结果为:range(0, 10)

for number in range(1,101): 
	print(number)

3,迭代字典

通过key来遍历字典d
只对值感兴趣,可使用d.values
d.items以元组的方式返回键值对
for循环的优点之一是,可在其中使用序列解包

d = {
   
     'x': 1, 'y': 2, 'z': 3} 
for key in d: 
    print(key, 'corresponds to', d[key])
for key, value in d.items(): 
    print(key, 'corresponds to', value)
'''
结果为:
x corresponds to 1
y corresponds to 2
z corresponds to 3
x corresponds to 1
y corresponds to 2
z corresponds to 3
'''

4,一些迭代工具

并行迭代

names = ['anne', 'beth', 'george', 'damon'] 
ages = [12, 45, 32, 102]
for i in range(len(names)): 
	print(names[i], 'is', ages[i], 'years old')
	
'''
anne is 12 years old
beth is 45 years old
george is 32 years old
damon is 102 years old
'''	

1,并行迭代

内置函数zip,它将两个序列“缝合”起来,并返回一个由元组组成的序列
可使用list将其转换为列表

names = ['anne', 'beth', 'george', 'damon'] 
ages = [12, 45, 32, 102]

list(zip(names,ages))#结果为:[('anne', 12), ('beth', 45), ('george', 32), ('damon', 102)]

for name, age in zip(names, ages): 
    print(name, 'is', age, 'years old')
'''
结果为:
anne is 12 years old
beth is 45 years old
george is 32 years old
damon is 102 years old
'''

当序列的长度不同时,函数zip将在最短的序列用完后停止“缝合”

list(zip(range(5), range(1000)))#结果为:[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4)]

2,迭代时获取索引

替换一个字符串列表中所有包含子串’xxx’的字符串
使用内置函数enumerate

for index, string in enumerate(strings): 
	if 'xxx' in string: 
		strings[index] = '[censored]'

3,反向迭代和排序后再迭代

函数:reversed和sorted,类似于列表方法reverse和sort
不修改对象,而是返回反转和排序后的版本
sorted返回一个列表,而reversed像zip那样返回一个更神秘的可迭代对象

sorted([4, 3, 6, 8, 3])#结果为:[3, 3, 4, 6, 8]
sorted('Hello, beyond!')#结果为:[' ', '!', ',', 'H', 'b', 'd', 'e', 'e', 'l', 'l', 'n', 'o', 'o', 'y']
list(reversed('Hello, beyond!'))#结果为:['!', 'd', 'n', 'o', 'y', 'e', 'b', ' ', ',', 'o', 'l', 'l', 'e', 'H']
'Y'.join(reversed('Hello, beyond!'))#结果为:'!YdYnYoYyYeYbY Y,YoYlYlYeYH'
''.join(reversed('Hello, beyond!'))#结果为:'!dnoyeb ,olleH'

要按字母表排序,可先转换为小写

sorted("aBc", key=str.lower)#结果为:['a', 'B', 'c']

5,跳出循环

1,break

找出小于100的最大平方值

from math import sqrt 
for n in range(99, 0, -1): 
    root = sqrt(n) 
    if root == int(root): 
        print(n) 
        break
#结果为:81

2,continue

结束当前迭代,并跳到下一次迭代开头,即跳过循环体中余下的语句,但不结束循环

伪代码
for x in seq: 
	if condition1: continue
	if condition2: continue
		
	do_something() 
	do_something_else() 
	do_another_thing() 
	etc()

3,while True/break成例

在用户根据提示输入单词时执行某种操作,并在用户没有提供单词时结束循环

while True: 
	word = input('Please enter a word: ') 
	if not word: break 
	print('The word was ', word)

6,循环中的 else 子句

from math import sqrt 
for n in range(99, 81, -1): 
	root = sqrt(n) 
	if root == int(root): 
		print(n) 
		break 
	else: 
		print("Didn't find it!")

简单推导

列表推导是一种从其他列表创建列表的方式,工作原理类似于for循环

[x * x for x in range(10)]#结果为:[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

[x*x for x in range(10) if x % 3 == 0]#结果为:[0, 9, 36, 81]

[(x, y) for x in range(3) for y in range(3)]#结果为:[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
#与下列for循环效果等价
result = [] 
for x in range(3):
    for y in range(3):
        result.append((x, y))
#结果为:[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]

b在boys列表中,g在girls列表中,若俩名字首字母相等则配对

girls = ['alice', 'bernice', 'clarice'] 
boys = ['chris', 'arnold', 'bob'] 
[b+'+'+g for b in boys for g in girls if b[0] == g[0]]#结果为:['chris+clarice', 'arnold+alice', 'bob+bernice']

使用圆括号代替方括号并不能实现元组推导,而是将创建生成器
可使用花括号来执行字典推导

squares = {
   
     i:"{} squared is {}".format(i, i**2) for i in range(10)}
squares[8]#结果为:'8 squared is 64'

在列表推导中,for前面只有一个表达式
在字典推导中,for前面有两个用冒号分隔的表达式,分别为键及其对应的值

三人行

pass、del和exec

1,pass:什么都不做

name = input('your name input,please:')
if name == 'beyond': 
    print('Welcome!') 
elif name == 'huangjiaju': 
    pass
elif name == 'yanyu': 
    print('Game Over')
else:
    print("Goodbuy")

2,使用del删除

robin和scoundrel指向同一个字典,因此将None赋给scoundrel后,依然可以通过robin
来访问这个字典
但将robin也设置为None之后,Python解释器直接将其删除,这被称为垃圾收集

scoundrel = {
   
     'age': 42, 'first name': 'Robin', 'last name': 'of Locksley'} 
robin = scoundrel 
print(scoundrel){'age': 42, 'first name': 'Robin', 'last name': 'of Locksley'} 
print(robin){'age': 42, 'first name': 'Robin', 'last name': 'of Locksley'} 
scoundrel = None 
print(robin){'age': 42, 'first name': 'Robin', 'last name': 'of Locksley'} 
robin = None
print(robin)#结果为:None

x= 1
del x
x#结果为:报错  del不仅会删除到对象的引用,还会删除名称本身

x和y指向同一个列表,但删除x对y没有任何影响
只删除名称x,而没有删除列表本身(值)
在Python中,根本就没有办法删除值
对于你不再使用的值,Python解释器会立即将其删除

x = ['beyond',"yanyu"]
y = x
y[1] = 'huangjiaju'
print(x)#结果为:['beyond', 'huangjiaju']
del x
print(y)#结果为:['beyond', 'huangjiaju']

3,使用exec和eval执行字符串及计算其结果

1,exec

函数exec将字符串作为代码执行,执行一系列python语句,exec本身是条语句,什么都不返回

exec("print('Hello, world!')")#结果为:Hello, world!

函数exec主要用于动态地创建代码字符串
调用函数exec时只给它提供一个参数绝非好事。
在大多数情况下,还应向它传递一个命名空间——用于放置变量的地方(命名空间视为放置变量的地方,类似于一个看不见的字典)
否则代码将污染你的命名空间,即修改你的变量
将scope打印出来,发现其中包含所有内置函数和值的字典__builtins__。

from math import sqrt
exec("sqrt = 1")
sqrt(4)#结果为:报错,改变了该变量

from math import sqrt
scope = {
   
     }
exec("sqrt = 1",scope)
sqrt(4)#结果为:2.0
scope['sqrt']#结果为:1

len(scope)#结果为:2
scope.keys()#结果为:['sqrt', '__builtins__']

2,eval

eval计算用字符串表示的Python表达式的值,并返回结果
也可向eval提供一个命名空间
类似Python计算器

eval(input("please input some number: "))
#please input some number:1+2+3
#结果为:6

向exec或eval提供命名空间时,可在使用这个命名空间前在其中添加一些值

scope = {
   
     }
scope['x'] = 2
scope['y'] = 3
eval('x * y', scope)#结果为:6

同一个命名空间可用于多次调用exec或eval

scope = {
   
     }
exec('x = 2', scope) 
eval('x * x', scope)#结果为:4

本章节介绍的新函数

函数 描述
chr(n) 返回一个字符串,其中只包含一个字符,这个字符对应于传入的顺序值n(0 ≤ n < 256)
eval(source[,globals[,locals]]) 计算并返回字符串表示的表达式的结果
exec(source[, globals[, locals]]) 将字符串作为语句执行
enumerate(seq) 生成可迭代的索引值对
ord© 接受一个只包含一个字符的字符串,并返回这个字符的顺序值(一个整数)
range([start,] stop[, step]) 创建一个由整数组成的列表
reversed(seq) 按相反的顺序返回seq中的值,以便用于迭代
sorted(seq[,cmp][,key][,reverse]) 返回一个列表,其中包含seq中的所有值且这些值是经过排序的
xrange([start,] stop[, step]) 创建一个用于迭代的xrange对象
zip(seq1, seq2,…) 创建一个适合用于并行迭代的新序列