垃圾回收机制与流程控制
1.垃圾回收机制
引用计数
数据值被引用的数量
eg:
name = 'timi' # 数据值timi身上的引用计数为1
name1 = name # timi身上的引用计数为2
当数据值身上的引用计数为0时,系统会认为此数据值已无任何作用,此时会被垃圾回收机制回收
反之就是数据值身上的引用计数不为0时不会被垃圾回收机制回收
标记清除
主要针对循环引用问题
某些时候数据值在没绑定变量名的情况下身上的引用计数不为0
eg:
a1 = [1, 2] # 引用计数为1
a2 = [3, 4] # 引用计数为1
a1.append(a2) # a1 = [1, 2, [3, 4]] 此时[3, 4]引用计数为2
a2.append(a1) # a2 = [3, 4, [1, 2]] 此时[1, 2]引用计数为2
del a1 #断开变量名a1与列表[1, 2]的绑定关系 [1, 2]引用计数为1
del a2 #断开变量名a2与列表[3, 4]的绑定关系 [3, 4]引用计数为1
此时列表[1, 2]与[3, 4]身上都没有绑定的变量名但是引用计数却不为0
针对此种情况就产生了标记清除,其工作原理是:当内存占用达到一定程度时,程序会自动扫描程序中的所有数据,然后给只产生循环引用的数据打上标记之后一次性清除
分代回收
垃圾回收机制的频繁运行也会损耗各项资源,因此程序在扫描程序中的所有数据时会给数据自动做一个分级,使用频率从低到高放入各个级别中,各个级别程序的扫描频率不同,

2.流程控制理论
流程控制就是控制事物的执行流程,总共可以分为三种
-
顺序结构
从上往下依次执行
-
分支结构
事物的执行过程会根据条件的不同执行过程和结果也不同

- 循环结构
事务的执行会根据某个条件出现重复

流程控制必备知识
-
python中使用代码的缩进来表示代码的从属关系,缩进量相同时代码的地位相同,按照先后顺序依次执行
从属关系:缩进的代码也就是子代码是否执行取决于它的上层代码
-
不是所有的代码都有子代码
-
当某一行代码需要编写子代码,结尾要加冒号
-
当有多行子代码属于同一个上层代码时,缩进量相同
-
pycharm中针对缩进量没有要求但是推荐使用四个空格(快捷键为tab)
3.流程控制之分支结构
单if分支结构
if 条件:
条件成立之后才会执行的代码块
username = input('请输入用户名:')
if username == 'timi':
print('你好')

if...else...分支结构
if 条件:
条件成立之后执行的子代码
else:
条件不成立执行的子代码
username = input('请输入您的账号密码:')
if username == 'timi':
print('登陆成功')
else:
print('账号密码错误')

if...elif...else...分支结构
if 条件1:
条件1成立之后执行的子代码
elif 条件2:
条件1不成立,条件2成立执行的子代码
elif 条件3:
条件1和2都不成立,条件3成立执行的子代码
else:
上述条件都不成立执行的子代码
eg:
score = int(input('请输入分数:'))
if score >= 700:
print('恭喜你被清华大学录取了')
elif score >= 600:
print('恭喜你被985录取了')
elif score >= 500:
print('恭喜你被一本大学录取了')
elif score >= 400:
print('恭喜你被专科大学录取了')
else:
print('复读吧,啥也不是!!!')

if的嵌套使用
就是在if的条件语句下面再加if条件
sex = input('看到一个人:')
if sex == '女':
print('过去看看')
appearance = input()
if appearance == '美女':
print('上去要微信')
is_success = input()
if is_success == '成功':
print('聊天,增进关系')
else:
print('对不起我有男朋友了')
else:
print('路过')
else:
print('重新找一个')

4.流程控制之循环结构
让一些代码反复执行
while 条件:
条件成立之后执行的循环体代码
具体流程就是:
1.先判断条件是否成立
2.条件成立执行循环体代码
3.循环体代码执行完成以后回到条件判断处
4.条件成立则继续执行循环体代码
5.循环体代码的运行会一直持续到条件不成立
eg:
num = 1
while num <= 10:
print(num)
num += 1
print('结束')

循环体其它操作
break # 强行结束循环体
while循环体代码执行到break时会直接结束循环
continue # 直接跳到条件判断处
while循环体代码执行到continue时会结束本次循环,开始下一次循环
while 条件:
循环体代码
else:
循环体代码没有被强制结束的情况下执行完毕就会执行else子代码
while循环之补充说明
- 死循环
死循环的意思是一旦程序运行就不会自动停止

像上图所示的这种就是一个死循环,但还不是一个真正的死循环
真正的死循环是一旦程序运行,电脑的CPU利用率会急速上升,直至电脑采取紧急措施
程序执行前电脑的CPU利用率

程序执行后的CPU利用率

所以我们在以后编写程序的时候千万不要写出来一个死循环(自己电脑CPU烧了是小事,公司服务器出问题了那就BBQ了)
ps:我们在使用电脑时尽量不要让电脑的CPU长时间不间断运行
- 嵌套以及全局标志位
小知识:
- 一个break只能结束它所在的那一个循环体代码
- 想要一次性结束所有的循环体代码有几个while的嵌套就应该写几个break
- 如果不想写break,可以使用全局标志位
全局标志位:
看到这个名字就知道它很重要,概括的说就是程序中修改一次之后程序中所有有它的地方都会跟着修改从而使程序作出相应的改变
eg:
is_flag = True
while is_flag:
username = input('username>>>:')
password = input('password>>>:')
if username == 'jason' and password == '123':
while is_flag:
cmd = input('请输入您的指令>>>:')
if cmd == 'q':
break
print('正在执行您的指令:%s' % cmd)
break
else:
print('用户名或密码错误')
比如,在这个程序中我们写了两个while的嵌套,当我们想要一次性结束时,就需要写两个break,且break的位置需要与循环体代码相对应,如果我们不想写break,想用全局变量只需要一点小小的改动就行
is_flag = True
while is_flag:
username = input('username>>>:')
password = input('password>>>:')
if username == 'jason' and password == '123':
while is_flag:
cmd = input('请输入您的指令>>>:')
if cmd == 'q':
is_flag = False
print('正在执行您的指令:%s' % cmd)
else:
print('用户名或密码错误')
像这样,break去掉以后加一个is_flag = False,那么程序就会整体直接结束,而我们所加的就是一个全局变量
流程控制之for循环
for循环做到的事情while都能做到,while能做到的事情for不一定能做到,只是for循环在某些情况下的应用会比while更方便更简单
for循环主要应用于获取一些内部可以存储数据的数据的内部数据值
for循环语法结构:
for 变量名 in 待遍历的数据:
for循环体代码
eg:有一个列表[1, 2, 3, 4, 5, 6],我们需要循环打印出列表里的每一个数据值
num_list = [1, 2, 3, 4, 5, 6]
# for循环写法
for i in num_list:
print(i)
# while循环写法
count = 0
while count < 6:
print(num_list[count])
count += 1
在这个例子中我们可以看到第一个for循环的代码远远少于while循环,第二个当列表内的数据值的数量有变动时,for循环不需要动任何东西但是while循环需要修改条件不太方便
for循环的特点:
- 擅长遍历取值
- 不需要结束条件,遍历完以后自动结束
for循环主要遍历的数据类型是可以存储数据值的数据类型,字符串、列表、字典、元组、集合都是
字符串与字典稍微特殊
字符串遍历的是单个单个的字符

字典则是只有键参与遍历

for循环结构中变量名的命名
首先第一个尽量做到见名知意,第二个如果遍历出来的数据值没有具体的含义,那么就随便,但是推荐使用常用的,如:i j k v
小知识
-
break与continue在for循环中的用法与while循环一致
-
for循环结构也可以加else
for 变量名 in 待遍历的数据: for循环体代码 # 遇到break整个程序即停止,下面的else不会运行 else: for循环体代码没有被break强制结束且运行完毕之后才运行的代码range方法
range可以简单的理解为是一个可以帮我们产生多个数字的数据
eg:
for i in range(101): # 起始位置为0 终止位置为100 print(i) # [0,.......100]当然,range的写法不止这一种,还可以这样写
for i in range(10, 20): # 第一个为起始位置 第二个终止位置 print(i) # 或者这样写 for i in range(1, 20, 2): # 第三个数为等差值 默认不写为1 print(i)range小知识
range()在python2余python3中虽然长得一样但是产生的效果不一样,在python2中会产生一个内部存放多个数据值的列表,在python3中则只会产生一个像第二种range写法那样的数据,只要在范围内,我们需要哪个数据它就会产生哪个数据

在python2中range还有一种写法xrange(),这其实就是python3中的range
练习题详解
1.根据用户输入内容打印其权限
'''
jason --> 超级管理员
tom --> 普通管理员
jack,rain --> 业务主管
其他 --> 普通用户
'''
# 1.第一步,因为题目需要用户自己输入用户名,所以我们需要先定义一个用户输入
username = input('请输入用户名:')
'''
2.第二步,根据题目我们可以看到输入不同的用户名,输出结果不同,且条件不止一个,
所以这里我们需要用到if...elif...else结构
'''
if username == 'jason':
print('超级管理员')
elif username == 'tom':
print('普通管理员')
# 这一步我们需要注意一下,因为题目中有两个用户名,我们在写代码时极容易写成
# elif username == 'jack' or 'rain':
# 上面这段代码的意思是将username == 'jack'看成一个整体,'rain'看成一个整体
elif username == 'jack' or username == 'rain':
print('业务主管')
else:
print('普通用户')

2.编写用户登录程序
要求:有用户黑名单 如果用户名在黑名单内 则拒绝登录
eg:black_user_list = ['jason','kevin','tony']
如果用户名是黑名单以外的用户则允许登录(判断用户名和密码>>>:自定义)
eg: oscar 123
# 设置一个用户黑名单
black_username = ['jason', 'kevin', 'tony']
# 设置一个能够正确登录的用户名单
username_list = {'jack': 111, 'rain': 222}
# 先编写一个用户登录程序
username = input('请输入用户名:')
# 查看输入的用户名是否是黑名单用户
if username in black_username:
print('您已被加入黑名单')
# 如果用户不是黑名单用户则检查用户名正确与否
elif username in username_list:
pwd = int(input('请输入密码:'))
# 如果用户名正确检查输入的密码正确与否
if pwd == username_list[username]:
print('成功登录')
# 密码错误时,输出提示
else:
print('用户名密码错误')
# 用户名错误时输出提示
else:
print('用户不存在')

3.编写用户登录程序
用户如果登录失败 则只能尝试三次
用户如果登录成功 则直接结束程序
# 设置一个正确的用户名密码名单
username_list = {'jack': 111, 'rain': 222}
# 3.记录输入次数
count = 1
# 2.登陆失败可以重新登录,需要用到循环
while count <= 3:
# 1.先编写一个用户登录程序
username = input('请输入用户名:')
if username in username_list:
pwd = int(input('请输入密码:'))
if pwd == username_list[username]:
print('登陆成功')
break # 登录成功强制结束当前循环体代码(由于当前循环体代码下面没有同级别代码,程序结束运行)
else:
print('密码错误请重新登录')
count += 1 # 登陆失败重新登录,登录次数加1
else:
print('用户名不存在请重新登录')
count += 1 # 登陆失败重新登录,登录次数加1
else:
print('失败三次不允许登录')

4.猜年龄的游戏
假设用户的真实年龄是18 编写一个猜年龄的游戏 获取用户猜测的年龄
基本要求:可以无限制猜测 每次猜错给出提示(猜大了 猜小了) 猜对则结束程序
拔高练习:每次猜测只有三次机会 一旦用完则提示用户是否继续尝试 用户通过输入n或者y来表示是否继续尝试 如果是y则继续给用户三次猜测机会 否则结束程序
# 4.定义计数器
count = 1
# 3.添加循环结构
while count <= 3:
# 1.先编写一个猜年龄的小游戏,获取输入的猜测年龄
age = int(input())
# 2.判断猜测的年龄是否正确
if age > 18:
print('猜大了')
count += 1 # 猜错了,计数器加1
elif age < 18:
print('猜小了')
count += 1 # 猜错了,计数器加1
else:
print('猜对了')
# 5.猜对了结束循环
break
# 6.判断当前尝试次数
if count > 3:
a = input('是否继续?(y/n)')
if a == 'y': # 判断用户输入的选择
count == 1 # 重置计数器
continue
else:
break

5. 计算1-100所有的数之和
num = 0
for i in range(1, 101):
num += i
print(num)
- 判断列表中数字2出现的次数
l1 = [11,2,3,2,2,1,2,1,2,3,2,3,2,3,4,3,2,3,2,2,2,2,3,2]
num = 0
l1 = [11, 2, 3, 2, 2, 1, 2, 1, 2, 3, 2, 3, 2, 3, 4, 3, 2, 3, 2, 2, 2, 2, 3, 2]
for i in l1:
while i == 2:
num += 1
break
print(num)
- 编写代码自动生成所有页网址(注意总共多少页)
https://movie.douban.com/top250
l1 ='https://movie.douban.com/top250?start=%s&filter='
for i in range(0, 226, 25): # 打印开始为0,结束为226,等差为25的数值
print('https://movie.douban.com/top250?start=%s&filter=' % i)
- 编写代码打印出下列图形(ps:for循环嵌套)
*****
*****
*****
*****
for i in range(4):
for j in range(5):
print('*', end='')
print()
浙公网安备 33010602011771号