[Python]第五章 条件、循环以及其他语句

5.1再谈print和import

5.1.1打印多个参数

用逗号隔开,适用于简单合并文本的情况(不需要用format设置文本格式)

>>>name ='Gumby'
>>>salutation ='Mr.'
>>>greeting ='Hello,'
>>>print(greeting,salutation,name)
Hello, Mr. Gumby  #自动添加空格
>>>print('{greeting}{salutation}{name}'.format(name ='Gumby',salutation ='Mr.', greeting ='Hello,'))
Hello,Mr.Gumby

Notice:print方法直接打印出来的字符串中间都有个空格
用加号连接字符串,则打印出来没有空格

>>>name ='Gumby'
>>>salutation ='Mr.'
>>>greeting ='Hello,'
>>>print(greeting+salutation+name)
Hello,Mr.Gumby   #没有空格

也可以用sep参数指定间隔代替空格

>>>print('I','love','you',sep='*')
I*love*you

自定义结束字符串替换默认的换行符

>>>print('My name is',end=':')
>>>print('jack')
My name is:jack

5.1.2导入时重命名

确定要导入模块中的一切时:
使用 import somemodule 或者from somemodule import *
只需要导入模块中的某个或者某几个函数时:
from somemodule import somefunction,anotherfunction
当导入的多个模块含有相同名称的函数时,可以这样调用:
module1. function…)
module2. function (…)
或者指定别名
from module1 import function as function1
from module2 import function as function2
Notice:可以给模块指定别名,也可以给函数指定别名

>>> import math as foobar
>>> foobar.sqrt(4)
2.0
>>> from math import sqrt as foobar
>>> foobar(4)
2.0

5.2赋值魔法
5.2.1序列解包
同时给多个变量赋值

>>> x, y, z = 1, 2, 3
>>> print(x, y, z)
1 2 3

交换变量值:

>>> x, y = y, x
>>> print(x, y, z)
2 1 3

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

>>> values = 1, 2, 3 #这时的values是一个元组
>>> x, y, z = values
>>> x
1

适用于返回元组的函数或方法

>>> d = {'name': 'Gumby', 'age': 42, 'sex': 'male'}
>>>  #d.popitem() 原本popitem方法以元组形式返回被删除的键值对
#('sex', 'male')
>>> key,value=d.popitem()
>>> key
'sex'
>>> value
'male'

要解包的序列包含的元素个数需要等于相等数量的变量去接收

>>>x,y=1,2,3
报错

可以用变量名前*接收剩余所有的元素

>>>x,y,*r=[1,2,3,4,5]
>>>r
[3, 4, 5]  

r是一个列表,即使被解包的序列是一个元组或者字符串

>>>x,y,*r='abcde'
>>>r
['c', 'd', 'e']

*变量放中间默认接收两端以外的所有元素

>>>a,*who,c='Jack and his friends are brave'.split()
>>>who
['and', 'his', 'friends', 'are']

5.2.2链式赋值

将多个变量关联到同一个值的快捷方式,类似并行赋值
x = y = somefunction()
等价于
y = somefunction()
x = y
不等价
x = somefunction()
y = somefunction()

5.2.3增强赋值

将运算符移到赋值符前面
x=x+1可以写成x+=1 这里+也可以换成-、*、/、%

>>>x=1
>>>x*=2
>>>x
2

增强赋值也适用于其他可适用双目运算符的数据类型

>>>x='ab'
>>>x+='cd'
>>>x*=2
>>>x
'abcdabcd'

5.3代码块:缩进的乐趣

代码块是一组语句,可在满足条件时执行(if语句),可多次循环等,其通过缩进格式创建。
在Python中,使用冒号(:)指出接下来是一个代码块,并将该代码块中的每行代码都缩进相同的程度。

5.4条件和条件语句

5.4.1布尔值(真值)

解释器视为假的情况:
False None 0 “” () [ ] { }
布尔值True和False的类型是bool,可以和list\str\tuple类一样转化其他值

>>> bool('I think, therefore I am')
True
>>> bool(42)
True
>>> bool('')
False
>>> bool(0)
False

5.4.2有条件地执行和if语句

条件为真时,执行冒号后面的代码块

name=input('What is your name?\n')
if name.endswith('chen'):
	print('Hello,Mr chen')

5.4.3 else子句

else是if语句的一部分,当条件为假时执行

name=input('What is your name?\n')
if name.endswith('chen'):
	print('Hello,Mr chen')
else:
	print('get out!stranger!')

条件表达式(三目运算符):A if True else B

name=input('What is your name?\n')
identity='friend' if name.endswith('chen') else 'stanger'
print(identity)

5.4.4 elif子句

elif子句也是if语句的一部分,是else if的缩写,当if条件不满足时,再对条件进行判断

name=input('What is your name?\n')
if name.endswith('chen'):
    print('Hello,Mr chen')
elif name.endswith('wang'):
    print('Welcome,Mr wang')
else:
	print('get out!stranger!')

5.4.5代码块嵌套

当满足第一个if时,又产生条件分支时,可以在代码块里构造子条件语句

name=input('What is your name?\n')
if name.endswith('chen'):
    if name.startswith('Mr'):
        print('Hello,Mr.chen')
    elif name.startswith('Mrs'):
        print('Hello,Mrs.chen')
    else:
        print('Hello,chen')
else:
	print('get out!stranger!')

5.4.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的成员

类似链式赋值,也支持链式比较

age=int(input('How old are you?'))
if 18<age<25:
	print('You are a teenager!')

(1) ==相等运算符
一个=是赋值,可修改原值, ==是相等

>>> "foo" == "foo"
True
>>> "foo" == "bar"
False

(2) is 相同运算符

>>>x=[1,2,3]
>>>y=[1,2,3]
>>>x==y
True
>>>x is y
False

虽然xy的值相等,但指向的是两个列表,不是同一个对象,因此不相同
不要将is用于数和字符串等不可变的基本值。

(3) 字符串和序列的比较
字符串是根据字符的字母(unicode)顺序进行比较的

>>> "alpha" < "beta"
True
>>>'☃'>'✈'
False

实际上,比较的这两个顺序值的大小

>>>ord('☃')
9731
>>>ord('✈')
9992

ord(x)函数时返回字符的顺序值,反函数是chr(x)

>>>chr(5553)
'ᖱ'

由于大写字母的顺序值小于小写(A:64,a:97),因此如果不需要区分大小写,可以使用字串方法S.lower()将大写转为小写,或者用S.upper()转为大写

>>>'A'<'a'
True
>>>'A.lower()'<'a'
False
2、布尔运算符

and or not
True and True ——True
True and False ——False 短路逻辑 延迟求值
False and False ——False
True or True —— True
True or False ——True
False or False —— False
Not True ——False
Not False ——True

>>>num=int(input())
>>>if num>1 and num<10:
...	  print('great')
5
Great
>>>name=input() or 'no name'
>>>print(name)
nnnn
nnnn

5.4.7断言Assert

Assert 如果条件返回错误,则终止程序,在条件后面添加字符串作说明

>>>a=-5
>>>assert 0<a<100,'错了错了错了'
--------------------------------------------------------------
AssertionError                      Traceback (most recent call last)
<ipython-input-68-a63d07d6a750> in <module>()
      1 a=-5
----> 2 assert 0<a<100,'错了错了错了'

AssertionError: 错了错了错了

5.5 循环

while we aren't stopped:
	send mail
	wait one month

5.5.1 while循环

三个条件:赋初值、条件判断、自增/自减

x = 1
while x <= 100:
	print(x)
	x += 1
out: 输出1100

name = “”   #是False,并且是个字符串
while not name:  #为避免输入空字符串,可替换为while not name or name.isspace()或者while not name.srip()
	name = input('Please enter your name: ')
	print('Hello, {}!'.format(name))
--------------------------------------------
Please enter your name: 
Hello, !
Please enter your name: kk
Hello, kk!

5.5.2 for循环

For循环可以为特定序列遍历其中所有元素

>>>for i in range(0,5):
...    print(i)
0
1
2
3
4

>>>for i in ['a','b','c']:
...	   print(i)
a
b
c

其中range(起始值含,终止值不含,步长)是一个创建范围的函数

>>> range(0, 10)
range(0, 10)
>>> list(range(0, 10))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

5.5.3 迭代字典

类似遍历序列的方式,同时可以打印出值

d={'a':'age','b':'name','c':'sex'}
for j in d:
	print(j,d[j])
--------------------------------------
a age
b name
c sex

或者用在字典序列d.items()里面遍历,可以序列解包

d={'a':'age','b':'name','c':'sex'}
for key,value in d.items(): #d.items()是一个可迭代的字典视图
	print(key,value)
----------------------------------------
a age
b name
c sex
d={'a':'age','b':'name','c':'sex'}
for it in d.items():
	print(it)
------------------------------------------
('a', 'age')
('b', 'name')
('c', 'sex')

5.5.4 一些迭代工具

1、并行迭代zip(list1,list2)

循环索引的标准名称i

name=['addy','benth','daef','kack']
age=[11,14,16,15]
for i in range(len(name)): #取短序列len,否则会报错
	print(name[i],age[i])
--------------------------------------
addy 11
benth 14
daef 16
kack 15

zip(list1,list2)将几个序列“缝合”起来,返回的是一个元组压缩包,需要用list或者tuple查看

>>>name=['addy','benth','daef','kack']
>>>age=[11,14,16,15]
>>>type(zip(name,age)) 
zip
>>>list(zip(name,age))
[('addy', 11), ('benth', 14), ('daef', 16), ('kack', 15)]

在循环中解包

name=['addy','benth','daef','kack']
age=[11,14,16,15]
sex=['male','female','male','female']
for a,b,c in zip(name,age,sex):
	print(a,b,c)
---------------------------------------------------
addy 11 male
benth 14 female
daef 16 male
kack 15 female

当两个被缝合的序列长度不一致是,会只缝合到最短序列的长度

>>> list(zip(range(5), range(100000000)))
[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4)]
2、迭代时获取索引enumerate()

方法1:先让i遍历列表中的每个值,然后轮到符合if条件的元素的时候,打印出该元素在列表中的位置

>>>lis=['a','hfbj','c']
>>>for i in lis:
>>>    if 'b'in i:
>>>        print(lis.index(i))
1

方法2:用i来记录遍历次数,初始数与第一个索引数相同=0,并且每轮一次,自增一次,由于遍历序列是按顺序的,当轮到符合if条件的时候,打印出的i刚好是元素的索引

lis=['a','hfbj','c']
i=0
for l in lis:
    if 'c'== l:
        print(i)
	i+=1
--------------------
2

内置函数enumerate(list),返回的是一个自带索引的元组包

>>>type(enumerate(lis))
>>>enumerate
>>>list(enumerate(lis))
[(0, 'a'), (1, 'dfdb'), (2, 'c')]

同样可以在循环中解包

>>>lis=['a','dfdb','c']
>>>for i,l in enumerate(lis):#i是索引数,l是对应元素
>>>    if 'b' in l:
>>>        print(i)
1
3、反向迭代reversed(list)和排序后再迭代sorted(list)

reversed(list)和sorted(list)不就地修改,总是返回字面逆序和排序后的版本

>>>lis=['a','dfdb','c']
>>>sorted(lis)
['a', 'c', 'dfdb']
>>>type(reversed(lis))
list_reverseiterator      #列表反序迭代器
>>>list(reversed(lis))    #list查看
['c', 'dfdb', 'a']        #reversed只是字面逆序

可在for循环和.join()方法中使用,但不能切片和索引

>>>m=''.join(reversed(lis))
>>>m
'cdfdba'
>>>m[0]
报错

5.5.5跳出循环

1、break

i在范围内正常遍历,打印出所有符合条件的值

>>>for i in range(10):
>>>    if i%2==1:
>>>        print(i)
1
3
5
7
9

如果希望满足条件后不再继续执行,可以使用break跳出循环

>>>for i in range(10):
>>>    if i%2==1:
>>>        print(i)
>>>        break
1
2、continue

如果满足条件后遇到continue,后面的语句就不再执行,直接跳到下一个else,不一定是结束循环

>>>for i in range(0,10):
>>>     if i%2==0:
>>>        print('偶数',i)
>>> 	print(i)
偶数 0
0
1
偶数 2
2
3
偶数 4
4
5
偶数 6
6
7
偶数 8
8
9

当遇到continue后,该次循环只执行到第一个Print就跳出循环了

>>>for i in range(0,10):
>>>    if i%2==0:
>>>        print('偶数',i)
>>>        continue
>>>    print(i)
偶数 0
1
偶数 2
3
偶数 4
5
偶数 6
7
偶数 8
9
3、while True/break成例

方式1:需要先赋值

>>>word='jhgh'
>>>while  word:#非空字符串True
>>>    word=input()
>>>    print('this is ',word)

方式2:语句重复

>>>word=input()
>>>while word:
>>>    print('this is',word)
>>>    word=input()

方式3:While True/break 更简洁

>>>while True:
>>>    word=input()#负责设置
>>>    if not word:break  #当word为空时执行该句
>>>    print('this is',word)# 在循环条件为真时使用第一部分初始化的数据。

While True/break 相对于for循环和while循环,不需要提前知道循环的次数,条件达到后即可停止循环,也不需要事先赋值,先执行后判断。
if/break行将整个循环分成两部分:第一部分负责设置(如果使用常规while循环,将重复这部分),第二部分在循环条件为真时使用第一部分初始化的数据。

5.5.6循环中的else子句

当在循环正常结束后没有输出,可以用else采取某种措施

>>>from math import sqrt
>>>for n in range(99,90,-1):
>>>    r=sqrt(n)
>>>    if r==int(r):
>>>        print(n)
>>>        break
>>>else:
>>>	print('not found')
not found

5.6简单推导

列表推导是一种从其他列表创建列表的方式,类似于数学中的集合推导。原理有点类似for循环

>>> [x for x in range(10)]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

相当于:

>>>result=[]
>>>for x in range(10):
>>>    result.append(x)
>>>print(result)

Notice:外面的方括号如果改成(),将会生成一个generator生成器,使用{ }则会生成一个集合,但是输出表达式如果用冒号分隔两个参数,则得到一个字典

>>> (x for x in range(10))
<generator object <genexpr> at 0x0000000004D817D8>      #生成器
>>>{x for x in range(10)}
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}                   #type验证是个set
>>>{x:x*x for x in range(10)}
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}   #字典

第一个x是要被输出的部分,后面的部分则是设置输出的条件,所有的输出都放在一个列表里,同样也可以带if条件

>>> [x*x for x in range(10) if x%3==0]
[0, 9, 36, 81]

相当于:

>>>result=[]
>>>for x in range(10):
>>>    if x%3==0:
>>>        result.append(x*x) 
print(result)

也可以多因素,嵌套循环

>>>[(x,y) for x in range(3)   for y in ['a','b']]
[(0, 'a'), (0, 'b'), (1, 'a'), (1, 'b'), (2, 'a'), (2, 'b')]

相当于:

>>>result=[]
>>>for x in range(3):
>>>		for y in ['a','b']:
>>>		   result.append((x,y))
>>>print(result)

同样,多因素的循环也可以加if条件

>>>girls=['alice','bence','cindy']
>>>boys=['allen','bob','chris']
>>>[(x,y) for x in girls  for y in boys  if x[0]==y[0]]
[('alice', 'allen'), ('bence', 'bob'), ('cindy', 'chris')]

相当于:

>>>result=[]
>>>girls=['alice','bence','cindy']
>>>boys=['allen','bob','chris']
>>>for x in girls:
>>>    for y in boys:
>>>        if x[0]==y[0]:
>>>            result.append((x,y))
>>>print(result)

这种方式需要将所有的配对方式列出来再选取,有效率更高的写法:

>>>result={}
>>>girls=['alice','bence','cindy']
>>>boys=['allen','bob','chris']
>>>for g in girls:
>>>    result.setdefault(g[0],[]).append(g)#append是序列的方法
>>>print([(xx,b) for b in boys for xx in result[b[0]]])

解析1:

>>>for g in girls:
>>>    result.setdefault(g[0],[])#这里返回的是一个列表[]
>>>    print(result)
>>>    result.setdefault(g[0],[]).append(g)#append是序列的方法
>>>	   print(result)  #实际上通过for循环
{'a': []}
{'a': ['alice']}
{'a': ['alice'], 'b': []}
{'a': ['alice'], 'b': ['bence']}
{'a': ['alice'], 'b': ['bence'], 'c': []}
{'a': ['alice'], 'b': ['bence'], 'c': ['cindy']}

解析2:

[(xx,b) for b in boys for xx in result[b[0]]]

相当于

>>>result={'a': ['alice'], 'b': ['bence'], 'c': ['cindy']}
>>>for b in ['allen','bob','chris']:
>>> 	print(b)
>>> 	print(b[0])
>>>     print(result[b[0]])
>>>     for xx in result[b[0]]:
>>>        print(xx,b) 
allen
‘a’
['alice']
alice allen
bob
‘b’
['bence']
bence bob
chris
‘c’
['cindy']
cindy chris

这种方式不需要检查每对配对,只需要查找键值

5.7三条语句pass、del和exec

5.7.1什么都不做pass

Pass可以用作占位符

>>>name='jack'
>>>if name=='allen':
>>>    print('hi')
>>>elif name=='jack':
>>>    pass#还未完成,运行到此,什么也不输出,也可插入一条字符串
>>>else:
>>>	   print('hello')

5.7.2使用del删除

当一个值没有任何名称与之关联的时候,这个值就被垃圾回收

>>>x=1
>>>y=x
>>>x=5
>>>y#这时候值1还没被回收,因为至少还有y跟它关联
1
>>>y=8
>>>print(x,y)#此时值1已经被回收了

del 语句删除到对象的引用和名称本身

>>>x=1
>>>y=x
>>>del x
>>>x
报错  #x这个名称也被删除了
>>>y
1   #x和引用的值1被删除了,但y和引用的值1没有被删除

事实上,在Python中,根本就没有办法删除值

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

1、exec():将字符串作为代码执行
>>>exec("print('Hello,World')")
Hello,World

但是如果只有一个参数,该字符串内容不可控,有可能会污染命名空间,修改变量

>>>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

实际上scope包含很多内容

>>> len(scope)
2
>>> scope.keys()
['sqrt', '__builtins__']
2、eval():计算用字符串表示的表达式的值,并返回结果(exec不返回)
>>>eval('4+5*9')
49

与exec一样,也可以向eval提供一个命名空间

>>>scope={}
>>>scope['x']=3
>>>scope['y']=2
>>>eval('x*y',scope)
6

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

>>> scope = {}
>>> exec('x = 2', scope)
>>> eval('x * x', scope)
4

猜你喜欢

转载自blog.csdn.net/weixin_40844116/article/details/84038411
今日推荐