循环结构
接上一篇。
for循环
通常用于可迭代对象的遍历。
注意,循环中的变量出来循环体外就会失效
for循环格式:
for 变量 in 可迭代对象:
循环体语句
例:
for x in (1,2,3,4,5):
print(x)
对于可迭代对象
字符串,依次把字符串中字符输出。
字典
字典的键
或
字典的值
字典的键对
range
range(start,end,step)
start:起始值,不写默认0;end:结束值;step:步长,默认为1。
for语句的else
用法与while的else一样
for 变量 in 可迭代对象
循环体
else
语句块
下面整点活儿:
b=['name','age','type','number']
a=[]
for i in range(4):
an=input('请输入{0}:'.format(b[i]))
a.append(an)
print('录入完成',end='! ')
if an=='q':
print('主动退出录入')
break
else:
c=dict(zip(b,a))
print('录入完成,录入结果为{0}'.format(c))
正常运行:会执行else的语句
break的情况下,没有执行else内的语句
break语句
可用于while和for循环,用来接收整个循环,当有嵌套循环时,break语句只能跳出最近的一层。
continue语句
只结束本次循环,整个循环继续。
continue后会提示不会运行它。
这里给个例子展示一下:注意输出的内容
x=0
while True:
x+=1
print('第{0}轮'.format(x),end='\t')
a=input()
if a=='q':
print('break,circle is over',end='\t')
break
else:
print('no break','\t')
if a == 'c':
print('continue,just jump one circle')
continue
print('it`s wrong , continue isn`t work!')
else:
print('no break and no continue,a full circle')
嵌套循环练习
1.实现这样的阵列
我的写法:
for x in range(5):
for i in range(5):
if i<4:
print(x,end='\t')
else:
print(x, end='\n')
课上的写法
for x in range(5):
for i in range(5):
print(x,end='\t')
print()
还是年轻了,没想到直接print()空输出来换行
2.打印下面的九九乘法表
我的写法
for x in range(1,10,1):
for i in range(1,x+1,1):
print(str(x),'*',str(i),'=',x*i,end='\t')
print()
课上讲的使用了.format来格式化输出
print("{0}*{1}={2}".format(x,i,x*i),end='\t')
3.用列表和字典存储下表信息,并打印出表中工资高于15000的数据
我写的:
l1={'name':'高小一','年龄':'18','薪资':30000,'城市':'北京'}
l2={'name':'高小二','年龄':'19','薪资':20000,'城市':'上海'}
l3={'name':'高小五','年龄':'20','薪资':10000,'城市':'深圳'}
a=[l1,l2,l3]
for x in a:
if x.get('薪资')>=15000:
print(x)
这次思路一样了,不写课上的代码了。
循环代码的优化
1.尽量减少循环内部不必要的计算;
2.嵌套循环中见谅减少内层的计算,将计算向外提;
3.局部变量查询的较快,尽量使用局部变量。
使用zip()进行并行迭代
其实有其他方法实现,这里只是说zip可以实现这种效果
推导式创建序列
列表推导式
生成列表对象
[表达式 for item in 可迭代对象]
a=[x**2 for x in range(1,5,1)]
print(a)
或
[表达式 for item in 可迭代对象 if 条件判断]
a=[x**2 for x in range(1,10,1) if x%2==0]
print(a)
更复杂的甚至可以写:
a=[(x,y)for x in range(3) for y in range(3)]
print(a)
整活
a=['{0}*{1}={2}'.format(x,y,x*y) for x in range(1,10,1) for y in range(1,x+1,1)]
count=0
for i in range(0,9,1):
for b in range(0,i+1,1):
print(a[count],end=' ')
count+=1
print()
print('乘法表')
字典推导式
生成字典对象
{key_expression : value_expression for 表达式 in 可迭代对象}
a1=['name','age','type']
a2=['temmie',23,'dog']
a={a1[i]:a2[i] for i in range(2)}
print(a)
课上给了一个更加有用的例子:统计一句话中各种字母的个数:
text='i am temmie!temmie!!temmie!!!'
a={c:text.count(c) for c in text}
print(a)
因为字典的键不能重复,所以本应该出现所有字符的,但每一个字符只出现了一次。
集合推导式
{expression for 表达式 in 可迭代对象}
跟字典的类似,这里就不演示了。
生成器推导式(生成元组)
注意:生成器运行一次只能用一次。生成器是一个可迭代的对象,使用的时候按照可迭代对象一样使用即可。
gnt=(x for x in range(1,100) if x%9==0)
for x in gnt:
print(x,end=' ')
练习:绘制不同颜色同心圆
先补充两个小海龟的语法:
1.可以赋值变量来简化输入:t=turtle.Pen(),这样后面调用时可以直接写t.circle来简化输入代码。
2.turtle.done()可以让绘制后的窗口不关闭(以前我的绘图截屏都是靠开debug来截图的,淦!)
3.turtle.speed()来设置绘制速度
import turtle as t
t.width('5')
t.speed(0)
co=('red','orange','yellow','green','cyan','blue','purple')
for i in range(1,7,1):
t.color(co[i])
t.penup()
t.goto(0,-50*i)
t.pendown()
t.circle(50*i)
t.done()
练习:绘制棋盘
import turtle as t
t.width('5')
t.speed(0)
for f in range(0,2,1):
for i in range(0,5,1):
if f==0:
t.penup()
t.goto(-100,50*i)
t.pendown()
t.goto(100,50*i)
else:
t.penup()
t.goto(50*(i-2),0)
t.pendown()
t.goto(50*(i-2),200)
t.done()
函数
函数是可重复用的程序代码块。是对代码的封装,增加了函数调用、传递参数、返回计算结果等内容。
查询函数文档可以使用:
help(函数名.__doc__)
python中的函数分类
1.内置函数:我们可以直接使用的都是内置函数
2.标准库函数:我们通过import导入库,然后使用的函数。
3.第三方库函数:在社区中下载安装,使用import导入的第三方函数。
4.用户自定义函数:我们自己创建的函数。
定义函数的方法:
def 函数名([参数列表]):
'''文档字符串(说明注释)'''
函数体/若干语句
多个参数时用 **,**隔开。无参数也要保留函数。
例:
创建
def temmie(n):
for i in range(1,n+1,1):
print('temmie','!'*i)
调用
temmie(5)
形参与实参
形参是函数定义时使用,是局部变量,超出函数部分将无效。形参不需要指定类型,实参与形参应是一一对应的。
def 函数名(形参1,形参2…)
实参是在调用函数时,传递的参数称为实参。
函数名(实参1,实参2…)
函数的返回值
return语句可以写或不写,不写默认返回None。
使用时格式:return 表达式
return后的语句不会执行。
对象=函数名(实参),这样就把返回值给了对象。
函数也是一个对象,你也可以不传给其他变量,直接作为一个对象使用。
对于要返回多个值时,可以利用列表、字典等来将多个数据返回。
全局变量与局部变量(变量的作用域)
变量起作用的模块被称为变量的作用域。不同作用域内各同名变量互不影响。
全局变量::
1.在函数和类定义之外声明的变量。作用域为定义的模块,从定义位置开始知道模块结束;
2.全局变量降低了函数通用性和可读性,应尽量避免全局变量的使用;
3.全局变量一般做常量使用;
4.函数内要改变全局变量的值,需要使用global声明一下;
局部变量::
1.在函数体中(包含形参)声明的变量;
2.局部变量的引用比全局量快,优先考虑使用;
3.如果局部变量和全局变量同名,这在函数内隐藏全局变量,只使用同名的局部变量。如果想用要用global声明一下再用。
输出全局、局部变量
使用下面的语句
print(locals())
print(globals())
a=100
b=200
def temmie_num():
a=1000
print(a)
global b
b=400
print('这是局部变量',locals())
print('这是全局变量',globals())
temmie_num()
参数的传递
函数的参数传递本质上就是:从实参到形参的赋值操作。
1.对于可变对象
字典、列表、集合、自定义的对象等,传递操作实际上是传递的内容地址。是对同一个对象进行操作。
2.对于不可变对象
数字、字符串、元组、function 等,传递操作是创建了一个新的对象。
a=100#数字,不可变对象
b=[200]#列表,可变对象
print(type(a),type(b))
print('a与b的地址',id(a),id(b))
def temmie(m,n):
print('m与n的地址',m,id(m),n,id(n),'传递进来的地址')
m=m*2
n.append(20)
print('m与n的地址',m,id(m),n,id(n))
temmie(a,b)#a是不可变对象,b是可变对象
print(a,b)
但我在自己尝试的时候有一点疑问,如果对列表操作换成n=n*2的话,它的地址会改变。
浅拷贝(copy)与深拷贝(deepcopy)
浅拷贝:不拷贝子对象的内容,只是拷贝子对象的引用。
深拷贝:会连子对象的内存也全部拷贝一份,对子对象的修改不会影响源对象。
使用时需要导入copy模块
我们用代码试验一下:
import copy
a=[10,20,[30,40]]
b=[50,60,[70,80]]
a_c=copy.copy(a)
b_c=copy.deepcopy(b)
a_c[2][1]=100
print(a,'\n',a_c)
b_c[2][1]=100
print(b,'\n',b_c)
print('a的元素地址:',a[0],':',id(a[0]),a[1],':',id(a[1]),a[2][0],':',id(a[2][0]),a[2][1],':',id(a[2][1]))
print('a_c的元素地址:',a_c[0],':',id(a_c[0]),a_c[1],':',id(a_c[1]),a_c[2][0],':',id(a_c[2][0]),a_c[2][1],':',id(a_c[2][1]))
print('b的元素地址:',b[0],':',id(b[0]),b[1],':',id(b[1]),b[2][0],':',id(b[2][0]),b[2][1],':',id(b[2][1]))
print('b_C的元素地址:',b_c[0],':',id(b_c[0]),b_c[1],':',id(b_c[1]),b_c[2][0],':',id(b_c[2][0]),b_c[2][1],':',id(b_c[2][1]))
结果:
下面我用图文表示一下我的理解:
也就是说,如果列表a有一个小本本,这个小本本记着它包含多少元素,每个元素在哪的话,浅拷贝只是把列表a的本本复制了一个一样的,而列表a中包含的列表b的小本本还是用的之前的;深拷贝则把所有本本都复制了一个。
参数的几种类型
位置参数
函数调用时,实参默认按照位置顺序传递,需要个数和形参匹配。按位置传递的参数,称为:位置参数
默认值参数
例如:def fuction1(a,b,c=1,d=2)
这面c和d就是默认值参数,如果调用函数时不给出则默认使用这些值,给出则使用输入的值。默认值参数必须放到最后面
命名参数
如:def fuction1(a,b,c)
在调用时写 fuction(c=1,b=2,a=10)则与写fuction(10,2,1)效果相同,但这样写可以乱序输入。
可变参数
- *param,将多个参数收集到一个元组对象中。
- **param,将多个采纳数收集到一个字典对象中。
def temmie(a,b,*c):
print(a,b,c)
def temmie01(a,b,**c):
print(a,b,c)
temmie(1,2,3,4,5,6)
temmie01(1,2,name='temmie',age=23)#注意这里面字典的表述方式!!
强制命名参数
对于上面可变参数,如果列在前面,会出现不知道从哪到哪是属于这个可变参数的值,所以如果函数定义时写成:
*def fuction01(a,b,c)
这种形式的话,调用应写作:
fuction01(1,2,3,4,b=1,c=2)
这样将名字写入,其他没有指定的就都是*a的内容。
lambda表达式和匿名函数
lambda表达式可以用来声明匿名函数,是一种简单的,在同一行中定义函数的方法。
lambda只允许包含一个表达式,不能包含复杂语句,该表达式的就是那结果就是函数的返回值。
lambda arg1,arg2...:<表达式>
arg1,arg2…相当于函数的参数,<表达式>相当于函数体。
eval函数
将字符串 str 当成有效的表达式来求值并返回计算结果。
eval(source[, globals[, locals]]) -> value
整个活吧:
while True:
message=input('temmie say:')
if message=='q':
print('tteemmiiee say:see ya!!!!',end='')
break
else:
print('tteemmiiee alsooo say:',end='')
eval(message)
递归函数
递归函数指的是:自己调用自己的函数,在函数体内部直接或间接的自己调用自己。
每个递归函数必须包含下面两部分:1.终止条件:表示递归什么时候结束,一般用于返回值,不再调用自己;2.递归步骤:把第n步的值和第n-1步相关联。
递归函数会大量占用资源,小心使用。
例子:计算阶乘
def fuction01(n):
if n==1:
return 1
else:
return n*fuction01(n-1)
a=fuction01(5)
print(a)
嵌套函数(内部函数)
在函数内部定义的函数
就是这样:
def outer_fuction():
代码块
def inner_fuction():
代码块
inner_fuction()#外函数调用内函数
outer_fuction()#使用外部函数
注意,内部函数只能由这个外部函数使用,其他位置无法调用该内部函数。
作用:封装:外部无法访问嵌套函数。2.避免函数内部代码重复。3.闭包(暂时没讲)