授课: 尚煜茗

Python程序实例解析

温度转换练习

根据华氏和摄氏温度定义,转换公式如下:C = ( F – 32 ) / 1.8,F = C * 1.8 + 32。其中,C表示摄氏温度,F表示华氏温度

1
2
3
4
5
6
7
8
9
temp_str=input("请输入带符号温度值:")
if temp_str[-1] in ['F','f']:
C=(eval(temp_str[0:-1])-32)/1.8
print("转换后的温度是{:.2f}C".format(C))
elif temp_str[-1] in ['C','c']:
F=1.8*eval(temp_str[0:-1])+32
print("转换后的温度是{:.2f}F".format(F))
else:
print("输入格式错误")

根据父母的身高可以估算一下孩子的身高,计算公式如下:男孩身高=(父亲身高+母亲身高+13)÷2,然后加或者减5公分。女孩身高=(父亲身高+母亲身高-13)÷2,然后加或者减5公分。设:父亲身高179,母亲身高165,计算他们生男孩和女孩,分别预测身高是多少?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 输入父母身高
father_height = 179
mother_height = 165

# 计算男孩身高
boy_height = (father_height + mother_height + 13) / 2
boy_min = boy_height - 5
boy_max = boy_height + 5

# 计算女孩身高
girl_height = (father_height + mother_height - 13) / 2
girl_min = girl_height - 5
girl_max = girl_height + 5

# 输出结果
print("父母身高:")
print(f"父亲:{father_height}cm,母亲:{mother_height}cm")
print("\n孩子预测身高:")
print(f"男孩:{boy_height:.1f}cm(范围:{boy_min:.1f}cm ~ {boy_max:.1f}cm)")
print(f"女孩:{girl_height:.1f}cm(范围:{girl_min:.1f}cm ~ {girl_max:.1f}cm)")

Python语法元素分析

程序的格式框架

(1)缩进

Python语言采用严格的“缩进”来表明程序的格式框架。缩进指每一行代码开始前的空白区域,用来表示代码之间的包含和层次关系。

1个缩进 = 4个空格。用以在Python中标明代码的层次关系,缩进是Python语言中表明程序框架的唯一手段。

image.png

单层缩进

image.png

多层缩进

(2)注释

image.png

image.png

命名与保留字

(1)Python 3.x保留字列表 (33个)

image.png

(2)命名表示

逻辑与值

1.True/False:布尔值常量,表示逻辑真/假

1
2
3
4
5
6
7
8
9
#True和False与整数进行比较
print(True==1)#True
print(False==0)#True
#True和False与浮点数进行比较
print(True==1.0)#True
print(False==0.0)#True
#True和False与字符串进行比较
print(True=="True")#False
print(False=="false")#False

2.None:空值常量,表示无数据,其数据类型为NoneType;所有赋值为None的变量都相等,并且None与其他任何非None的对象比较的结果都为False。

1
2
3
result = None
if result is None:
print("No data")

3.and/or/not:逻辑与/或/非运算,优先级not>and>or

and:所有条件必须同时为真,整个表达式才为真

or:只要有一个条件为真(True),整个表达式为真

not:逻辑非运算,对布尔值取反

1
2
3
4
5
lst=[1,2,3]
if not lst or len(lst)>10:
print("条件成立")
if lst and len(lst)<10:
print("有效列表")
1
2
3
4
5
6
7
8
9
10
11
### 实际应用场景:用户权限验证
is_admin = False
is_vip = True
has_2fa = False
# 允许访问的条件:管理员或(VIP且开启了二次验证)
access_granted = is_admin or (is_vip and has_2fa)
# 使用not优化逻辑:非管理员且验证不通过时拒绝
if not is_admin and not(is_vip and has_2fa):
print("访问被拒绝")
else:
print("允许访问")

控制流

4.if/elif/else:条件分支控制

if:判断语句

elif:判断语句,else if的缩写,是if语句的一部分,用于在满足多个条件时执行不同的代码块。

else:判断语句,对应if语句

1
2
3
4
5
6
7
score = 85
if score >= 90:
print("A")
elif score >= 80:
print("B")
else:
print("C")

5.for/in:遍历可迭代对象

for:循环语句

in:成员运算符,用于判断某个元素是否存在于一个集合中

1
2
3
4
5
6
7
8
for num in [1,2,3]:
print(num)#输出123

my_list =[1,2,3,4,5]
if 3 in my_list:
print("3存在于my_list中")
else:
print("3不存在于my_list中")

6.while/break/continue:循环控制与中断

while:循环语句,后接条件,若条件为真则运行后面的代码块break:用来终止循环语句,即循环条件没有False条件或者序列还没被完全递归完,也会停止执行循环语句。

continue:跳出本次循环,在本次循环后面的语句则不执行

1
2
3
4
5
6
7
8
9
10
11
12
#用while循环从1数到10
count = 1
while count <= 10:
#当count等于5时,使用continue跳过本次循环的剩余代码,直接进入下一次循环
if count==5:
count+=1
continue
print(count)
#当count等于8时,使用break跳出循环
if count==8:
break
count+=1

函数与类

7.def:定义函数

1
2
3
def greet(name):
return f"hello,(name)!"
print(greet("Alice")) #输出 Hello,Alice!

8.return:从函数返回值,并总结程序运行

1
2
3
def add(a,b);
result=a+b
return result #返回计算结果

9.lambda:创建匿名函数,它可以在不使用def和return关键字的情况下创建简单的函数

1
2
square=lambda x:x**2
print(square(3)) #输出9

10.class:用于定义类,是对象的声明

1
2
3
4
5
class Dog:
def bark(self):
print("Woof!")
my_dog=Dog()
my_dog.bark()

全局变量

11.global:用于在函数内部声明一个全局变量,使其能够被函数内部修改。

x仅在函数内被修改

1
2
3
4
5
6
def modify_x():
x=20
print(x)
x=10
modify_x()
print(x)

x作为全局变量被修改

1
2
3
4
5
6
7
def modify_x():
global x
x=20
print(x)
x=10
modify_x()
print(x)

12.nonlocal:用于在嵌套函数中声明一个外层变量(但非全局变量),使得内部函数可以调用该变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
def outer():
x=10 #外部函数的局部变量
def inner():
x=20 #修改外部函数的x
print("内部函数 x=",x)

inner()
print("外部函数 x=",x)

outer()

def outer():
x=10 #外部函数的局部变量

def inner():
nonlocal x
x=20 #修改外部函数的x
print("内部函数 x=",x)

inner()
print("外部函数 x=",x)

outer()

导入&命名

13.import/from/as:模块导入与命名

import:用于导入Python 模块或包,让当前脚本可以使用其他模块的功能。

from:用于从模块中导入特定的函数、类或变量,避免导入整个模块。

as:用于简化代码、避免名称冲突或提高可读性。

1
2
3
4
#从math库中导入sqrt函数
from math import sqrt as sq
print(sq(25))
#输出:5

删除&通过

14.del:用于删除变量、列表元素、对象属性等,释放内存。

1
2
3
4
5
x=10
del x #删除变量#
print(x)

#输出:NameError:name 's' is not defined
  1. pass:占位符,用于语法上需要代码但实际不执行任何操作。
1
2
3
#pass占位:避免语法错误
for i in range(s):
pass

异常处理

16.try/except/finally/raise:异常处理语句,用于处理代码运行时可能发生的错误和异常,避免程序崩溃。

1
2
3
4
5
6
7
8
9
10
11
12
13
try:
num = int(input("输入一个整数:"))
if num < 0:
raise ValueError("不允许输入负数")
print("输入的数字是:",num)
except ValueError as e:
print("异常:",e)
finally:
print("程序结束")

#输出:
输入一个整数:-5
异常:不允许输入负数程序结束

断言

17.assert:用于检查某个条件是否为 True,如果条件为 False则触发AssertionError并可选地附带错误信息,通常用于调试。

assert用于判断除数不能为0

1
2
3
4
5
6
def divide(a, b):
assert b!=0,"除数不能为 0"
return a/b

print(divide(10,2)) #正常运行
print(divide(10,0)) #触发AssertionError

生成器

18.yield:使函数变成迭代器,每次调用 yield 都会返回一个值,但函数的执行状态会被保存,可在下次迭代时继续执行。

每次调用next,函数都会暂停在yield并返回值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def my_generator():
yield 1
yield 2
yield 3

gen = my_generator()
print(next(gen))
print(next(gen))
print(next(gen))

#输出:
1
2
3

判断&处理

19.is用于判断两个对象是否是同一个对象,而不是判断它们的值是否相等。

20.with:用于上下文管理,通常用于简化资源管理,确保资源使用后能正确释放。

判断两者存储地址是否相同

1
2
3
4
a=[1,2,3]
b=[1,2,3]
print(a == b)#判断数值相等
print(a is b)#判断是否同一对象

用with打开并写入文件

1
2
3
with open("example.txt","w") as f:
f.write("Hello, world!")
#文件自动关闭

数据类型

(1)程序设计语言让计算机明确数据形式的方式,为数据类型100,100,100

(2)数值:Python语言中,包含整型、浮点型、复数类型等三种,100,30.7,1+2i,int(),float()转换

Python中一般可以直接操作数值运算,不用担心溢出问题,但需要注意0.1 + 0.2 = ?

数值过长时,可以用下划线“_”分割。i = 1_000_000, i + 10 = ?

(3)字符串:Python语言中,字符串是用两个双引号“ ”或者单引号‘ ’括起来的一个或多个字符。Python字符串的两种序号体系。

image.png

字符串中取字符:TempStr[-1]:取字符串TempStr最后一个字符

字符串区间访问:TempStr[0:-1]:取开始到最后一个字符(不含)的部分

*左闭右开

(4)序列:在Python中,序列指任何包含对象的有序集合。可以通过“索引” 来获取其中的成员,也可以通过“切片” 来获取其中的子序列。

列表,字符串,元组,数组(Numpy库)

Len(), string[index],string.index(x),string[0:2]

String[0:10:1]

(5)布尔类型

a.Python中表示“真”、“假”的类型,True和False,对应0、1。int(True),int(False)

b.布尔值可作为数值参与运算

练习:从网上随意找一段文字,并统计字符串中有多少个特定字符?例如,空格,“人”、“标点符号”

语句与函数、Python的输入输出

(1)赋值语句

a.Python语言中,= 表示“赋值”,即将等号右侧的值计算后将结果值赋给左侧变量,包含等号(=)的语句称为“赋值语句”

b.同步赋值语句:同时给多个变量赋值<变量1>, …, <变量N> = <表达式1>, …, <表达式N>

image.png

(2)input()函数

获得用户输入之前,input()函数可以包含一些提示性文字

<变量> = input(<提示性文字>)

1
2
3
4
5
6
>>>input("请输入: ")
请输入: python
'python'
>>> input("请输入: ")
请输入: 1024.256
'1024.256'

(3)分支语句

image.png

(4)eval()函数

eval(<字符串>)函数是Python语言中一个十分重要的函数,它能够以Python表达式的方式解析并执行字符串,将返回结果输出

1
2
3
4
5
>>>x = 1
>>>eval("x + 1")
2
>>>eval("1.1 + 2.2")
3.3

(5)输出函数

print()函数用来输出字符信息,或以字符形式输出变量。

print()函数可以输出各种类型变量的值。

print()输出多个变量或常量,用逗号分隔

例如:print(“a和b的值为:”,a , b)

(6)格式化输出

在输出变量的值时,可以通过字符串的format方法将输出变量整理成我们期望的格式

大括号表示槽的位置,括号内容由format方法的参数C填充

大括号中的:.2f表示输出格式(保留两位小数)

(6)循环语句

a.循环语句:控制程序运行,根据判断条件或计数条件确定一段程序的运行次数

b.遍历循环,基本过程如下

for i in range (<计数值>):

<语句块>

c.例如,使某一段程序连续运行10次

for i in range (10):

<语句块>

d.其中,变量i用于计数

*练习:基于本节课学习内容,撰写一个“选择排序”程序

第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。以此类推,直到全部待排序的数据元素的个数为零。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def selection_sort(arr):
# 遍历数组中的所有元素
for i in range(len(arr)):
# 假设当前元素是最小的
min_idx = i
# 检查剩余未排序部分是否有更小的元素
for j in range(i+1, len(arr)):
if arr[j] < arr[min_idx]:
min_idx = j
# 将找到的最小元素与当前位置元素交换
arr[i], arr[min_idx] = arr[min_idx], arr[i]
return arr

# 测试选择排序
if __name__ == "__main__":
test_array = [64, 25, 12, 22, 11]
print("排序前:", test_array)
sorted_array = selection_sort(test_array)
print("排序后:", sorted_array)

turtle库和蟒蛇绘制程序

1.蟒蛇绘制实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#e2.1DrawPython.py
import turtle#import是一个关键字,用来引入一些外部库,这里的含义是引入一个名字叫turtle的函数库
turtle.setup(650,350,200,200)#前两个为画布长宽,后两个为画布距离屏幕左上角距离
turtle.penup()#抬起画笔
turtle.fd(-250)#往前/后走250个(看符号),penup了不留痕迹
turtle.pendown()#放下画笔
turtle.pensize(25)#画笔大小
turtle.pencolor("purple")#颜色
turtle.seth(-40)#设置朝向,负为顺时针
for i in range(4):#循环0,1,2,3(4次,左闭右开,每次画了一正一反2个弯,共8个弯)
turtle.circle(40,80)#第一个为圆的半径,第一个为圆的弧长(圆的度数的弧长)
turtle.circle(-40, 80) #以它的右侧40,再画80弧长
turtle.circle(40,80/2)
turtle.fd(40)#往前40距离
turtle.circle(16,180)#画了一个180度的圆
turtle.fd(40*2/3)#往前走了此距离
turtle.done()

Python蟒蛇程序分析

(1)import turtle:import是一个关键字,用来引入一些外部库,这里的含义是引入一个名字叫turtle的函数库

(2)Turtle库:

a,Turtle库是Python语言中一个很流行的绘制图像的函数库

b.使用turtle库,需要有以下概念:想象一个小乌龟,在一个横轴为x、纵轴为y的坐标系原点,(0,0)位置开始。它根据一组函数指令的控制,在这个平面坐标系中移动,从而在它爬行的路径上绘制了图形

c..()是Python典型表达形式:对象.方法()、库.函数()

d.Turtle中的turtle.setup()函数用于启动一个图形窗口,它有四个参数:turtle.setup(width, height, startx, starty)

分别是:启动窗口的宽度和高度。表示窗口启动时,窗口左上角在屏幕中的坐标位置。

(3)程序:

a.Turtle中的turtle.pencolor()函数表示小乌龟运动轨迹的颜色。

b.它包含一个输入参数,这里我们把它设为蓝色,blue,其他颜色单词也可以使用。Turtle采用RGB方式来定义颜色,如果希望获得和图片中颜色一致的小蛇,请输入turtle.pencolor(“#3B9909”)

c.Turtle.penup() turtle.pendown() 表示提起和放下画笔

d.Turtle中的turtle.pensize()函数表示小乌龟运动轨迹的宽度。它包含一个输入参数,这里我们把它设为25像素。

e.Turtle中的turtle.seth(angle)函数表示小乌龟启动时运动的方向。它包含一个输入参数,是角度值。

其中,0表示向东,90度向北,180度向西,270度向南;负值表示相反方向。

程序中,我们让小乌龟向-40度启动爬行,即:向东南方向40度。

(4)Turtle空间坐标体系

1
2
3
4
5
6
7
8
#绝对坐标(画布坐标)
import turtle
turtle.goto(100, 100)
turtle.goto(100, -100)
turtle.goto(-100,-100)
turtle.goto(-100,100)
turtle.goto(0,0)
turtle.done()

前进方向、右侧方向、左侧方向、正后方向:Turtle.circle(r, angle)、Turtle.bk(d)、Turtle.fd(d)

练习题:请尝试用turtle画一个“正三角形”

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import turtle
# 设置画布
screen = turtle.Screen()
screen.title("正三角形绘制")
# 创建海龟对象
t = turtle.Turtle()
t.shape("turtle") # 设置海龟形状
t.color("blue") # 设置画笔颜色
t.pensize(3) # 设置画笔粗细
# 绘制正三角形(每条边长度200,内角60度)
for _ in range(3):
t.forward(200) # 前进200像素
t.left(120) # 左转120度(外角)
# 完成绘制
turtle.done()

(5)turtle.circle()函数功能

a.turtle.circle()函数让小乌龟沿着一个圆形爬行

b.参数rad描述圆形轨迹半径的位置:这个半径在小乌龟运行的左侧rad远位置处,如果rad为负值,则半径在小乌龟运行的右侧

c.参数angle表示小乌龟沿着圆形爬行的弧度值(就是圆的度数)

(6)turtle.fd()函数功能

turtle.fd()函数也可以用turtle.forward()表示乌龟向前直线爬行移动

表示小乌龟向前直线爬行移动,它有一个参数表示爬行的距离

turtle.left(角度), turtle.right(角度) 小乌龟以当前位置为准,向左/右调整行进方向

1
2
3
4
5
6
7
8
9
#一个简单的例子
import turtle
turtle.left(45)
turtle.fd(100)
turtle.left(135)
turtle.fd(200)
turtle.right(135)
turtle.fd(100)
turtle.done()

(7)Turtle填充颜色

开始填充 turtle.begin_fill(),结束填充 turtle.end_fill(),选择颜色 turtle.fillcolor(“颜色”)

*练习:奥运五环个人代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import turtle
turtle.setup(1000,600,200,200)#前两个为画布长宽,后两个为画布距离屏幕左上角距离
turtle.pensize(10)#画笔大小

turtle.penup()#抬起画笔
turtle.seth(0)#设置朝向,负为顺时针,0正常从底部逆时针
turtle.fd(-150)#往前+/后-走150个(看符号),penup了不留痕迹
turtle.pendown()#放下画笔

turtle.pencolor("blue")#颜色
turtle.circle(60,360)#画了一个360度的圆

turtle.penup()#抬起画笔
turtle.fd(150)#往前+/后-走150个(看符号),penup了不留痕迹
turtle.pendown()#放下画笔
turtle.pencolor("black")#颜色
turtle.circle(60,360)#画了一个360度的圆

turtle.penup()#抬起画笔
turtle.fd(150)#往前+/后-走150个(看符号),penup了不留痕迹
turtle.pendown()#放下画笔
turtle.pencolor("red")#颜色
turtle.circle(60,360)#画了一个360度的圆

turtle.penup()#抬起画笔
turtle.seth(45)#设置朝向,负为顺时针,0正常从底部逆时针
turtle.fd(-45)#往前+/后-走45个(看符号),penup了不留痕迹
turtle.pendown()#放下画笔
turtle.pencolor("green")#颜色
turtle.circle(60,360)#画了一个360度的圆

turtle.penup()#抬起画笔
turtle.seth(5)#设置朝向,负为顺时针,0正常从底部逆时针
turtle.fd(-190)#往前+/后-走190个(看符号),penup了不留痕迹
turtle.pendown()#放下画笔
turtle.pencolor("yellow")#颜色
turtle.circle(60,360)#画了一个360度的圆

turtle.done()

函数封装

蟒蛇程序功能

可以分成两类:绘制图形前对画笔的设置,包括颜色、尺寸、初始位置等以及绘制Python蟒蛇的功能。

由于蟒蛇绘制的功能相对独立,可以用函数来封装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#e2.3DrawPython.py
import turtle
def drawSnake(radius,angle,length):
turtle.seth(-40)
for i in range(length):
turtle.circle(radius,angle)
turtle.circle(-radius,angle)
turtle.circle(radius,angle/2)
turtle.fd(40)
turtle.circle(16,180)
turtle.fd(40*2/3)
turtle.setup(650,350,200,200)
turtle.penup()
turtle.fd(-250)
turtle.pendown()
turtle.pensize(25)
turtle.pencolor("purple")
drawSnake(40,80,4)
turtle.done()

def定义函数

def用于定义函数。函数是一组代码的集合,用于表达一个功能,或者说,函数表示一组代码的归属,函数名称是这段代码的名字。

def所定义的函数在程序中未经调用不能直接执行,需要通过函数名调用才能够执行。

Python第一次作业

作业1:说句心里话A

1
2
3
name = input()
message = input()
print(f"{name},我想对你说,{message}")

作业2:货币转换1

1
2
3
4
5
6
7
8
9
a=input()
b=a[:3]
c=a[3:]
if b=="RMB":
d=(eval(c)/6.78)
print("USD{:.2f}".format(d))
elif b=="USD":
d=(eval(c)*6.78)
print("RMB{:.2f}".format(d))

作业3:垂直的世界,你好!

1
2
3
a="世界,你好!"
for char in a:
print(char)

作业4:美国队长盾牌

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import turtle
import math
# 最大圆半径240,最小圆的半径是60,由大到小依次减少60
# 由外向内填充颜色依次是红、白、红、蓝
turtle.speed(0) # 设置turtle的速度为最快
color_list = ['red', 'white', 'red', 'blue'] # 填充颜色
xy_list = [(0, -240), (0, -180), (0, -120), (0, -60)] # 从大到小四个圆的起始点坐标
for i in range(4):
turtle.goto(xy_list[i])
turtle.pencolor(color_list[i])
turtle.fillcolor(color_list[i])
turtle.begin_fill()
turtle.circle(240-i*60,360)
turtle.end_fill()
# 内接五角星的边长,数学问题
width = (math.sin(math.radians(36)) * 60) / math.sin(math.radians(126))
# 绘制内接五角,填充白色
turtle.penup()
turtle.goto(0,60) #画笔移动到最小圆的最高点
turtle.pendown()
turtle.right(72) #设置画笔起始角度
turtle.pencolor('white') #设置画笔颜色为白色
turtle.fillcolor('white') #设置填充颜色为白色
turtle.begin_fill() #开始填充
for i in range(5): #循环画五角星的外轮廓
turtle.fd(width)
turtle.left(72)
turtle.fd(width)
turtle.right(144)
turtle.end_fill() #结束填充
#=======================================================
turtle.hideturtle()
turtle.done()

作业5:绘制中国象棋

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
import turtle as t
width = 60 # 定义全局变量,每个单元格的宽度

def draw_chessboard(x, y):
"""绘制棋盘的方格"""
t.penup()
t.goto(x-0.3*width, y-0.3*width)
t.color('black','orange')
t.begin_fill()
t.goto(x+8.3*width,y-0.3*width)
t.goto(x+8.3*width,y+9.3*width)
t.goto(x-0.3*width,y+9.3*width)
t.end_fill()

t.pendown()
t.goto(x-0.3*width, y-0.3*width)
t.goto(x+8.3*width, y-0.3*width)
t.goto(x+8.3*width, y+9.3*width)
t.goto(x-0.3*width, y+9.3*width)

for i in range(5):
t.penup()
t.goto(x, y+i*width)
t.pendown()
t.forward(8*width)
for i in range(9):
start_x = x+i*width
t.penup()
t.goto(start_x, y)
t.pendown()
t.goto(start_x, y+4*width)
t.penup()
t.goto(x, y+8*width)
t.pendown()
for i in range(5,10):
t.penup()
t.goto(x, y+i*width)
t.pendown()
t.forward(8*width)
for i in range(9):
start_x = x+i*width
t.penup()
t.goto(start_x, y+5*width)
t.pendown()
t.goto(start_x, y+9*width)

def draw_camp():
"""绘制将帅营的斜线"""
# 红方九宫格斜线
t.penup()
t.goto(-width,-4*width)
t.pendown()
t.goto(width,-2*width)
t.penup()
t.goto(-width,-2 width)
t.pendown()
t.goto(width,-4*width)
# 黑方九宫格斜线
t.penup()
t.goto(-width,3*width)
t.pendown()
t.goto(width,5*width)
t.penup()
t.goto(-width,5*width)
t.pendown()
t.goto(width,3*width)

def marker(x, y):
"""在指定位置绘制标记"""
t.penup()
t.goto(x, y)
t.pendown()
t.dot(5)

def draw_marker_gun():
"""绘制炮位标记"""
# 红方炮位
marker(-3*width,-2*width)
marker(3*width,-2*width)
# 黑方炮位
marker(-3*width,3*width)
marker(3*width,3*width)

def draw_marker_soldier():
"""绘制兵卒位标记"""
# 红方兵位
for i in [0,2,4,6,8]:
x = -4*width+i*width
y = -4*width+3*width
marker(x,y)
# 黑方卒位
for i in [0,2,4,6,8]:
x = -4*width+i*width
y = -4*width+6*width
marker(x,y)

def piece_circle(radius):
"""绘制棋子圆形"""
t.begin_fill()
t.circle(radius)
t.end_fill()

def piece_font(text, fontColor):
"""在棋子上写文字"""
t.color(fontColor)
t.write(text, align='center', font=('楷体', 25, 'bold'))

def draw_boundary(x, y):
"""绘制楚河汉界文字"""
t.penup()
t.goto(-2*width,0.25*width)
t.color('green')
t.write("楚", align='center', font=('楷体', 25, 'bold'))
t.goto(-0.66*width,0.25*width)
t.write("河", align='center', font=('楷体', 25, 'bold'))
t.goto(0.66*width,0.25*width)
t.write("汉", align='center', font=('楷体', 25, 'bold'))
t.goto(2*width,0.25*width)
t.write("界", align='center', font=('楷体', 25, 'bold'))

def draw_piece_soldier(x, y):
"""绘制兵和卒的棋子"""
radius = width*0.4
# 红方兵
for i in [0, 2, 4, 6, 8]:
x_pos=-4*width+i*width
y_pos=-4*width+3*width
t.penup()
t.goto(x_pos, y_pos-radius)
t.setheading(0)
t.pendown()
t.pencolor('red')
t.fillcolor('white')
piece_circle(radius)
t.penup()
t.goto(x_pos,y_pos-0.25*width)
piece_font('兵','red')
# 黑方卒
for i in [0, 2, 4, 6, 8]:
x_pos=-4*width+i*width
y_pos=-4*width+6*width
t.penup()
t.goto(x_pos, y_pos-radius)
t.setheading(0)
t.pendown()
t.pencolor('green')
t.fillcolor('white')
piece_circle(radius)
t.penup()
t.goto(x_pos,y_pos-0.25*width)
piece_font('卒','green')

def draw_piece_gun(x, y):
"""绘制炮的棋子"""
radius = width * 0.4
# 红方砲
for i in [1, 7]:
x_pos = -4 * width + i * width
y_pos = -4 * width + 2 * width
t.penup()
t.goto(x_pos, y_pos - radius)
t.setheading(0)
t.pendown()
t.pencolor('red')
t.fillcolor('white')
piece_circle(radius)
t.penup()
t.goto(x_pos, y_pos-0.25*width)
piece_font('砲', 'red')
# 黑方炮
for i in [1, 7]:
x_pos = -4 * width + i * width
y_pos = -4 * width + 7 * width
t.penup()
t.goto(x_pos, y_pos - radius)
t.setheading(0)
t.pendown()
t.pencolor('green')
t.fillcolor('white')
piece_circle(radius)
t.penup()
t.goto(x_pos, y_pos-0.25*width)
piece_font('炮', 'green')

def draw_piece_other(x, y):
"""为其他棋子增加文字"""
radius = width * 0.4
for i in range(9):
t.penup()
t.goto(-4 * width + i * width, -4 * width - radius)
t.setheading(0)
t.pendown()
t.pencolor('red')
t.fillcolor('white')
piece_circle(radius)
t.penup()
t.goto(-4 * width + i * width, -4.25*width)
piece_font(chess_pieces[0][i], 'red')
for i in range(9):
t.penup()
t.goto(-4 * width + i * width, -4 * width + 9 * width - radius)
t.setheading(0)
t.pendown()
t.pencolor('green')
t.fillcolor('white')
piece_circle(radius)
t.penup()
t.goto(-4 * width + i * width, 4.75* width)
piece_font(chess_pieces[1][i], 'green')

if __name__ == '__main__':
# t.tracer(10) # 取消注释可加速刷新,提高绘制速度
t.speed(0) # 绘制速度
t.pensize(2) # 画笔粗线
width = 60 # 设置每格宽度
t.screensize(10 * width, 12 * width) # 画布大小
pos_of_x, pos_of_y = -4 * width, -4 * width # 画笔初始坐标
chess_pieces = [['車', '馬', '相', '仕', '帅', '仕', '相', '馬', '車', '兵', '砲'],['車', '馬', '相', '仕', '帅', '仕', '相', '馬', '車', '兵', '砲']]
font_color = ['red', 'green'] # 设置棋子填充色
draw_chessboard(pos_of_x, pos_of_y) # 绘制空棋盘函数
draw_camp() # 绘制将帅营房函数
draw_marker_gun() # 绘制炮位标记函数
draw_marker_soldier() # 绘制兵卒位标记函数
draw_boundary(pos_of_x, pos_of_y) # 绘制楚河汉界函数
draw_piece_soldier(pos_of_x, pos_of_y) # 绘制棋子兵和卒函数
draw_piece_gun(pos_of_x, pos_of_y) # 绘制棋子炮函数
draw_piece_other(pos_of_x, pos_of_y) # 绘制其他棋子函数
t.hideturtle() # 隐藏画笔
t.update() # 更新缓存
t.done() # 结束绘制

Python基本数据类型

数字类型

程序元素:010/10,存在多种可能:表示十进制整数值10,类似人名一样的字符串

数字类型对Python语言中数字的表示和使用进行了定义和规范

Python语言包括三种数字类型:整数类型、浮点数类型、复数类型

整数类型

与数学中的整数概念一致,没有取值范围限制

pow(x, y)函数:计算x的y次方

打开IDLE。程序1:pow(2,10) , pow(2,15);程序2:pow(2, 1000);程序3:pow(2, pow(2,15))

image.png

浮点数类型

带有小数点及小数的数字。

Python语言中浮点数的数值范围存在限制,小数精度也存在限制。这种限制与在不同计算机系统有关。

image.png

image.png

(1)浮点数间运算存在不确定尾数,不是bug

image.png

(2)浮点数间运算存在不确定尾数,不是bug

image.png

(3)浮点数间运算存在不确定尾数

image.png

复数类型

与数学中的复数概念一致, z = a + bj, a是实数部分,b是虚数部分,a和b都是浮点类型,虚数部分用j或者J标识。示例:12.3+4j, -5.6+7j

z = 1.23e-4+5.6e+89j(实部和虚部是什么?)

对于复数z,可以用z.real获得实数部分,z.imag获得虚数部分

a.conjugate() 输出共轭复数

z.real = 0.000123 z.imag = 5.6e+89

数字类型的操作

数值运算操作符

(1)操作符是完成运算的一种符号体系

image.png

image.png

(2)二元操作符有对应的增强赋值操作符

image.png

数字类型的关系

(1)类型间可进行混合运算,生成结果为”最宽”类型

三种类型存在一种逐渐”扩展”或”变宽”的关系:整数 -> 浮点数 -> 复数

例如:123 + 4.0 = 127.0(整数+浮点数 = 浮点数)

可以用type()函数进行类型判断

(2)内置的数值运算函数:Python解释器提供了一些内置函数,在这些内置函数之中,有6个函数与数值运算相关

image.png

数字类型的转换

(1)数值运算操作符可以隐式地转换输出结果的数字类型

例如,两个整数采用运算符“/”的除法将可能输出浮点数结果。此外,通过内置的数字类型转换函数可以显式地在数字类型之间进行转换

image.png

(2)三种类型可以相互转换

函数:int(), float(), complex()

示例:int(4.5) = 4 (直接去掉小数部分)、float(4) = 4.0 (增加小数部分)、complex(4) = 4 + 0J

复数不能转化为浮点数、整数,会报错!

image.png

数字类型的判断

函数:type(x),返回x的类型,适用于所有类型的判断

示例:

image.png

math库的使用

math库概述

(1)math库是Python提供的内置数学类函数库

(2)math库不支持复数类型

(3)math库一共提供了4个数学常数和44个函数。44个函数共分为4类。

包括:16个数值表示函数、8个幂对数函数、16个三角对数函数和4个高等特殊函数

首先使用保留字import引用该库

第一种:import math。对math库中函数采用math.()形式使用

1
2
3
import math
math.ceil(10.2)
#11

第二种,from math import <函数名>。对math库中函数可以直接采用<函数名>()形式使用

1
2
3
from math import floor
floor(10.2)
#10

math库解析

(1)math库包括4个数学常数

image.png

(2)math库包括16个数值表示函数

image.png

(3)math库中包括8个幂对数函数

image.png

(4)math库包括六个“三角、双曲函数”

image.png

(5)math库包括4个高等特殊函数

image.png

天天向上的力量

1.一年365天,以第1天的能力值为基数,记为1.0,当好好学习时能力值相比前一天提高1%,当没有学习时由于遗忘等原因能力值相比前一天下降1%。每天努力和每天放任,一年下来的能力值相差多少呢?

1
2
3
4
5
#e3.1DayDayUp365.py
import math
dayup = math.pow((1.0 + 0.001), 365) # 提高0.001
daydown = math.pow((1.0 - 0.001), 365) # 放任0.001
print("向上: {:.2f}, 向下: {:.2f}.".format(dayup, daydown))

运行结果如下,每天努力1%,一年下来将提高44%,好像不多?请继续分析。

2.一年365天,如果好好学习时能力值相比前一天提高5%,当放任时相比前一天下降5%。效果相差多少呢?

1
2
3
4
5
#e3.2DayDayUp365.py
import math
dayup = math.pow((1.0 + 0.005), 365) # 提高0.005
daydown = math.pow((1.0 - 0.005), 365) # 放任0.005
print("向上: {:.2f}, 向下: {:.2f}.".format(dayup, daydown))

运行结果如下,每天努力5%,一年下来将提高6倍!

3.一年365天,如果好好学习时能力值相比前一天提高1%,当放任时相比前一天下降1%。效果相差多少呢?

1
2
3
4
5
6
#e3.3DayDayUp365.py
import math
dayfactor = 0.01
dayup = math.pow((1.0 + dayfactor), 365) # 提高dayfactor
daydown = math.pow((1.0 - dayfactor), 365) # 放任dayfactor
print("向上: {:.2f}, 向下: {:.2f}.".format(dayup, daydown))

运行结果如下,每天努力1%,一年下来将提高37倍。这个相当惊人吧!

4.一年365天,一周5个工作日,如果每个工作日都很努力,可以提高1%,仅在周末放任一下,能力值每天下降1%,效果如何呢?

1
2
3
4
5
6
7
8
#e3.4DayDayUp365.py
dayup, dayfactor = 1.0, 0.01
for i in range(365):
if i % 7 in [6, 0]:#周六周日
dayup = dayup * (1 - dayfactor)
else:
dayup = dayup * (1 + dayfactor)
print("向上5天向下2天的力量: {:.2f}.".format(dayup))

猜猜运行结果?每周努力5天,而不是每天,一年下来,水平仅是初始的4.63倍!与每天坚持所提高的237倍相去甚远

5.如果对实例代码3.4的结果感到意外,那自然会产生如下问题:每周工作5天,休息2天,休息日水平下降0.01,工作日要努力到什么程度一年后的水平才与每天努力1%所取得的效果一样呢?

1
2
3
4
5
6
7
8
9
10
11
12
13
#e3.5DayDayUp365.py
def dayUP(df):
dayup = 0.01
for i in range(365):
if i % 7 in [6, 0]:
dayup = dayup * (1 -0.01 df)
else:
dayup = dayup * (1 + df)
return dayup
dayfacotr = 0.01
while (dayUP(dayfactor)<37.78):
dayfactor += 0.001
print("每天的努力参数是: {:.3f}.".format(dayfactor))

如果每周连续努力5天,休息2天,为了达到每天努力1%所达到的的水平,则就需要在工作日将提高的程度达到约2%,即要努力1倍才仅是为了休息2天。这就是天天向上的力量。

字符串类型及其操作

字符串

(1)由0个或多个字符组成的有序字符序列

image.png

image.png

(2)不同表示方法的作用

image.png

字符串类型的转换

大多数数据类型都可以通过str()函数转换为字符串

image.png

字符串的序号

正向递增序号和反向递减序号

image.png

字符串的使用

使用[ ]获取字符串中一个或多个字符

image.png

*注意:字符串的“驻留”

Python对于短小字符串会自动驻留,使其指向同一块内存

image.png

image.png

字符串切片高级用法

使用[M: N: K]根据步长对字符串切片

image.png

字符串的特殊字符

转义符 \

image.png

字符串切片相关事例内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#TempStr[-1]:取字符串最后一个字符
#TempStr[0:-1]:取开始到最后一个字符(不含)的部分。左闭右开!!!
s="Hello World"
print(s[4])#o
print(s[1:])#ello World
print(s[:-1])#Hello Worl
print(s[-6])#和s[5]相同输出空格
print(s[6:10])#Worl
print(s[-5:-2])#Wor
print(s[2:5:1])#llo,下标2到5,步长为1
print(s[2:5:2])#lo,下标2到5,步长为2
print(s[5:2:-1])# ol,下标5到2,步长为-1(其实就是反过来)
print(s[-5:-1:3])#Wl,下标-5到-1,可认为是6到9,步长为3
print(s[::-1])#dlroW olleH 开头和结尾都省略时,默认按步长(-1从后往前1步,-2为从后往前2步)
eval("print('Hello World')")只去掉一层引号

字符串操作符

(1)操作符及使用

由0个或多个字符组成的有序字符序列。如果*后面是负数,会怎样。

image.png

(2)获取星期字符串

输入:1-7的整数,表示星期几。输出:输入整数对应的星期字符串。例如:输入3,输出星期三

1
2
3
4
5
6
7
8
9
10
#WeekNamePrintV1.py
weekStr = "星期一星期二星期三星期四星期五星期六星期日"
weekId = eval(input("请输入星期数字(1-7):"))
pos = (weekId–1) * 3
print(weekStr[pos: pos+3])

#WeekNamePrintV2.py
weekStr = "一二三四五六日"
weekId = eval(input("请输入星期数字(1-7):"))
print("星期" + weekStr[weekId-1])

字符串处理函数

(1)一些以函数形式提供的字符串处理功能

image.png

(2)一些以函数形式提供的字符串处理功能

image.png

(3)Unicode编码:Python字符串的编码方式

统一字符编码,即覆盖几乎所有字符的编码方式

从0到1114111 (0x10FFFF)空间,每个编码对应一个字符

Python字符串中每个字符都是Unicode编码字符

例子:

image.png

字符串处理方法

(1)”方法”在编程中是一个专有名词

image.png

(2)一些以方法形式提供的字符串处理功能

image.png

image.png

image.png

观察例子:

image.png

image.png

字符串类型的格式化

1.字符串格式化

Python中字符串格式化的三种方法:

(1)字符串%运算:format%values,早期使用较多

类似于C语言中的printf函数:format为格式字符串,values为要设置格式的值。

例:print(“Hello, %s” % name)

(2)字符串format方法:最常用例:print(“Hello,”.format(name))

(3)f字符串:例:print(f”Hello, {name}”)

format()方法的基本使用

字符串format()方法的基本使用格式是:<模板字符串>.format(<逗号分隔的参数>)

默认的参数序号:

image.png

改变默认的参数序号:

image.png

按照关键词插入:

image.png

format()方法的格式控制

槽内部对格式化的配置方式。{ <参数序号> : <格式控制标记>}

image.png

image.png

image.png

时间

1
2
3
4
for i in range(10):
print("hello world"+str(i)+"\r",end="")
#print("hello world" + str(i) + "\r", end="",flush=True)
time.sleep(5)

笔记草稿

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
content='你的表现真不错👍🏿'
print(len(content))
print(content[-1])

s='👨‍👨‍👧‍👦'
for i in s:
print(i)

print(ord('中'))
print(bin(20013))
c='1+1=2'+chr(10004)
print(c)
d='这个字符♏的Unicode值是:'+str(ord('♏'))
print(d)

for i in range(12):
print(chr(9800+i),end=' ')

a='absadfdasfadsf'
print(a.upper())#ABSADFDASFADSF
b=a.upper()
print(b.lower())#absadfdasfadsf
d='aa bb cc dd ee'
print(d.split(' '))#['aa', 'bb', 'cc', 'dd', 'ee']
f='aa,bb,cc,dd,ee'
print(f.split(','))#['aa', 'bb', 'cc', 'dd', 'ee']
s='  hello  world  '
print(s.split(" "))#['', '', 'hello', '', 'world', '', '']
t='##hello###world##'
print(t.split("#"))#['', '', 'hello', '', '', 'world', '', '']
print(t.split("##"))#['', 'hello', '#world', '']
q='###hello#####world###'
print(q.split("###"))#['', 'hello', '##world', '']
print(q.replace("#","o"))#ooohellooooooworldooo
w='hello world'
print(w.split(' '))#['hello', 'world']
x='hello'print(x.center(20,"*"))#*******hello********
y=' hello     world 'print(y.split(' '))#['', 'hello', '', '', '', '', 'world', '']
print(y.strip())#hello     world
a='pythonpython=='
print(a.strip('py='))#thonpython
li='12345'
print(li.join(' '))#' '
print(' '.join(li))#1 2 3 4 5
a='test'
b='work'
print(a+b)#testwork
1
2
3
4
print("{}的概率是{}%,这个概率小于阈值{}".format('事件发生',95,98))
#事件发生的概率是95%,这个概率小于阈值98
print("{1}的概率是{2}%,这个概率小于阈值{0}".format('事件发生',95,98))
#95的概率是98%,这个概率小于阈值事件发生(结果倒过来,引入第几个参数)

课堂事例记录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
a="123456789"
print(a[::2])#13579
text="My name is {0} and I am {1} years old.".format("Alice",25)
print(text)#My name is Alice and I am 25 years old.
text="My name is {name} and I am {age} years old.".format(name="Alice",age=25)
print(text)#My name is Alice and I am 25 years old.

content="{:=^50}".format("Train")
print(content)#======================Train=======================
content="{:-^50}".format("Test")
print(content)#-----------------------Test-----------------------
content="{:-^50,}".format(123123123123)
print(content)#-----------------123,123,123,123------------------
content="{:-^50,.2}".format(3.14159265)
print(content)#-----------------------3.1------------------------
content="{:-^50,.2f}".format(3.14159265)
print(content)#-----------------------3.14-----------------------
content="{:-^50,.2e}".format(3.14159265)
print(content)#---------------------3.14e+00---------------------
content="{:-^50,.2E}".format(3.14159265)
print(content)#---------------------3.14E+00---------------------
content="{:-^50,.2%}".format(3.14159265)
print(content)#---------------------314.16%----------------------
content="{:-^50b}".format(16)
print(content)#----------------------10000-----------------------
content="{:-^50d}".format(16)
print(content)#------------------------16------------------------
content="{:-^50o}".format(16)
print(content)#------------------------20------------------------
content="{:-^50x}".format(16)
print(content)#------------------------10------------------------
content="{:-^50X}".format(15)
print(content)#------------------------F-------------------------
content="{:-^50c}".format(97)
print(content)#------------------------a-------------------------
content="{:-^50c} hello world {:->20c}".format(97,10010)#>为右对齐
print(content)#------------------------a------------------------- hello world -------------------✚
content="{:-^50c} hello world {:+<20c}".format(97,8888)#<为左对齐
print(content)#------------------------a------------------------- hello world ⊸+++++++++++++++++++
content="{1:-^50c} hello world {0:+<20c}".format(97,98)
print(content)#------------------------b------------------------- hello world a+++++++++++++++++++

content="{0:=^20}".format("PYTHON")
print(content)#=======PYTHON=======
content="{0:*>20}".format("BIT")
print(content)#*****************BIT
content="{:10}".format("BIT")
print(content)#BIT

文本进度条

简单的开始

利用print()函数实现简单的非刷新文本进度条。

基本思想是按照任务执行百分比将整个任务划分为100个单位,每执行N%输出一次进度条。每一行输出包含进度百分比,代表已完成的部分(**)和未完成的部分(..)的两种字符,以及一个跟随完成度前进的小箭头,风格如下:

image.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#e4.1TextProgressBar.py
import time
scale=10
print("------执行开始------")
for i in range(scale+1):
a='**'*i
b='..'*(scale-i)
c=(i/scale)*100
print("%{:^3.0f}[{}->{}]" .format(c,a,b))
time.sleep(0.1)
print("------执行结束------")

'''
输出结果:
------执行开始------
% 0 [->....................]
%10 [**->..................]
%20 [****->................]
%30 [******->..............]
%40 [********->............]
%50 [**********->..........]
%60 [************->........]
%70 [**************->......]
%80 [****************->....]
%90 [******************->..]
%100[********************->]
------执行结束------
'''

单行动态刷新

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#e4.2TextProgressBar.py
import time
for i in range(101):
print("\r{:2}%".format(i), end="")
time.sleep(0.05)

'''
输出结果:
0% 1% 2% 3% 4% 5% 6% 7% 8% 9% 10% 11% 12% 13% 14% 15% 16%
17% 18% 19% 20% 21% 22% 23% 24% 25% 26% 27% 28% 29% 30% 31% 32% 33%
34% 35% 36% 37% 38% 39% 40% 41% 42% 43% 44% 45% 46% 47% 48% 49% 50%
51% 52% 53% 54% 55% 56% 57% 58% 59% 60% 61% 62% 63% 64% 65% 66% 67%
68% 69% 70% 71% 72% 73% 74% 75% 76% 77% 78% 79% 80% 81% 82% 83% 84%
85% 86% 87% 88% 89% 90% 91% 92% 93% 94% 95% 96% 97% 98% 99% 100%
'''

为什么输出没有单行刷新呢?

这是因为IDLE本身屏蔽了单行刷新功能,如果希望获得刷新效果,请使用控制台命令行执行e4.2TextProgressBar.py程序。以Windows系统为例,启动命令行工具(<Windows系统安装目录>\system32\cmd.exe),选择到e4.2TextProgressBar.py文件所在目录执行

带刷新的文本进度条

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#e4.3TextProgressBar.py
import time
scale = 50
print("执行开始".center(scale//2,'-'))
t = time.clock()
for i in range(scale+1):
a = '*' * i
b = '.' * (scale - i)
c = (i/scale)*100
t -= time.perf_counter()
print("\r{:^3.0f}%[{}->{}]{:.2f}s".format(c,a,b,-t),\end='')
time.sleep(0.05)
print("\n"+"执行结束".center(scale//2,'-'))

'''
输出结果:
-----------执行开始----------
100%[**************************************************->] 65.71s
-----------执行结束----------
'''

五花八门的进度条设计函数

image.png

专门的进度条库tqdm

Tqdm是python中专门用于处理和实现进度条的库。简单、易用、功能强大。将一个进度条包装在可迭代对象上,显示其执行时间

(1)基本用法

1
2
3
4
5
#最基本的用法
from tqdm import tqdm
import time
for i in tqdm(range(100)):
time.sleep(0.1)

(2)tqdm.write()

在tqdm进度条中,直接使用print会打乱排版,tqdm.write()就是解决该问题

1
2
3
4
for i in tqdm(range(10)):
time.sleep(0.5)
if i%2==0:
print("阶段性进展")

(3)tqdm.trange()

Trange()是tqdm(range())的简写形式

1
2
3
4
from tqdm import trange 
import time
for i in trange(50, desc="加载中", unit="文件"):
time.sleep(0.1)

(4)Tqdm嵌套进度条

支持嵌套进度条,适用于多层循环的场景。Leave参数的作用,表示当前进度条结束之后是否要保留。

1
2
3
4
5
6
from tqdm import tqdm
import time

for i in tqdm(range(5),desc="外层循环"):
for j in tqdm(range(100),desc="内层循环",leave=False):
time.sleep(0.01)

Tqdm手动更新进度条:有些不可迭代的对象也需要进度条展示,便可采用手动更新方式

1
2
3
4
5
6
from tqdm import tqdm 
import time
with tqdm(total=100) as pbar:
for i in range(10):
time.sleep(0.5)
pbar.update(10)

正则表达式

正则表达式

(1)正则表达式的作用就是从文本中提取特定信息

(2)正则表达式与Python独立

(3)正则表达式在科研、工程、数据挖掘等实践中非常有用。爬虫所获取的数据的解析~

看一个例子:

大数据项目经理(上海正中能源科技有限公司) 上海正中能源科技有限公司上海2.50万/每月
大数据项目经理(上海众调信息科技有限公司) 上海众调信息科技有限公司上海1.8万/月
大数据项目经理(03)(复深蓝软件) 上海复深蓝软件股份有限公司上海0.65万/每月
393197-大数据精算团队主管(平安医疗健康管理股份有限公司) 平安医疗健康管理股份有限公司上海3.3333万/月
医疗大数据销售 神州医疗投资有限公司东城区8000万/每月
393185-大数据运维工程师(平安医疗健康管理股份有限公司) 平安医疗健康管理股份有限公司上海28000万/每月

如何提取公司名称,以及工资金额,例如:上海正中能源科技有限公司2.50万元?

r’([上海|平安].?公司).?([\d.]+万)/每{0,1}月’,

1
2
3
4
5
Lines = content.splitlines()
For I in lines:
寻找 关键词 位置
如果存在,则……
如果不存在,则 continue

image.png

正则表达式,就是高效处理上述问题的有力工具。其核心就是“模式匹配”

正则表达式的常见语法

正则表达式中包括了【普通字符】和【特殊字符】

普通字符:没有特殊含义,如月/每/元

特殊字符:在正则表达式语法中承担特殊功能的字符,如 * ? []

(1).  表示匹配除了换行符之外的任意单个字符

苹果是红色

香蕉是黄色

乌鸦是黑色

橙子是黄色

过程:

定义变量 content = “源字符串”

导入库 import re

定义模式 p = re.compile(r’.色’)

遍历文字 for one in p.findall(content):

得到结果 print(one)

(2)*表示匹配前面出现的字符或者表达式任意次数【可以是0次】

苹果,是红色的

香蕉,是黄色的

乌鸦,是黑色的

橙子,是黄色的

目标:匹配逗号后面的内容,包括逗号本身

**,.(最常见的组合),苹果是绿色色色色色色色的*

*紧跟在.后面,表示任意字符可以出现任意多次

(3)+表示匹配前面出现的字符或者表达式一次或者多次【不能是0次】

苹果,是红色的

香蕉,是黄色的

乌鸦,是黑色的

橙子,是黄色的

目标:绿色+

苹果是绿色色色色色色色的

绿

*紧跟在.后面,表示任意字符可以出现任意多次

(4)花括号{} 表示匹配前面出现的字符或者表达式指定次数

苹果,是红色的

香蕉,是黄色的

乌鸦,是黑色的

橙子,是黄色的

示例:红彤彤,绿油油,黑乎乎,白茫茫,粉噗噗噗噗噗噗噗

匹配文本中的“噗”至少出现3次,最多出现7次

粉噗{3,7} 粉噗{7}

最常用的场景,就是手机号(连续11位),身份证号(连续13位)

(5)区分贪婪模式与非贪婪模式

image.png

(6)对特殊字符的转义

image.png

(7)用反斜杠匹配某种字符类型

image.png

image.png

(8)[]方括号表示匹配几个字符之一

image.png

(9)^不在方括号中,表示匹配文本的起始位置

正则表达式分为单行和多行模式,匹配的是行的开头

image.png

(10)$表示匹配文本的结尾,同样分为多行模式和单行模式

image.png

(11)( )表示分组

image.png

image.png

正则表达式切分字符串

image.png

image.png

练习题

(1)判断字符串是否为一个合法的用户名,一个合法的用户名只能包含数字、字母、下划线,并且第一个字母为大写

^[A-Za-z0-9_]*$

(2)匹配.com或者.cn结尾的url网址,并将其他无关信息全部过滤掉

(1) String = “百度首页

“[a-zA-Z]+://[^\s]*[.com | .cn]”

(3)使用正则表达式校验身份证号码

身份证号码的规则:公民身份号码是特征组合码,由十七位数字本体码和一位数字校验码组成。排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。

地址码(身份证前六位)表示编码对象第一次申领居民身份证时的常住户口所在县(市、旗、区)的行政区划代码。生日期码(身份证第七位到第十四位)表示编码对象出生的年、月、日,其中年份用四位数字表示,年、月、日之间不用分隔符。例如:1981年05月11日就用19810511表示。

顺序码(身份证第十五位到十七位)是县、区级政府所辖派出所的分配码,其中单数为男性分配码,双数为女性分配码

校验码(身份证最后一位)是根据前面十七位数字码。

^[1-9]\d{5}[0-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$

Python第二次作业

第一题:计算几何形状的表面积与体积

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
import math

def type_judge(geom_type):
"""接收一个字符串为参数,根据参数判断几何体类型
若输入为二维图形,计算其面积
若输入为三维图形,计算其面积与体积
根据类型调用不同的函数进行运算。
"""
if geom_type == '长方形':
length, width = map(float, input().split()) # 空格分隔的输入切分为列表并映射为浮点数
return square(length, width) # 调用函数计算长方形面积
elif geom_type == '长方体':
length, width, height = map(float, input().split()) # 空格分隔的输入切分为列表并映射为浮点数
return cube(length, width, height) # 调用函数计算长方体表面积与体积
elif geom_type == '圆形':
radius = float(input()) # 输入转为浮点数
return circle(radius) # 调用函数计算圆面积
elif geom_type == '球':
radius = float(input()) # 输入转为浮点数
return sphere(radius) # 调用函数计算球表面积与体积
elif geom_type == '圆柱体':
radius, height = map(float, input().split()) # 空格分隔的输入切分为列表并映射为浮点数
return cylinder(radius, height) # 调用函数计算圆柱体表面积与体积
elif geom_type == '圆锥':
radius, height = map(float, input().split()) # 空格分隔的输入切分为列表并映射为浮点数
return cone(radius, height) # 调用函数计算圆锥表面积与体积
elif geom_type == '正三棱柱':
side, height = map(float, input().split())
return tri_prism(side, height)
else:
return f'未找到{geom_type}计算方法'

def square(length, width):
"""计算长方形的面积"""
area_of_square = length * width
return f'长方形的面积为{area_of_square:.2f}'

def cube(length, width, height):
"""计算长方体的表面积和体积"""
area_of_cube = length * width * 2 + width * height * 2 + length * height * 2
volume_of_cube = length * width * height
return f'长方体的表面积为{area_of_cube:.2f}, 体积为{volume_of_cube:.2f}'

def circle(radius):
"""接收圆的半径,返回圆形的面积,圆周率用math.pi"""
area_of_circle = math.pi * radius ** 2
return f'圆形的面积为{area_of_circle:.2f}'

def sphere(radius):
"""接收球的半径,返回球的表面积和体积,圆周率用math.pi"""
area_of_sphere = 4 * math.pi * radius ** 2
volume_of_sphere = 4 / 3 * math.pi * radius ** 3
return f'球的表面积为{area_of_sphere:.2f}, 体积为{volume_of_sphere:.2f}'

def cylinder(radius, height):
"""接收圆柱体的底面半径和高,返回圆柱体的表面积和体积,圆周率用math.pi"""
area_of_cylinder = 2 * math.pi * radius * (radius + height)
volume_of_cylinder = math.pi * radius ** 2 * height
return f'圆柱体的表面积为{area_of_cylinder:.2f}, 体积为{volume_of_cylinder:.2f}'

def cone(radius, height):
"""接收圆锥的底面半径和高,返回圆锥的表面积和体积,圆周率用math.pi"""
area_of_cone = math.pi * radius * (radius + math.sqrt(radius ** 2 + height ** 2))
volume_of_cone = 1 / 3 * math.pi * radius ** 2 * height
return f'圆锥的表面积为{area_of_cone:.2f}, 体积为{volume_of_cone:.2f}'

# 参考前面的方法自定义一个函数计算正三棱柱的表面积与体积,
# 函数名为tri_prism()
# 函数接受底边长和高两个参数side, height

def tri_prism(side, height):
"""计算正三棱柱的表面积与体积"""
area_of_tri_prism = side * 3 * height + side ** 2 * math.sqrt(3) / 2
volume_of_tri_prism = side ** 2 * math.sqrt(3) / 4 * height
return f'正三棱柱的表面积为{area_of_tri_prism:.2f}, 体积为{volume_of_tri_prism:.2f}'

if __name__ == '__main__':
type_of_geometry = input() # 接收用户输入的字符串
geometry = type_judge(type_of_geometry) # 调用判断图形类型的函数
print(geometry) # 输出函数运行结果

第二题:计算弓形的面积

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import math
# 输入弦长度,浮点数#
chord = float(input( ))

# 输入弓高度,浮点数#
bow = float(input( ))

# 计算半弦长#
half_chord = chord / 2

# 计算半径#
radius = (half_chord**2 + bow**2)/(2*bow)

# 计算圆心角#
central_angle=2*math.asin(half_chord/radius)

# 计算弓形所在扇形的面积#
area_of_sector = central_angle/(math.pi*2) * math.pi *radius**2

# 计算三角形面积
area_of_triangle = 1/2 * (radius**2) * math.sin(central_angle)

# 计算弓形面积#
area_of_arch = area_of_sector - area_of_triangle

# 在两行中分别输出半径和弓形面积#
print("{0:.2f}".format(radius))
print("{0:.2f}".format(area_of_arch))

第三题:学费计算

1
2
3
4
5
6
7
8
9
10
11
python = 3
math = 4
english = 4
physical = 2
military_theory = 2
philosophy = 2
total = python + math + english + physical + military_theory + philosophy
per_fee=int(input())
fee= total * per_fee
print("你本学期选修了{}个学分。".format(total))
print("你应缴纳的学费为{}元。".format(fee))

第四题:商店找钱

1
2
3
4
5
6
7
8
9
10
import math
money=eval(input())
m50 = math.floor(money/50)
money = money % 50
m5 = math.floor(money/5)
money = money % 5
m1 = math.floor(money/1)
print("50yuan:",m50)
print("5yuan:",m5)
print("1yuan:",m1)

第五题:获得用户的输入当作宽度,以*作为填充符号右对齐输出PYTHON字符串

1
2
3
w = input()  # 请输入输出宽度:
s = "PYTHON"
print("{:*>{}}".format(s, w))

第六题:获得用户输入,无论输入内容多少,以30字符宽度居中输出其中最多前10个字符,‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬如果不足10个字符,则全部输出

1
2
s = input()  # 请输入信息:
print("{:^30}".format(s[:10]))

第七题:获得输入正整数N,反转输出该正整数,不考虑异常情况

1
2
N=input()
print(int(N[::-1]))

第八题:字母统计a

1
2
s = input()
print(s.count('a'))

第九题:三次方格式化

1
2
3
4
a = eval(input())#获取输入并转换为数值
result = str(a ** 3)#计算三次方并转为字符串
formatted_result = result.center(20, '-')#居中并用 '-' 填充
print(formatted_result)

程序的控制结构

程序的基本结构

顺序结构是程序的基础,但单一的顺序结构不可能解决所有问题。

程序由三种基本结构组成:顺序结构、分支结构、循环结构

这些基本结构都有一个入口和一个出口。任何程序都由这三种基本结构组合而成。

程序的分支结构

单分支结构if语句

*Python中if语句的语法格式如下:

if <条件>:
语句块

语句块是if条件满足后执行的一个或多个语句序列。语句块中语句通过与if所在行形成缩进表达包含关系。if语句首先评估<条件>的结果值,如果结果为True,则执行语句块里的语句序列,然后控制转向程序的下一条语句。如果结果为False,语句块里的语句会被跳过。

if语句中语句块执行与否依赖于条件判断。但无论什么情况,控制都会转到if语句后与该语句同级别的下一条语句。

image.png

if语中<条件>部分可以使用任何能够产生True或False的语句

形成判断条件最常见的方式是采用关系操作符

*Python语言共有6个关系操作符:

image.png

(1)If x == True:可简写做 If x(2)If支持链式比较: if 0 < x < 10:(3)判断是否为空,要用 is None(4)Python列表推导式中,可以用if进行过滤

条件组合:*用于条件组合的三个操作符

image.png

image.png

1
2
3
4
5
6
7
8
#微实例4.4:PM 2.5空气质量提醒(1)
PM = eval(input("请输入PM2.5数值: "))
if 0<= PM < 35:
print("空气优质,快去户外运动!")
if 35 <= PM <75:
print("空气良好,适度户外活动!")
if 75 <= PM:
print("空气污染,请小心!")

二分支结构:if-else语句

Python中if-else语句用来形成二分支结构,语法格式如下:

if <条件>:
<语句块1>
else:
<语句块2>

<语句块1>是在if条件满足后执行的一个或多个语句序列。<语句块2>是if条件不满足后执行的语句序列。二分支语句用于区分<条件>的两种可能True或者False,分别形成执行路径。

1
2
3
4
5
6
#微实例4.5:PM 2.5空气质量提醒(2)
PM = eval(input("请输入PM2.5数值: "))
if PM >= 75:
print("空气存在污染,请小心!")
else
print("空气没有污染,可以开展户外运动!")

二分支结构还有一种更简洁的表达方式,适合通过判断返回特定值,语法格式如下:**<表达式1> if <条件> else <表达式2>**

1
2
PM = eval(input("请输入PM2.5数值: "))
print("空气{}污染!".format("存在" if PM >= 75 else "没有"))

简单的条件判断语句可以用if三元运算符

1
Results = "Positive" if x > 0 else "Negative"

if…else的紧凑结构非常适合对特殊值处理的情况如下

1
2
3
4
5
6
>>>count = 2
>>>count if count!=0 else "不存在"
2
>>>count = 0
>>>count if count!=0 else "不存在"
"不存在"

多分支结构: if-elif-else语句

Python的if-elif-else描述多分支结构,语句格式如下:

if <条件1>:
<语句块1>
elif <条件2>:
<语句块2>

else:
<语句块N>

image.png

多分支结构是二分支结构的扩展,这种形式通常用于设置同一个判断条件的多条执行路径。

Python依次评估寻找第一个结果为True的条件,执行该条件下的语句块,同时结束后跳过整个if-elif-else结构,执行后面的语句。如果没有任何条件成立,else下面的语句块被执行。else子句是可选的,

微实例4.4通过多条独立的if语句对同一个变量PM进行判断,这种情况更适合多分支结构,改造后的代码如下

1
2
3
4
5
6
7
PM = eval(input("请输入PM2.5数值: "))
if 0 <= PM < 35:
print("空气优质,快去户外运动!")
elif 35 <= PM <75:
print("空气良好,适度户外活动!")
else:
print("空气污染,请小心!")

实例:身体质量指数BMI

BMI的定义如下:BMI = 体重(kg)÷身高^2(m^2)。例如,一个人身高1.75米、体重75公斤,他的BMI值为24.49

image.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#e5.1CalBMI.py
height, weight = eval(input("请输入身高(米)和体重\(公斤)[逗号隔开]: "))
bmi = weight / pow(height, 2)
print("BMI数值为:{:.2f}".format(bmi))
wto, dom = "", ""
if bmi < 18.5: # WTO标准
wto = "偏瘦"
elif bmi < 25: # 18.5 <= bmi < 25
wto = "正常"
elif bmi < 30: # 25 <= bmi < 30
wto = "偏胖"
else:
wto = "肥胖"

if bmi < 18.5: # 我国卫生部标准
dom = "偏瘦"
elif bmi < 24: # 18.5 <= bmi < 24
dom = "正常"
elif bmi < 28: # 24 <= bmi < 28
dom = "偏胖"
else:
dom = "肥胖"
print("BMI指标为:国际'{0}', 国内'{1}'".format(wto, dom))

>>>
请输入身高(米)和体重(公斤)[逗号隔开]: 1.75, 75
BMI数值为:24.49
BMI指标为:国际'正常', 国内'偏胖'

程序的循环结构

遍历循环(for)、无限循环(while)、循环控制保留字

遍历循环for语句

遍历循环:循环的次数是确定的,循环语句对循环次数有明确的定义,循环次数采用遍历结构中元素个数来体现

Python通过保留字for实现“遍历循环” :

for <循环变量> in <遍历结构>:
<语句块>

image.png

*遍历循环的应用

计数循环(N次)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
>>> for i in range(5):
print(i)
0
1
2
3
4

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

计数循环(特定次):遍历由range()函数产生的数字序列,产生循环

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
for i in range(M,N,K) :
<语句块>

for i in range(1,6):
print(i)
1
2
3
4
5

>>> for i in range(1,6,2):
print("Hello:",i)
Hello: 1
Hello: 3
Hello: 5

字符串遍历循环

1
2
3
4
5
6
7
for c in s: 
<语句块>
#s是字符串,遍历字符串每个字符,产生循环

>>> for c in "Python123":
print(c, end=",")
P,y,t,h,o,n,1,2,3,

列表遍历循环

1
2
3
4
5
6
7
8
for item in ls  : 
<语句块>
#ls是一个列表,遍历其每个元素,产生循环

for item in [123, "PY", 456] :
print(item, end=",")

123,PY,456,

文件遍历循环

1
2
3
4
5
6
7
8
9
for line in fi  : 
<语句块>
#fi是一个文件标识符,遍历其每行,产生循环

for line in fi :
print(line)
优美胜于丑陋
明了胜于隐晦
简洁胜于复杂

当for循环正常执行之后,程序会继续执行else语句中内容。else语句只在循环正常执行之后才执行并结束,因此,可以在<语句块2>中放置判断循环执行情况的语句。

1
2
3
4
5
6
7
8
9
10
for s in "BIT":
print("循环进行中: " + s)
else:
s = "循环正常结束"
print(s)
>>> 
循环进行中: B
循环进行中: I
循环进行中: T
循环正常结束

无限循环while语句

无限循环:无限循环一直保持循环操作直到特定循环条件不被满足才结束,不需要提前知道确定循环次数。

Python通过保留字while实现无限循环,使用方法如下:

while <条件>:
<语句块>语句块

无限循环也有一种使用保留字else的扩展模式:

while <条件>:
<语句块1>
else:
<语句块2>

1
2
3
4
5
6
7
8
9
10
11
12
s, idx = "BIT", 0
while idx < len(s):
print("循环进行中: " + s[idx])
idx += 1
else:
s = "循环正常结束"
print(s)
>>> 
循环进行中: B
循环进行中: I
循环进行中: T
循环正常结束

循环保留字break和continue

循环结构有两个辅助保留字:break和continue,它们用来辅助控制循环执行

break用来跳出最内层for或while循环,脱离该循环后程序从循环后代码继续续执行

其中,break语句跳出了最内层for循环,但仍然继续执行外层循环。每个break语句只有能力跳出当前层次循环

1
2
3
4
5
6
7
for s in "BIT":
for i in range(10):
print(s, end="")
if s=="I":
break
>>> 
BBBBBBBBBBITTTTTTTTTT

continue用来结束当前当次循环,即跳出循环体中下面尚未执行的语句,但不跳出当前循环。

对于while循环,继续求解循环条件。而对于for循环,程序流程接着遍历循环列表

对比continue和break语句,如下

1
2
3
4
5
6
7
8
9
10
11
12
13
for s in "PYTHON":
if s=="T":
continue
print(s, end="")
>>> 
PYHON

for s in "PYTHON":
if s=="T":
break
print(s, end="")
>>> 
PY

for循环和while循环中都存在一个else扩展用法。

else中的语句块只在一种条件下执行,即for循环正常遍历了所有内容没有因为break或return而退出。

continue保留字对else没有影响。看下面两个例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
for s in "PYTHON":
if s=="T":
continue
print(s, end="")
else:
print("正常退出")
>>>PYHON正常退出

for s in "PYTHON":
if s=="T":
break
print(s, end="")
else:
print("正常退出")
>>>PY

time库基本介绍

time库是Python中处理时间的标准库:计算机时间的表达、提供获取系统时间并格式化输出功能、提供系统级精确计时功能,用于程序性能分析

1
2
import time
time.<b>()

time库包括三类函数:

时间获取:time() ctime() gmtime()

时间格式化:strftime() strptime()

程序计时:sleep(), perf_counter()

时间获取

image.png

random库的使用

随机数在计算机应用中十分常见,Python内置的random库主要用于产生各种分布的伪随机数序列。random库采用梅森旋转算法(Mersenne twister)生成伪随机数序列,可用于除随机性要求更高的加解密算法外的大多数工程应用。

使用random库主要目的是生成随机数,因此,读者只需要查阅该库的随机数生成函数,找到符合使用场景的函数使用即可。这个库提供了不同类型的随机数函数,所有函数都是基于最基本的random.random()函数扩展而来。

random库解析

生成随机数之前可以通过seed()函数指定随机数种子,随机种子一般是一个整数,只要种子相同,每次生成的随机数序列也相同。这种情况便于测试和同步数据。

1
2
3
4
5
6
7
8
>>>seed(125) # 随机种子赋值125
>>>"{}.{}.{}".format(randint(1,10),randint(1,10),randint(1,10))
'4.4.10'
>>>"{}.{}.{}".format(randint(1,10),randint(1,10),randint(1,10))
'5.10.3'
>>>seed(125) # 再次给随机种子赋值125
>>>"{}.{}.{}".format(randint(1,10),randint(1,10),randint(1,10))
'4.4.10'

image.png

π的计算

π(圆周率)是一个无理数,即无限不循环小数。精确求解圆周率π是几何学、物理学和很多工程学科的关键。

对π的精确求解曾经是数学历史上一直难以解决的问题之一,因为π无法用任何精确公式表示,在电子计算机出现以前,π只能通过一些近似公式的求解得到,直到1948年,人类才以人工计算方式得到π的808位精确小数。

随着计算机的出现,数学家找到了另类求解π的另类方法:蒙特卡罗方法,又称随机抽样或统计试验方法。当所要求解的问题是某种事件出现的概率,或者是某个随机变量的期望值时,它们可以通过某种“试验”的方法,得到这种事件出现的频率,或者这个随机变数的平均值,并用它们作为问题的解。这就是蒙特卡罗方法的基本思想。

应用蒙特卡罗方法求解π的基本步骤如下:随机向单位正方形和圆结构,抛洒大量“飞镖”点。计算每个点到圆心的距离从而判断该点在圆内或者圆外。用圆内的点数除以总点数就是π/4值。随机点数量越大,越充分覆盖整个图形,计算得到的π值越精确。实际上,这个方法的思想是利用离散点值表示图形的面积,通过面积比例来求解π值。

image.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#e6.1CalPi.py
from random import random
from math import sqrt
from time import clock
DARTS = 10000
hits = 0.0
clock()
for i in range(DARTS):
x, y = random(), random()
dist = sqrt(x ** 2 + y ** 2)
if dist <= 1.0:
hits = hits + 1
pi = 4 * (hits/DARTS)
print("Pi值是{}.".format(pi))
print("运行时间是: {:5.5}s".format(clock()))

>>> 
Pi值是3.144
运行时间是: 0.016477s

异常处理机制

异常处理try-except语句

观察下面这段小程序:

1
2
num=eval(input("请输入一个整数: "))
print(num**2)

当用户输入的不是数字呢?

1
2
3
4
5
6
7
8
9
10
>>> 
请输入一个整数: 100
10000
>>> 
请输入一个整数: No
Traceback (most recent call last):
File "D:/PythonPL/echoInt.py", line 1, in <module>
num = eval(input("请输入一个整数: "))
File "<string>", line 1, in <module>
NameError: name 'No' is not defined

Python解释器返回了异常信息,同时程序退出

Python异常信息中最重要的部分是异常类型,它表明了发生异常的原因,也是程序处理异常的依据。

Python使用try-except语句实现异常处理,基本的语法格式如下:

try:
<语句块1>
except <异常类型>:
<语句块2>

1
2
3
4
5
6
7
8
try:
num = eval(input("请输入一个整数: "))
print(num**2)
except NameError:
print("输入错误,请输入一个整数!")
>>> 
请输入一个整数: NO
输入错误,请输入一个整数!

异常的高级用法

try-except语句可以支持多个except语句,语法格式如下:

try:
<语句块1>
except <异常类型1>:
<语句块2>
….
except <异常类型N>:
<语句块N+1>
except:
<语句块N+2>

注意顺序,从具体到一般

最后一个except语句没有指定任何类型,表示它对应的语句块可以处理所有其他异常。这个过程与if-elif-else语句类似,是分支结构的一种表达方式,一段代码如下

1
2
3
4
5
6
7
8
try:
alp = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
idx = eval(input("请输入一个整数: "))
print(alp[idx])
except NameError:
print("输入错误,请输入一个整数!")
except:
print("其他错误")

该程序将用户输入的数字作为索引从字符串alp中返回一个字符,当用户输入非整数字符时,except NameError异常被捕获到,提示升用户输入类型错误,当用户输入数字不在0到25之间时,异常被except捕获,程序打印其他错误信息,执行过程和结果如下:

1
2
3
4
5
6
>>> 
请输入一个整数: NO
输入错误,请输入一个整数!
>>> 
请输入一个整数: 100
其他错误

除了try和except保留字外,异常语句还可以与else和finally保留字配合使用,语法格式如下:

try:
<语句块1>
except <异常类型1>:
<语句块2>
else:
<语句块3>
finally:
<语句块4>

image.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#采用else和finally修改代码如下
try:
alp = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
idx = eval(input("请输入一个整数: "))
print(alp[idx])
except NameError:
print("输入错误,请输入一个整数!")
else:
print("没有发生异常")
finally:
print("程序执行完毕,不知道是否发生了异常")

#执行过程和结果如下
>>> 
请输入一个整数: 5
F
没有发生异常
程序执行完毕,不知道是否发生了异常
>>> 
请输入一个整数: NO
输入错误,请输入一个整数!
程序执行完毕,不知道是否发生了异常

课堂讲解代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
for i in range(10):
print(i)
if i == 5:
i = 8

a=[7,4,5,6,2,3,1]
for index,number in enumerate(a):
print(index,number)

sample={'name':'王大锤','age':20,'school':'清华大学'}
for i in sample:
print(i) # 只打印key
for i in sample.items():
print(i) # 打印key和value
for i in sample.values():
print(i) # 只打印value

years=[2020,2021,2022,2023,2024,2025]
scores=[600,601,602,603,604,605]
for i in zip(years,scores):
print(i)

sentiment = [1,0,1,0,1,0]
for i in zip(years,scores,sentiment):
print(i)
# zip()函数可以将多个可迭代对象打包成一个元组的列表,返回一个zip对象

sentiment = ['kaixin','shangxin','kaixin','shangxin']
for i in zip(years,scores,sentiment):
print(i)

import time
start=time.perf_counter()
# 列表推导式
squares=[x**2 for x in range(1000000)]
squares=map(lambda x:x**2,[x for x in range(1000000)])
print(time.perf_counter()-start)
squares=map(lambda x:x**2,[x for x in range(20)])
print(list(squares))

numbers=[1,2,3,4,5,6]
# 筛选出偶数并平方
result=map(lambda x:x**2,filter(lambda x:x%2==0,numbers))
print(list(result)) # [4,16,36]

循环

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
s,idx ="BIT",0
while idx < len(s):
print("循环进行中:"+ s[idx])
idx += 1
else:
s="循环正常结束"
print(s)
'''
循环进行中:B
循环进行中:I
循环进行中:T
循环正常结束
'''

for s in "BIT":
for i in range(10):
print(s,end="")
if s=="I":
break #跳出当前循环,当前循环结束
#BBBBBBBBBBITTTTTTTTTT

for s in "PYTHON":
if s=="T":
continue
print(s,end="")#PYHON

for s in "PYTHON":
if s=="T":
break
print(s,end="")#PY

时间

1
2
3
4
5
6
7
8
9
10
11
12
13
import time
print(time.time())#从1970年1月1日到现在的秒数
start=time.time()
end=time.time()
print(end-start)#输入这两行代码的时间差

import time
time.strptime('2025-04-08 20:12:30','%Y-%m-%d %H:%M:%S')#将字符串转换为时间元组
#time.struct_time(tm_year=2025, tm_mon=4, tm_mday=8, tm_hour=20, tm_min=12, tm_sec=30, tm_wday=2, tm_yday=98, tm_isdst=-1)#将时间元组转换为字符串
time.perf_counter()#返回一个浮点数,表示当前时间的秒数
start=time.perf_counter()
end=time.perf_counter()
print(end-start) #返回时间差

random

1
2
3
4
5
6
7
8
9
10
11
12
import random
random.seed(15)# 生成随机数种子
random.random()# 生成随机数

import random
random.random()
random.random()*100# 生成随机数
random.randint(0,100)# 生成随机整数
random.uniform(0,100)# 生成随机浮点数
lis=[1,2,3,4,5,6,7,8,9,10]
random.choice(lis)
random.shuffle(lis)# 打乱列表顺序

平均身高课堂练习

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import random
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei'] # 或者使用其他支持中文的字体
plt.rcParams['axes.unicode_minus'] = False

# 生成 10000 个身高(单位:cm),假设身高在 150-200 cm 之间,均匀分布
population_height = [random.uniform(150, 200) for _ in range(10000)]

# 抽样 1000 次,每次抽取 10 人,计算平均身高
average_heights = []
for _ in range(1000):
sample = random.sample(population_height, 10)
avg_height = sum(sample) / len(sample)
average_heights.append(avg_height)

# 画直方图
plt.figure(figsize=(10, 6))
plt.hist(average_heights, bins=30, edgecolor='black')
plt.title("1000次抽样的10人平均身高分布")
plt.xlabel("平均身高 (cm)")
plt.ylabel("频度")
plt.grid(axis='y', linestyle='--', alpha=0.7)
plt.tight_layout()
plt.show()

蒙特卡洛方法算π课堂练习

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import random
import matplotlib.pyplot as plt

def estimate_pi(num_points):
inside_circle = 0
x_in, y_in = [], []
x_out, y_out = [], []

for _ in range(num_points):
x = random.uniform(0, 1)
y = random.uniform(0, 1)

if x**2 + y**2 <= 1:
inside_circle += 1
x_in.append(x)
y_in.append(y)
else:
x_out.append(x)
y_out.append(y)

pi_estimate = (inside_circle / num_points) * 4

# 可视化
plt.figure(figsize=(6,6))
plt.scatter(x_in, y_in, color='blue', s=1, label='Inside Quarter Circle')
plt.scatter(x_out, y_out, color='red', s=1, label='Outside Quarter Circle')
plt.title(f'Estimated π = {pi_estimate:.6f} (using {num_points} points)')
plt.legend()
plt.xlabel("x")
plt.ylabel("y")
plt.axis("square")
plt.show()

return pi_estimate

# 示例:使用 100000 个随机点估算 π
estimated_pi = estimate_pi(100000)
print(f"Estimated π: {estimated_pi}")

异常处理

1
2
3
4
5
try:
num=eval(input("请输入一个整数: "))
print(num**2)
except NameError:
print("输入错误,请输入一个整数")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def test_finally_override():
try:
print("try块执行")
return "来自try的返回值"
except:
print("except块执行")
finally:
print("finally块执行")

result = test_finally_override()
print("最终返回值:",result)

'''
try块执行
finally块执行
最终返回值: 来自try的返回值
'''
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def test_finally_override():
try:
print("try块执行")
return "来自try的返回值"
except:
print("except块执行")
finally:
print("finally块执行")
return "来自finally的返回值"

result = test_finally_override()
print("最终返回值:",result)

'''
try块执行
finally块执行
最终返回值: 来自finally的返回值
'''
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def test_finally_with_loop():
for i in range(3):
try:
if i == 1:
break #尝试提前退出循环
print(f"循环第{i}次")
finally:
print(f"finally执行(i={i})")

test_finally_with_loop()

'''
循环第0次
finally执行(i=0)
finally执行(i=1)
'''
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
try:
num=eval(input("请输入一个整数: "))
print(num**2)
except:
print("输入错误,请输入一个整数")

else:
print("现在是else")
finally:
print("现在是finally")

'''
请输入一个整数: 2
4
现在是else
现在是finally
'''

'''
请输入一个整数: n
输入错误,请输入一个整数
现在是finally
'''

函数和代码复用

函数的基本使用

函数的定义:函数是一段代码的表示

函数是一段具有特定功能的、可重用的语句组

函数是一种功能的抽象,表达特定功能

两个作用:降低编程难度和代码复用

def  <函数名>(<参数(0个或多个)>) :

<函数体>

return

<返回值>

函数定义时,所指定的参数是一种占位符

函数定义后,如果不经过调用,不会被执行

函数定义时,参数是输入、函数体是处理、结果是输出(IPO)

函数的调用过程

调用是运行函数代码的方式

调用时要给出实际参数,实际参数替换定义中的参数,函数调用后得到返回值

1
2
3
4
5
6
def fact(n):#函数的定义
S=1
for i in range(1, n+1):
S*=i
return S
fact(10)

image.png

函数的参数传递

参数个数:函数可以有参数,也可以没有,但必须保留括号

def <函数名>():

<函数体>

return <返回值>

def fact():

print(“我也是函数")

可选参数传递

函数定义时可以为某些参数指定默认值,构成可选参数(可选参数必须在后边,否则在调用时会引起混乱)

def <函数名>(<非可选参数>,<可选参数>):
<函数体>
return <返回值>

1
2
3
4
5
6
7
8
9
10
11
#计算n!//m
def fact(n,m=1):
S=1
for i in range(1,n+1):
S*=i
return s//m

>>> fact(10)
3628800
>>> fact(10,5)
725760

可变参数传递

函数定义时可以设计可变数量参数,既不确定参数总数量

def <函数名>(<参数>, *b):

 <函数体>

 return <返回值>

带星号的参数必须出现在参数列表最后通过元组类型接收多个值(0个也可!)

1
2
3
4
5
6
7
8
9
10
11
12
#计算n!乘数
def fact(n,*b):#b为可变参数
S=1
for i in range(1, n+1):
S*=i
for item in b:
s*= item
return s
>>>fact(10,3)
10886400
>>>fact(10,3,5,8)
435456000

参数传递的两种方式:函数调用时,参数可以按照位置或名称方式传递

image.png

Python中的可变参数

关键词位置可变参数*args

1

关键词可变参数kwargs**

1
2
3
def show info(**kwargs):
for key, value in kwargs.items():
print(f"{key} = {value}")

位置可变、关键词可变组合使用(考试会考)

1
2
3
4
5
6
def demo(a,b,*args,c=0,**kwargs):#参数,可变参数,可变位置参数,默认参数,关键词可变参数
print(f"a={a},b={b},c={c},args={args},kwargs={kwargs}")

def fact(a,b=1,*c,**d):
return True
fact(3,2,123,456,789,name='wangdachui')

函数的返回值

函数可以返回0个或多个结果,return保留字用来传递返回值。

函数可以有返回值,也可以没有,可以有return,也可以没有return可以传递0个返回值,也可以传递任意多个返回值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def fact():
return 1,2,3,"a","b",[4,5,6],(7,8,9),{'name':'wangdachui','age':18}

def fact():
return 1,2,3

>>>fact()
(1,2,3)
>>>fact()[1]
2
>>>fact()[0:2]
(1,2)
>>>fact()
(1,2,3)
>>>a,b,c = fact()
>>>a
1
>>>b
2
>>>c
3
1
2
3
4
5
6
7
8
9
10
11
def fact(n,m=1):
S=1
for i in range(1,n+1):
S*=i
return s//m,n,m

>>>fact(10,5)
(725760,10,5)
>>> a,b,c=fact(10,5)
>>> print(a,b,c)
725760 10 5

高阶函数:返回函数

1
2
3
4
5
def create_adder(x):
def adder(y):
return x+y
Add5 = create adder(5)
print(add5(3))

提前返回,实现安全验证

1
2
3
4
5
6
7
8
def divide(a,b):
if b==0:
returnFalse
return a/b

def count up(n):
for i in range(n):
yield i

返回None

1
2
3
4
5
6
return None

Return

Def A:
pass

注意可变参数的返回

1
2
3
4
5
6
7
8
9
10
11
12
def append_item(lst=[]):
lst.append(1)
return lst

>>>append_item()
[1]
>>>append_item()
[1,1]
>>>append_item()
[1,1,1]
>>>append_item()
[1,1,1,1]

Python迭代器

Map Filter Yield 返回的皆是迭代器

迭代器是一个可以逐个产出元素的对象,迭代器只能往前,不能后退。

符合两个基本方法:iter_()可选代、next_0可不断取下一个值

直到结束,抛出Stoplteration异常

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
>>> def fact():
yield [1,2,3,4,5,6,7]
>>> def fact1():
return [1,2,3,4,5,6,7]
>>> fact()
<generator object fact at 0x100db6380>
>>> fact1()
[1,2,3,4,5,6,7]
>>>fact()
<generator object fact at 0x100db6380>
>>> fact().next()
Traceback(most recent call last):File "<stdin>",line 1,in <module>AttributeError:'generator'object has no attribute 'next'
>>> next(fact())
[1234567]
>>> lsss =[1,2,3,4,5,6]
>>> iter(lsss)
<list_iterator object at 0x100efd300>

局部变量和全局变量

<语句块1>

def <函数名>(<参数>):

   <函数体>

   return<返回值>

<语句块2>

规则1:局部变量和全局变量是不同变量

局部变量是函数内部的占位符,与全局变量可能重名但不同。函数运算结束后,局部变量被释放。可以使用global保留字在函数内部使用全局变量。

1
2
3
4
5
6
7
8
9
10
11
n,s=10100
def fact(n):
s=1
#fact()函数中s是局部变量,与全局变量s不同
for i in range(1,n+1):
s*=i
return s #此处局部变量s是3628800
print(fact(n),s) #此处全局变量s是100

>>
3628800 100

规则2:局部变量为组合数据类型且未创建,等同于全局变量

1
2
3
4
5
6
7
8
9
ls =["F","f"] #通过使用"真实创建了一个全局变量列表ls
def func(a):
ls.append(a) #此处ls是列表类型,未真实创建,则等同于全局变量
return
func("c") #全局变量ls被修改
print(ls)

>>>
['F','f','c']

lambda函数

<函数名>= lambda<参数>:<表达式>

def <函数名>(<参数>):

   <函数体>
   return<返回值>

lambda函数返回函数名作为结果

lambda函数是一种匿名函数,即没有名字的函数。使用lambda保留字定义,函数名是返回结果。lambda函数用于定义简单的、能够在一行内表示的函数

1
2
3
4
5
>>>f= lambda x,y:x+y
>>>f(10,15)
25
>>>f= lambda:"lambda函数"
>>> print(f())

lambda函数主要用作一些特定函数或方法的参数

lambda函数有一些固定使用方式,建议逐步掌握

一般情况,建议使用def定义的普通函数

七段数码管绘制

七段数码管绘制时间

步骤1:绘制单个数字对应的数码管

七段数码管由7个基本线条组成,七段数码管可以有固定顺序,不同数字显示不同的线条

image.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import turtle
def drawLine(draw): #绘制单段数码管
turtle.pendown() if draw else turtle.penup()
turtle.fd(40)
turtle.right(90)
def drawDigit(digit): #根据数字绘制七段数码管
drawLine(True) if digit in [2,3,4,5,6,8,9] else drawLine(False)
drawLine(True) if digit in [0,1,3,4,5,6,7,8,9] else drawLine(False)
drawLine(True) if digit in [0,2,3,5,6,8,9] else drawLine(False)
drawLine(True) if digit in [0,2,6,8] else drawLine(False)
turtle.left(90)
drawLine(True) if digit in [0,4,5,6,8,9] else drawLine(False)
drawLine(True) if digit in [0,2,3,5,6,7,8,9] else drawLine(False)
drawLine(True) if digit in [0,1,2,3,4,7,8,9] else drawLine(False)
turtle.left(180)
turtle.penup() #为绘制后续数字确定位置
turtle.fd(20) #为绘制后续数字确定位置

步骤2:获得一串数字,绘制对应的数码管

image.png

image.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import turtle
def drawLine(draw): #绘制单段数码管
…(略)
def drawDigit(digit): #根据数字绘制七段数码管
…(略)
def drawDate(date): #获得要输出的数字
for i in date:
drawDigit(eval(i)) #通过eval()函数将数字变为整数
def main():
turtle.setup(800, 350, 200, 200)
turtle.penup()
turtle.fd(-300)
turtle.pensize(5)
drawDate('20181010')
turtle.hideturtle()
turtle.done()
main()

增加七段数码管之间线条间隔

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import turtle
def drawGap(): #绘制数码管间隔
turtle.penup()
turtle.fd(5)
def drawLine(draw): #绘制单段数码管
drawGap()
turtle.pendown() if draw else turtle.penup()
turtle.fd(40)
drawGap()
turtle.right(90)
def drawDigit(digit): #根据数字绘制七段数码管
drawLine(True) if digit in [2,3,4,5,6,8,9] else drawLine(False)
drawLine(True) if digit in [0,1,3,4,5,6,7,8,9] else drawLine(False)
drawLine(True) if digit in [0,2,3,5,6,8,9] else drawLine(False)
drawLine(True) if digit in [0,2,6,8] else drawLine(False)
…(略)

步骤3:获得系统时间,绘制对应的数码管

使用datetime库获得系统当前时间,增加年月日标记,年月日颜色不同

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import turtle, time
…(略)
def drawDate(date): #data为日期,格式型如'2023-03=24+'
turtle.pencolor("red")
for i in date:
if i == '-':
turtle.write('年',font=("Arial", 18, "normal"))
turtle.pencolor("green")
turtle.fd(40)
elif i == '=':
turtle.write('月',font=("Arial", 18, "normal"))
turtle.pencolor("blue")
turtle.fd(40)
elif i == '+':
turtle.write('日',font=("Arial", 18, "normal"))
else:
drawDigit(eval(i))
def main():
…(略)
1
2
3
4
5
6
7
8
9
10
11
12
13
import turtle, time
…(略)
def drawDate(date):
…(略)
def main():
turtle.setup(800, 350, 200, 200)
turtle.penup()
turtle.fd(-300)
turtle.pensize(5)
drawDate(datetime.datetime.now().strftime('%Y-%m=%d+'))
turtle.hideturtle()
turtle.done()
main()

image.png

函数的递归

函数定义中调用函数自身的方式

image.png

类似数学归纳法

两个关键特征:

链条:计算过程存在递归链条;基例:存在一个或多个不需要再次递归的基例

如何实现?

1
2
3
4
def fact(n):    if n == 0 :
return 1
else:
return n*fact(n-1)

函数 + 分支语句

递归本身是一个函数,需要函数定义方式描述

函数内部,采用分支语句对输入参数进行判断

基例和链条,分别编写对应代码

image.png

函数递归实例解析

(1)字符串反转

将字符串s反转后输出:s[::-1]

1
2
3
4
5
def rvs(s):    
if s == "" :
return s
else :
return rvs(s[1:])+s[0]

经典的上台阶问题:给定整数N,代表台阶数,一次可以跨2个或者1个台阶,返回有多少种走法。

斐波那契数列:

image.png

1
2
3
4
5
6
7
def f(n):    
if n == 1:
return 1
elif n == 2:
return 2
else:
return f(n-1) + f(n-2)

汉诺塔:

1
2
3
4
5
6
7
8
9
10
11
12
count = 0
def hanoi(n,src,mid,dst):
global count
if n == 1:
print("{}->{}".format(src,dst))
count += 1
else :
hanoi(n-1,src,dst,mid)
hanoi(1,src,mid,dst)
hanoi(n-1,mid,src,dst)
hanoi(3, "A", "B", "C")
print(count)

image.png

Python第三次作业

1.鸡兔同笼

有若干只鸡兔同在一个笼子里,从上面数,有35个头,从下面数,有94只脚,问笼中各有多少只鸡和兔?‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬

请编一个程序,用户在同一行内输入两个整数,代表头和脚的数量,编程计算笼中各有多少只鸡和兔(假设鸡和兔都正常,无残疾)。如无解则输出“Data Error!‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬”‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬

输入格式‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬

输入为一行,以空格分隔的两个整数h f,分别代表鸡兔的总头数和总脚数。‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬

输出格式‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬

使用输入值进行计算,如有解,则输出:有m只鸡,n只兔;如无解则输出Data Error!‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬

1
2
3
4
5
6
7
h, f = map(int, input().split())
if f % 2 != 0 or f < 2 * h or f > 4 * h:
print("Data Error!")
else:
n = (f - 2 * h) // 2 # 兔的数量
m = h - n # 鸡的数量
print(f"有{m}只鸡,{n}只兔")

2.存款买房(B)

你刚刚大学毕业,在北京找到了一份很好的工作,决定开始存钱买房。由于北京的房价很高,你要攒几年钱才能付得起房子的首付。‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬

现根据以下假定来计算你需要多长时间才能攒够首付款:‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬

1.将你想购买的房子的总价称为total_cost。‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬

2.将首付款占总房价的比例称为portion_down_payment。为简单起见,假设portion_down_payment = 0.30(30%)。‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬

3.将存款金额称为current_savings。你的存款从0元开始。‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬

4.假设你的年薪是annual_salary,按12个月平均发放,单位是元。‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬

5.假设你每个月都要拿出一定百分比的工资来存首付。称为portion_saved,此值为一个表示百分比的整数,例如50表示50%。‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬

6.假定你每6个月加一次工资,每半年加薪比例semi_annual_raise是一个表示百分比的整数,例如7表示7%,即第7个月的月初涨一次工资,工资涨幅为7%,以后每过6个月再涨一次工资。‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬

写一个程序来计算你需要多少个月才能攒够钱付定金,不足一个月按一个月计算。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
total_cost = float(input())  # total_cost为当前房价
annual_salary = float(input()) # 年薪
portion_saved = float(input()) / 100
# 月存款比例,输入30转为0.30(即30%)
semi_annual_raise = float(input()) / 100
# 输入每半年加薪比例,输入7转化为0.07(即7%)
portion_down_payment = 0.3

# 首付比例,浮点数

# 根据首付款比例计算首付款down_payment
# =======================================================
def down_payment():
down_payment = total_cost * portion_down_payment
return down_payment

# =======================================================
down_payment = down_payment()
print('首付', down_payment)

current_savings = 0
# 存款金额,从0开始
number_of_months = 1

monthly_salary = annual_salary / 12 #月工资
monthly_deposit = monthly_salary * portion_saved #月存款

# 总共缴纳房款

# 计算多少个月才能存够首付款,结果为整数,不足1月按1个月计算,即向上取整
# 每6个月涨一次工资,每年输出年底的存款总额
# =======================================================
def print_current(number_of_months, monthly_salary, semi_annual_raise, monthly_deposit):
enough = True
current_saving = 0
while enough:
current_saving = current_saving + monthly_deposit # 发工资了,先给自己存一笔
if current_saving >= down_payment: # 存够了买房去
print(f'需要{number_of_months}个月可以存够首付')
enough = False
return
if number_of_months % 12 == 0:
print("第{}个月月末有{:,.0f}元存款".format(number_of_months, current_saving)) # 每12个月输出一次存款,保留0位小数,使用千分符
if number_of_months % 6 == 0:
monthly_deposit = monthly_deposit * (1 + semi_annual_raise) # 六月之期已到,加薪
number_of_months = number_of_months + 1

# =======================================================
print_current(number_of_months, monthly_salary, semi_annual_raise, monthly_deposit)

# 计算存款总额

3.素数问题

描述‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬

素数或称质数,是指一个大于1的整数,除1和它本身外,不能被其他的正整数所整除。 素数判定方法是: 先用一定的方法枚举正整数n所有可能的真因子,并验证每个枚举的数是否为真因子。若是,则停止枚举,确定n为合数;若枚举完也没发现真因子,可确定n为素数。完成以下函数的定义并按要求完成问题:‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬

  1. 定义素数函数is_ prime(n) 将素数的判定代码定义为一个函数,接受用户输入的正整数n,返回n是否是素数,n为素数时返回True,不是素数时返回False。 一个整数若可以进行因数分解,那么分解时得到的两个数一定是一个小于等于sqrt(n),一个大于等于sqrt(n),所以对于每个数n,并不需要从2判断到n-1,只需要遍历到sqrt(n)即可。因为若sqrt(n)左侧找不到因数,那么右侧也一定找不到因数,这样可以显著提升算法的效率。‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬
  2. 定义一个函数output_prime(n),接受一个正整数number为参数,在函数中调用问题1中定义的判定素数函数,对不大于number的整数一一判定,在同一行中输出不大于n的全部素数。此函数无返回值,直接输出找到的素数。 调用all_prime(n)函数前,先接收用户输入的一个正整数,作为函数调用时的参数。‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬
  3. 定义寻找回文素数函数 回文是指数或者字符串具有首尾回环性质,从后向前按位颠倒后与原文一样。首尾回环的数字就是回文数,如:12321;首尾回环的字符串就是回文串,如:’上海自来水来自海上’。 如果一个整数是素数,同时,其对应的字符串是回文字符串时,便称其为回文素数。 编写一个函数,调用前面定义好的素数判定函数和题目给定的回文判定函数完成回文素数的判定,函数无返回值,直接输出找到的回文素数。 输入一个正整数,输出小于这个数的所有回文素数。‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬
  4. 寻找反素数 反素数是指一个将其逆向拼写后也是一个素数的非回文数。例如:17和71都是素数且均不是回文数,所以17和71都是反素数。 输入一个正整数n,按从小到大顺序输出所有反素数。‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬
  5. 哥德巴赫猜想1742年,哥德巴赫给欧拉的信中提出了以下猜想“任意一个大于2的整数都可写成三个质数之和”。常见的猜想陈述为欧拉的版本,即任意一个大于2的偶数都可写成两个素数之和,亦称为“强哥德巴赫猜想”或“关于偶数的哥德巴赫猜想”。 编写函数,接收一个大于2的偶数,输出两个素数,并且两个素数之和等于原来的偶数,如果有多个不同组合,则全部输出。若输入的数不是大于2的偶数,输出’Data error!’‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬

输入输出‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬

问题1 如果输入’素数’,再输入一个正整数n,按从小到大顺序输出不大于n的所有素数。‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬

问题2 如果输入’回文素数’,再输入一个正整数n,按从小到大顺序输出小于n的所有回文素数。‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬

问题3 如果输入’反素数’,再输入一个正整数n,输入一个正整数n,按从小到大顺序输出小于n的所有反素数。‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬

问题4 如果输入’哥德巴赫猜想’,接收一个大于2的偶数,输出两个素数,并且两个素数之和等于原来的偶数,如果有多个不同组合,则全部输出,格式参考下面的示例。若输入的数不是大于2的偶数,输出’Data error!’‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬

如果输入不是以上字符串,输出’输入错误’。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
def question_judge(question):
"""接收一个字符串为参数,根据参数值判断问题类型,调用合适的函数进行操作。"""
if question == '素数': # 如果输入素数,再输入一个正整数n,输出不大于n的所有素数
n = int(input())
output_prime(n) # 输出素数
elif question == '回文素数':
n = int(input())
palindromic_prime(n) # 输出回文素数
elif question == '反素数':
n = int(input())
reverse_prime(n) # 输出反素数
elif question == '哥德巴赫猜想':
n = int(input())
goldbach_conjecture(n)
else:
print('输入错误')

def is_prime(n):
"""判断素数的函数,接收一个正整数为参数,参数是素数时返回True,否则返回False
减小判定区间,减少循环次数,提升效率"""
if n < 2:
return False
for i in range(2,int(n**0.5+1)):
if n % i == 0:
return False
else:
return True

def output_prime(number):
"""接收一个正整数为参数,遍历从0到number之间的所有整数
在一行中输出不大于number的所有素数,函数无返回值"""
for i in range(number+1):
if is_prime(i)==True:
print(i,end=' ')

def palindromic(num):
"""接收一个数字为参数,判定其是否为回文数,返回布尔值。"""
return str(num) == str(num)[::-1]

def palindromic_prime(number):
"""接收一个正整数参数number,遍历从0到number之间的所有整数,
若某个数是素数,且转为字符串后是回文字符串,则称其为回文素数
找出并在同一行中从小到大输出小于number的所有回文素数,各数字间用一个空格分隔,
函数无返回值"""
for i in range(number+1):
if palindromic(i)==True and is_prime(i)==True:
print(i,end=' ')

def reverse_num(num):
"""接收一个整数,返回其逆序字符串对应的整数"""
return int(str(num)[::-1])

def reverse_prime(number):
"""接收一个正整数参数,找出并在同一行内输出所有小于number的反素数,数字间用一个空格分隔。
反素数指某数i及其逆序数都是素数,但数i对应的字符串不是回文字符串
函数无返回值"""
for i in range(number):
if palindromic(i)==False and is_prime(i)==True and is_prime(reverse_num(i))==True :
print(i,end=' ')

def goldbach_conjecture(num):
""" 哥德巴赫猜想, 接收一个不小于4的正整数为参数。
当参数为不小于4的偶数时,将其分解为两个素数的加和,按小数+数的格式输出。
有多种组合时全部输出,但不输出重复的组合,例如输出8=3+5,不输出8=5+3。
参数为奇数或小于4时,输出'Data error!'
"""
if num %2==0 and num>=4:
for i in range(2,(num//2)+1):
if is_prime(i)==True and is_prime(num-i)==True:
print(f"{num}={i}+{num-i}")
else:
print("Data error!")

if __name__ == '__main__':
problems = input()
question_judge(problems)

4.用户登录的三次机会

给用户三次输入用户名和密码的机会,要求如下:‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬

  1. 如输入第一行输入用户名为 ‘Kate’,第二行输入密码为 ‘666666’,输出 ‘登录成功!’,退出程序;
  2. 当一共有 3 次输入用户名或密码不正确输出 “3次用户名或者密码均有误!退出程序。”。
1
2
3
4
5
6
7
8
9
10
11
12
correct_username = 'Kate'
correct_password = '666666'

for attempt in range(3):
username = input().strip()
password = input().strip()

if username == correct_username and password == correct_password:
print("登录成功!")
break
else:
print("3次用户名或者密码均有误!退出程序。")

5.多输入数字求和

获取用户输入一批数字,每个数字一行,即输入一个数字之后回车在下一行输入下一个数字,最后以空回车为结束(即空输入)。‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬

计算这批数字的和。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
total = 0
while True:
s = input()
if s == '':
break
try:
#支持二/八/十六进制整数和十进制整数、浮点数
if s.lower().startswith(('0x','0o','0b')):
num = int(s,0)
elif '.' in s or 'e' in s.lower():
num = float(s)
else:
num = int(s)
total += num
except ValueError:
print(f"输入无效:{s}")
print(total)

6.随机字符串

输入两个整数,以它们的和为随机数种子,并在32-127之间(含)随机产生20个整数。‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬

以这些数字为Unicode码产生字符,并将组成字符串输出。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import random

# 获取输入并解析为两个整数
input_str = input()
a, b = map(int, input_str.split(','))

# 计算种子并设置随机种子
seed = a + b
random.seed(seed)

# 生成20个32-127之间的随机数并转换为字符
result = []
for i in range(20):
num = random.randint(32, 127)
result.append(chr(num))

# 组合成字符串并输出
output = ''.join(result)
print(output)

7.汉诺塔实践

汉诺塔问题大家都清楚,这里不再赘述。‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬

请补充编程模板中代码,完成如下功能:‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬

有三个圆柱A、B、C,初始时A上有N个圆盘,N由用户输入给出,最终移动到圆柱C上。‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬

每次移动步骤的表达方式示例如下:[STEP 10] A->C。其中STEP是步骤序号,宽度为4个字符,右对齐。‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬

请编写代码,获得输入N后,输出汉诺塔移动的步骤。

1
2
3
4
5
6
7
8
9
10
11
12
13
steps = 0
def hanoi(src, des, mid, n):
global steps
if n == 1:
steps += 1
print("[STEP{:>4}] {}->{}".format(steps, src, des))
else:
hanoi(src, mid, des, n-1)
steps += 1
print("[STEP{:>4}] {}->{}".format(steps, src, des))
hanoi(mid, des, src, n-1)
N = eval(input())
hanoi("A", "C", "B", N)

8.英文单词个数统计

给出一个字符串s,内容参见”编程模板”,请统计并打印字符串s中出现单词的个数。

1
2
3
4
5
6
7
s = '''
"Collusion is very real with Russia," Trump quoted conservative commentator Dan Bongino as saying on Trump's favorite Fox News morning show, "but only with Hillary and the Democrats, and we should demand a full investigation."
'''
def count_words(text):
words = text.split() #默认按空格分割,并自动去除空字符串
return len(words)
print(count_words(s))

组合数据类型

组合数据类型概述

组合数据类型

计算机不仅对单个变量表示的数据进行处理,更多情况,计算机需要对一组数据进行批量处理。一些例子包括:
给定一组单词{python, data, function, list, loop},计算并输出每个单词的长度;
给定一个学院学生信息,统计一下男女生比例;
一次实验产生了很多组数据,对这些大量数据进行分析;

组合数据类型能够将多个同类型或不同类型的数据组织起来,通过单一的表示使数据操作更有序更容易。根据数据之间的关系,组合数据类型可以分为三类:序列类型、集合类型和映射类型。

序列类型是一个元素向量,元素之间存在先后关系,通过序号访问,序列中元素值可以不唯一。

集合类型是一个元素集合,元素之间无序,相同元素在集合中唯一存在。

映射类型是“键-值”数据项的组合,每个元素是一个键值对,表示为(key, value)。

image.png

集合类型

*定义

集合是多个元素的无序组合,集合元素可以是:整数、浮点数、字符串、元组;不可以是:列表、集合、字典。

集合类型与数学中的集合概念一致

集合元素之间无序,每个元素唯一,不存在相同元素

集合元素不可更改,不能是可变数据类型

集合用大括号 {} 表示,元素间用逗号分隔

建立集合类型用 {} 或 set():set的参数必须为可迭代的数据类型

建立空集合类型,必须使用set():如果写成{},Python解释器认为是空字典而不是空集合

1
2
3
4
5
6
>>> A = {"python", 123, ("python",123)}  #使用{}建立集合
{123, 'python', ('python', 123)}
>>> B = set("pypy123") #使用set()建立集合
{'1', 'p', '2', '3', 'y'}
>>> C = {"python", 123, "python",123}
{'python', 123}

*集合间操作

image.png

image.png

image.png

1
2
3
4
5
6
7
8
9
10
11
12
>>> A = {"p", "y" , 123} 
>>> B = set("pypy123")
>>> A-B
{123}
>>> B-A
{'3', '1', '2'}
>>> A&B
{'p', 'y'}
>>> A|B
{'1', 'p', '2', 'y', '3', 123}
>>> A^B
{'2', 123, '3', '1'}

*集合处理方法

image.png

image.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> A = {"p", "y" , 123} 
>>> for item in A:
print(item, end="")
p123y
>>> A
{'p', 123, 'y'}
>>> try:
while True:
print(A.pop(), end=""))
except:
pass
p123y
>>> A
set()

*集合类型应用场景

(1)包含关系比较

1
2
3
4
>>> "p" in {"p", "y" , 123}
True
>>> {"p", "y"} >= {"p", "y" , 123}
False

(2)数据去重:集合类型所有元素无重复

1
2
3
4
5
>>> ls = ["p", "p", "y", "y", 123]
>>> s = set(ls) # 利用了集合无重复元素的特点
{'p', 'y', 123}
>>> lt = list(s) # 还可以将集合转换为列表
['p', 'y', 123]

序列类型

序列类型是一维元素向量,元素之间存在先后关系,通过序号访问。当需要访问序列中某特定值时,只需要通过下标标出即可。

由于元素之间存在顺序关系,所以序列中可以存在相同数值但位置不同的元素。序列类型支持成员关系操作符(in)、长度计算函数(len())、分片([]),元素本身也可以是序列类型。

Python语言中有很多数据类型都是序列类型,其中比较重要的是:str(字符串)、tuple(元组)、list(列表)。

元组是包含0个或多个数据项的不可变序列类型。元组生成后是固定的,其中任何数据项不能替换或删除。列表则是一个可以修改数据项的序列类型,使用也最灵活。

image.png

序列类型有12个通用的操作符和函数

image.png

元组类型定义

(1)元组是序列类型的一种扩展

元组是一种序列类型,一旦创建就不能被修改

使用小括号 () 或 tuple() 创建,元素间用逗号,分隔可以使用或不使用小括号

1
2
3
4
5
6
7
8
9
def func():
return 1,2

>>> creature = "cat", "dog", "tiger", "human"
>>> creature
('cat', 'dog', 'tiger', 'human')
>>> color = (0x001100, "blue", creature)
>>> color
(4352, 'blue', ('cat', 'dog', 'tiger', 'human'))

(2)元组继承序列类型的全部通用操作

元组继承了序列类型的全部通用操作

元组因为创建后不能修改,因此没有特殊操作

1
2
3
4
5
6
>>> creature = "cat", "dog", "tiger", "human"
>>> creature[::-1]
('human', 'tiger', 'dog', 'cat')
>>> color = (0x001100, "blue", creature)
>>> color[-1][2]
'tiger'

列表类型定义

*列表是序列类型的一种扩展,十分常用

列表是一种序列类型,创建后可以随意被修改

使用方括号[]或list()创建,元素间用逗号,分隔使用list()创建列表,参数必须为可迭代的数据类型

列表中各元素类型可以不同,无长度限制

1
2
3
4
5
6
>>> ls = ["cat", "dog", "tiger", 1024]
>>> ls
['cat', 'dog', 'tiger', 1024]
>>> lt = ls
>>> lt
['cat', 'dog', 'tiger', 1024]

image.png

*列表类型操作函数和方法

image.png

1
2
3
4
5
6
7
>>> ls = ["cat", "dog", "tiger", 1024]
>>> ls[1:2] = [1, 2, 3, 4]
['cat', 1, 2, 3, 4, 'tiger', 1024]
>>> del ls[::3]
[1, 2, 4, 'tiger']
>>> ls*2
[1, 2, 4, 'tiger', 1, 2, 4, 'tiger']

image.png

1
2
3
4
5
6
7
>>> ls = ["cat", "dog", "tiger", 1024]
>>> ls.append(1234)
['cat', 'dog', 'tiger', 1024, 1234]
>>> ls.insert(3, "human")
['cat', 'dog', 'tiger', 'human', 1024, 1234]
>>> ls.reverse()
[1234, 1024, 'human', 'tiger', 'dog', 'cat']

*列表功能默写

image.png

image.png

基本统计值计算

以最简单的统计问题为例,求解一组不定长数据的基本统计值,即平均值、标准差、中位数。

一组数据表示为S=s0, s1, …, sn-1,其算术平均值、标准差分别表示为:

image.png

由于平均数、标准差和中位数是三个不同的计算目标,使用函数方式编写计算程序。

getNum()函数从用户输入获得数据、mean()函数计算平均值、dev()函数计算标准差、median()函数计算中位数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#e9.1CalStatistics.py
from math import sqrt
def getNum(): #获取用户输入
nums = []
iNumStr = input("请输入数字(直接输入回车退出): ")
while iNumStr != "":
nums.append(eval(iNumStr))
iNumStr = input("请输入数字(直接输入回车退出): ")
return nums
def mean(numbers): #计算平均值
s = 0.0
for num in numbers:
s = s + num
return s / len(numbers)
def dev(numbers, mean): #计算方差
sdev = 0.0
for num in numbers:
sdev = sdev + (num - mean)**2
return sqrt(sdev / (len(numbers)-1))
def median(numbers): #计算中位数
new=sorted(numbers) #sorted函数,返回列表排序结果
size = len(numbers)
if size % 2 == 0:
med = (new[size//2-1] + new[size//2])/2
else:
med = new[size//2]
return med
n = getNum() #主体函数
m = mean(n)
print("平均值:{},方差:{:.2},中位数:{}.".format(m,\dev(n,m),median(n)))

>>> 
请输入数字(直接输入回车退出): 99
请输入数字(直接输入回车退出): 98
请输入数字(直接输入回车退出): 97
请输入数字(直接输入回车退出): 96
请输入数字(直接输入回车退出): 95
请输入数字(直接输入回车退出):
平均值:97.0,方差:1.6,中位数:97.

程序先后调用getNum()、mean()、dev()和median()函数。利用函数的模块化设计能够复用代码并增加代码的可读性。每个函数内部都采用了简单的语句。

列表在实现基本数据统计时发挥了重要作用,表现在:列表是一个动态长度的数据结构,可以根据需求增加或减少元素;列表的一系列方法或操作符为计算提供了简单的元素运算手段;列表提供了对每个元素的简单访问方式及所有元素的遍历方式。

字典

字典类型定义

理解“映射”:(1)映射是一种键(索引)和值(数据)的对应

image.png

image.png

image.png

(2)字典类型是“映射”的体现

键值对:键是数据索引的扩展

字典是键值对的集合,键值对之间无序

采用大括号{}和dict()创建,键值对用冒号: 表示{<键1>:<值1>,<键2>:<值2>, … ,<键n>:<值n>}

字典类型的用法

在字典变量中,通过键获得值

image.png

1
2
3
4
5
6
7
>>> d = {"中国":"北京", "美国":"华盛顿", "法国":"巴黎"}
>>> d
{'中国': '北京', '美国': '华盛顿', '法国': '巴黎'}
>>> d["中国"]
'北京'
>>> de = {} ; type(de) #type(x):返回变量x的类型
<class 'dict'>

字典处理函数及方法

image.png

1
2
3
4
5
6
7
>>> d = {"中国":"北京", "美国":"华盛顿", "法国":"巴黎"}
>>> "中国" in d
True
>>> d.keys()
dict_keys(['中国', '美国', '法国'])
>>> d.values()
dict_values(['北京', '华盛顿', '巴黎'])

image.png

1
2
3
4
5
6
7
>>> d = {"中国":"北京", "美国":"华盛顿", "法国":"巴黎"}
>>> d.get("中国","伊斯兰堡")
'北京'
>>> d.get("巴基斯坦","伊斯兰堡")
'伊斯兰堡'
>>> d.popitem()
('美国', '华盛顿')

*字典功能默写

image.png

*字典类型应用场景

(1)映射的表达

映射无处不在,键值对无处不在

例如:统计数据出现的次数,数据是键,次数是值

最主要作用:表达键值对数据,进而操作它们

(2)元素遍历

image.png

(3)统计某个特征的数量、构建树形结构、配置文件

image.png

jieba库的使用

分词

分词的目的,就是把中文文本按照词语切分开

(1)基于规则的分词

正向最大匹配(FMM):南京市长江大桥

逆向最大匹配(RMM):研究生命的起源

双向最大匹配:结婚的和尚未结婚的

(2)基于统计额分词:基于N-Gram模型的分词

(3)基于深度学习的分词:序列标注任务

(4)混合方法:多种方法一起用

jieba是Python中一个重要的第三方中文分词函数库,jieba库是第三方库,不是安装包自带,需要通过pip指令安装。

1
2
3
>>>import jieba
>>>jieba.lcut("中国是一个伟大的国家")
['中国', '是', '一个', '伟大', '的', '国家']

jieba库的解析

分词冗余度:全模式 > 搜索引擎模式 > 精确模式

image.png

1
2
3
4
5
6
7
>>>import jieba
>>>jieba.lcut("中华人民共和国是一个伟大的国家")
['中华人民共和国', '是', '一个', '伟大', '的', '国家']
>>>jieba.lcut("中华人民共和国是一个伟大的国家", cut_all=True)
['中华', '中华人民', '中华人民共和国', '华人', '人民', '人民共和国', '共和', '共和国', '国是', '一个', '伟大', '的', '国家']
>>>jieba.lcut_for_search("中华人民共和国是一个伟大的国家")
['中华', '华人', '人民', '共和', '共和国', '中华人民共和国', '是', '一个', '伟大', '的', '国家']

关键词提取

(1)TF-IDF算法

TF(term frequency)为词频,指给定单词在文档中出现的频率。

IDF(inverse document frequency)为倒文档词频,表示包含给定单词的文档数量的倒数

TF与IDF的乘积是单词与文档之间相关性的一种有效度量

image.png

image.png

基于TF-IDF算法

image.png

(2)TextRank算法

TextRank是一种图排序算法,基于PageRank的思想,将文本中的词语看作图中的节点,通过词语共现关系构建边,迭代计算节点权重(重要性)。

关键词提取:将句子中的词语作为节点,用窗口内共现关系构建边,权重由共现次数决定。

image.png

基于TextRank算法

image.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import jieba

#读文本文件
def read_text(file_path):
with open(file_path, 'r', encoding='utf-8') as f:
text = f.read()
return text

#提取n-gram
def get_ngrams(text,n=2):
words = [ word for word in jieba.lcut(text) if len(word) > 1] #分词
words = [ item for item in words if item !=" "] #去除空格
ngrams = zip(*[words[i:] for i in range(n)]) #生成n-gram
return [''.join(ngram) for ngram in ngrams] #返回n-gram列表

文本词频统计

需求:一篇文章,出现了哪些词?哪些词出现得最多?该怎么做呢?

英文文本:Hamet 分析词频

https://python123.io/resources/pye/hamlet.txt

中文文本:《三国演义》分析人物

https://python123.io/resources/pye/threekingdoms.txt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#CalHamletV1.py
def getText():
txt = open("hamlet.txt", "r").read()
txt = txt.lower()
for ch in '!"#$%&()*+,-./:;<=>?@[\\]^_‘{|}~':
txt = txt.replace(ch, " ")
return txt

hamletTxt = getText()
words = hamletTxt.split()
counts = {}
for word in words:
counts[word] = counts.get(word,0) + 1
items = list(counts.items())
items.sort(key=lambda x:x[1], reverse=True)
for i in range(10):
word, count = items[i]
print("{0:<10}{1:>5}".format(word, count))

>>> 
the 1138
and 965
to 754
of 669
you 550
a 542
i 542
my 514
hamlet 462
in 436

文本去噪及归一化,使用字典表达词频。

sort方法,列表排序。key参数指定排序关键字。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#e10.2CalHamlet.py
excludes = {"the","and","of","you","a","i","my","in"}
def getText():
txt = open("hamlet.txt", "r").read()
txt = txt.lower()
for ch in '!"#$%&()*+,-./:;<=>?@[\\]^_‘{|}~':
txt = txt.replace(ch, " ") #将文本中特殊字符替换为空格
return txt
hamletTxt = getText()
words = hamletTxt.split()
counts = {}
for word in words:
counts[word] = counts.get(word,0) + 1
for word in excludes:
del counts[word]
items = list(counts.items())
items.sort(key=lambda x:x[1], reverse=True)
for i in range(10):
word, count = items[i]
print("{0:<10}{1:>5}".format(word, count))

>>> 
to 754
hamlet 462
it 416
that 391
is 340
not 314
lord 309
his 296
this 295
but 269

《三国演艺》人物出现次数统计

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#CalThreeKingdomsV1.py
import jieba
txt = open("threekingdoms.txt", "r", encoding="utf-8").read()
words = jieba.lcut(txt)
counts = {}
for word in words:
if len(word) == 1: #把单字去掉,古文中2字及以上的大概率是人名
continue
else:
counts[word] = counts.get(word,0) + 1
items = list(counts.items())
items.sort(key=lambda x:x[1], reverse=True)
for i in range(15):
word, count = items[i]
print("{0:<10}{1:>5}".format(word, count))

>>>
曹操 953
孔明 836
将军 772
却说 656
玄德 585
关公 510
丞相 491
二人 469
不可 440
荆州 425
玄德曰 390
孔明曰 390
不能 384
如此 378
张飞 358

观察输出结果,同一个人物会有不同的名字,这种情况需要整合处理。同时,与英文词频统计类似,需要排除一些人名无关词汇,如“却说”、“将军”等。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#e10.4CalThreeKingdoms.py
import jieba
excludes = {"将军","却说","荆州","二人","不可","不能","如此"}
txt = open("三国演义.txt", "r", encoding='utf-8').read()
words = jieba.lcut(txt)
counts = {}
for word in words:
if len(word) == 1:
continue
elif word == "诸葛亮" or word == "孔明曰":
rword = "孔明"
elif word == "关公" or word == "云长":
rword = "关羽"
elif word == "玄德" or word == "玄德曰":
rword = "刘备"
elif word == "孟德" or word == "丞相":
rword = "曹操”
else:
rword = word
counts[rword] = counts.get(rword,0) + 1
for word in excludes:
del(counts[word])
items = list(counts.items())
items.sort(key=lambda x:x[1], reverse=True)
for i in range(5):
word, count = items[i]
print("{0:<10}{1:>5}".format(word, count))

输出排序前5的单词,运行程序后,输出结果如下

1
2
3
4
5
6
>>> 
曹操 1451
孔明 1383
刘备 1252
关羽 784
张飞 358

文件和数据格式化

文件的使用

文件的理解

(1)文件是数据的抽象和集合:文件是存储在辅助存储器上的数据序列、文件是数据存储的一种形式、文件展现形态:文本文件和二进制文件

(2)文本文件 vs. 二进制文件:文件文件和二进制文件只是文件的展示方式、本质上,所有文件都是二进制形式存储、形式上,所有文件采用两种方式展示

(3)文件是数据的抽象和集合:由单一特定编码组成的文件,如UTF-8编码、由于存在编码,也被看成是存储着的长字符串、适用于例如:.txt文件、.py文件等、直接由比特0和1组成,没有统一字符编码、一般存在二进制0和1的组织结构,即文件格式、适用于例如:.png文件、.avi文件等

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#f.txt文件保存: 中国是个伟大的国家!
#文本形式打开文件
tf = open("f.txt", "rt", encoding="utf-8")
print(tf.readline())
tf.close()
>>>
中国是个伟大的国家!

#二进制形式打开文件
bf = open("f.txt", "rb")
print(bf.readline())
bf.close()
>>>
b'\xe4\xb8\xad\xe5\x9b\xbd\xe6\x98\xaf\xe4\xb8\xaa\xe4\xbc\x9f\xe5\xa4\xa7\xe7\x9a\x84\xe5\x9b\xbd\xe5\xae\xb6\xef\xbc\x81'
(UTF-8编码,每个中文为3字节)

文件的打开关闭

image.png

文件的打开

image.png

文件路径

image.png

打开模式

image.png

image.png

文件的关闭

image.png

文件内容的读取

文件内容的读取

image.png

image.png

文件的全文本操作

image.png

image.png

文件的逐行操作

image.png

image.png

数据的文件写入

image.png

image.png

image.png

image.png

数据组织的维度

image.png

image.png

image.png

image.png

image.png

image.png

image.png

一维数据

(1)表示

a.如果数据间有序:使用列表类型

ls = [3.1398, 3.1349, 3.1376]

列表类型可以表达一维有序数据、for循环可以遍历数据,进而对每个数据进行处理

b.如果数据间无序:使用集合类型

st = {3.1398, 3.1349, 3.1376}

集合类型可以表达一维无序数据、for循环可以遍历数据,进而对每个数据进行处理

(2)存储

image.png

image.png

image.png

(3)处理

image.png

image.png

image.png

image.png

image.png

二维数据

(1)表示

image.png

image.png

image.png

(2)CSV格式与二维数据存储

国际通用的一二维数据存储格式,一般.csv扩展名。每行一个一维数据,采用逗号分隔,无空行。Excel和一般编辑软件都可以读入或另存为csv文件。

image.png

如果某个元素缺失,逗号仍要保留。二维数据的表头可以作为数据存储,也可以另行存储。逗号为英文半角逗号,逗号与数据之间无额外空格。

按行存?按列存?

按行存或者按列存都可以,具体由程序决定。一般索引习惯:ls[row][column],先行后列。根据一般习惯,外层列表每个元素是一行,按行存。

(3)处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 从CSV格式的文件中读入数据
fo = open(fname)
ls = []
for line in fo:
line = line.replace("\n","")
ls.append(line.split(",")) fo.close()

# 将数据写入CSV格式的文件
ls = [[], [], []] #二维列表
f = open(fname, 'w')
for item in ls:
f.write(','.join(item) + '\n') f.close()

# 采用二层循环
ls = [[1,2], [3,4], [5,6]] #二维列表
for row in ls:
for column in row:
print(column)

CSV格式的HTML展示

image.png

高维数据的格式化

与一维二维数据不同,高维数据能展示数据间更为复杂的组织关系。为了保持灵活性,表示高维数据不采用任何结构形式,仅采用最基本的二元关系,即键值对。
JSON格式可以对高维数据进行表达和存储。JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于阅读和理解。JSON格式表达键值对<key, value>的基本格式如下,键值对都保存在双引号中:”key” : “value”

当多个键值对放在一起时,JSON有如下一些约定:数据保存在键值对中;键值对之间由逗号分隔;大括号用于保存键值对数据组成的对象;方括号用于保存键值对数据组成的数组。

Json里的对象——>Python里的字典、Json里的数组——>Python里的列表

json库的使用

image.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
>>>dt = {'b':2,'c':4,'a':6}
>>>s1 = json.dumps(dt) #dumps返回JSON格式的字符串类型
>>>s2 = json.dumps(dt,sort_keys=True,indent=4)
>>>print(s1)
{"c": 4, "a": 6, "b": 2}
>>>print(s2)
{
"a": 6,
"b": 2,
"c": 4
}
>>>print(s1==s2)
False
>>>dt2 = json.loads(s2)
>>>print(dt2, type(dt2))
{'c': 4, 'a': 6, 'b': 2} <class 'dict'>

Python数据分析

image.png

读取数据并可视化、异常数据检测、数据预测KNN

Python第四次作业

1.文件关键行数

关键行指一个文件中包含的不重复行。关键行数指一个文件中包含的不重复行的数量。‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬统计附件文件中与关键行的数量。

1
2
3
with open('latex.log','r',encoding='utf-8') as f:
rows_set = set(f.readlines())
print('共{}关键行'.format(len(rows_set)))

2.字典翻转输出

读入一个字典类型的字符串,反转其中键值对输出。‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬即读入字典key:value模式,输出value:key模式。‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬

用户输入的字典格式的字符串,如果输入不正确,提示:输入错误。‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬

给定字典d,按照print(d)方式输出

1
2
3
4
5
6
7
8
d=eval(input())
if type(d)!=dict:
print('输入错误')
else:
c={}
for k in d:
c[d[k]]=k
print(c)

3.模拟决赛现场最终成绩的计算‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬

【功能要求】编写程序,模拟决赛现场最终成绩的计算过程。首先输入评委人数,要求判断评委不得少于5人;然后依次输入评委的成绩,成绩范围应在[0,100]。在所有评委的分数中,去掉一个最高分、去掉一个最低分,剩余成绩求算术平均分,作为选手的最终成绩。‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
while True:
try:
n=int(input('请输入评委人数:'))
if n<5:
print('评委人数太少,必须至少五个人')
else:
break
except:
pass
scores=[]

for i in range(n):
while True:
try:
score=input("请输入第{0}个评委的分数".format(i+1))
score=float(score)
assert 0<=score<=100
scores.append(score)
break
except:
print("分数错误")
highest=max(scores)
lowest=min(scores)
scores.remove(highest)
scores.remove(lowest)
final=round(sum(scores)/len(scores),2)
formatter='去掉一个最高分{0}去掉一个最低分{1}最终得分是{2}'
print(formatter.format(highest,lowest,final))

# 可扩展多位选手成绩的数据可视化
import matplotlib.pyplot as plt
import numpy as np
# 设置中文字体显示
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False
# 生成随机数据
x = np.arange(1, n+1)
y = np.random.randint(60, 100, size=n)
# 绘制柱状图
plt.bar(x, y)
# 添加标题和标签
plt.title('选手成绩')
plt.xlabel('选手')
plt.ylabel('分数')
# 显示图形
plt.show()

4.jieba库分词

‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪txt表示一段中文文本,请补充代码,输出该文本所有可能的分词结果。

1
2
3
4
import jieba
txt = "中华人民共和国教育部考试中心委托专家制定了全国计算机等级考试二级程序设计考试大纲"
ls = jieba.lcut(txt,cut_all=True)
print(ls)

5.CSV格式数据清洗

附件是一个CSV文件,其中每个数据前后存在空格,请对其进行清洗,要求如下:‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬去掉每个数据前后空格,即数据之间仅用逗号 (,) 分割;清洗后打印输出。

1
2
3
4
with open('data.csv','r') as f:
for line in f:
line = line.replace(' ','')
print(line,end='')

面向对象程序设计

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
class Person:
name = 'unknown'
age = 0
jiguan = 'unknown'

p1= Person()
p2= Person()
print(p1.name)

p1.name = 'wangdachui'
print(p1.name)
print(p2.name)

p2.aihao = 'zhoujielun'
print(p2.aihao)
print(p1.aihao)

print(p1.age)
print(p2.age)
print(id(p1.age),id(p2.age))

class Student:
name='Unknown'
def SetName(self,newname):
self.name=newname
def PrintName(self):
print('姓名:%s'%self.name)
if __name__ == '__main__':
stu1=Student()
stu2=Student()
stu1.SetName('zhangsan')
stu2.SetName('lisi')
stu1.PrintName()
stu2.PrintName()

print(stu1.name)
print(stu2.name)
stu3 = Student()
print(stu3.name)

class Student:
def Setinfo(self, newname, newid):
self.name = newname
self.id = newid
def PrintInfo(self):
print(self.name, self.id)
stu = Student()
stu.Setinfo('王大锤','1231231234567')

stu.PrintInfo()
print(stu.id)
print(stu.__id)

面向对象概述

面向对象是当前流行的程序设计方法,其以人类习惯的思维方式,用对象来理解和分析问题空间,使开发软件的方法与过程尽可能接近人类认识世界、解决问题的思维方法与过程。

面向对象方法的基本观点是一切系统都是由对象构成的,每个对象都可以接收并处理其他对象发送的消息,它们的相互作用、相互影响,实现了整个系统的运转。

类和对象的概念:类和对象是面向对象程序设计的两个重要概念。

类和对象的关系即数据类型与变量的关系,根据一个类可以创建多个对象,而每个对象只能是某一个类的对象。

类规定了可以用于存储什么数据,而对象用于实际存储数据,每个对象可存储不同的数据。

image.png

类的定义和创建实例

类的定义:

在一个类中,除了可以包含前面所说的属性,还可以包含各种方法。属性对应一个类可以用来保存哪些数据,而方法对应一个类可以支持哪些操作(即数据处理)。

类的定义形式多样:

我们既可以直接创建新的类,也可以基于一个或多个已有的类创建新的类;我们既可以创建一个空的类,然后再动态添加属性和方法,也可以在创建类的同时设置属性和方法。

封装性:

类中的属性对应前面所学习的变量,而类中的方法对应前面所学习的函数。通过类,可以把数据和操作封装在一起,从而使得程序结构更加清晰,这也就是所谓的类的封装性。

image.png

image.png

提示:每次创建对象时,系统都会在内存中选择一块区域分配给对象,每次选择的内存通常是不一样的。因此,实际运行时会看到一个不同的stu对象地址。

类属性定义及其访问

image.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 例:创建Student类对象
class Student: #定义Student类
name='Unknown' #定义Student类中有一个name属性
if __name__=='__main__':
print('第4行输出: ',Student.name)
stu1=Student() #创建Student类对象stu1
stu2=Student() #创建Student类对象stu2
print('第7行输出: stu1 %s,stu2 %s'%(stu1.name,stu2.name))
Student.name='未知' #将Student的类属性name赋为“未知”
print('第9行输出: ',Student.name)
print('第10行输出: stu1 %s,stu2 %s'%(stu1.name,stu2.name))
# 类属性的访问示例
stu1.name='李晓明' #将stu1的name属性赋值为“李晓明”
stu2.name='马红' #将stu2的name属性赋值为“马红”
print('第13行输出: ',Student.name)
print('第14行输出: stu1 %s,stu2 %s'%(stu1.name,stu2.name))
Student.name='学生' #将Student的类属性name赋为“学生”
print('第16行输出: ',Student.name)
print('第17行输出: stu1 %s,stu2 %s'%(stu1.name,stu2.name))

#第4行输出: Unknown
#第7行输出: stu1 Unknown,stu2 Unknown
#第9行输出: 未知
#第10行输出: stu1 未知,stu2 未知
#第13行输出:未知
#第14行输出: stu1 李晓明,stu2 马红
#第16行输出:学生
#第17行输出: stu1 李晓明,stu2 马红

为对象动态绑定新属性

Python作为一种动态语言,除了可以在定义类时指定类属性外,还可以动态地为已经创建的对象绑定新的属性。

例:为对象动态绑定新属性示例。

1
2
3
4
5
6
7
8
9
1    class Student: #定义Student类
2 name='Unknown' #定义Student类中有一个name属性
3 if __name__=='__main__':
4 stu1=Student() #定义Student类对象stu1
5 stu2=Student() #定义Student类对象stu2
6 stu1.age=19 #为对象stu1动态绑定新的属性age
7 print('stu1姓名: %s,年龄: %d'%(stu1.name,stu1.age)) #输出姓名和年龄
8 #print('stu2年龄: '%stu2.age) #取消注释则该语句会报错
9 #print('使用类名访问年龄属性: '%Student.age) #取消注释则该语句会报错

类中普通方法定义及调用

类中的方法实际上就是执行某种数据处理功能的函数。与普通函数定义一样,类中的方法在定义时也需要使用def 关键字。

类中的方法分为两类:普通方法和内置方法。普通方法需要通过类的实例对象根据方法名调用;内置方法是在特定情况下由系统自动执行。

普通方法定义和调用

在定义类的普通方法时,要求第一个参数需要对应调用方法时所使用的实例对象(一般命名为self,但也可以改为其他名字)。

当使用一个实例对象调用类的普通方法时,其语法格式为:实例对象名.方法名(实参列表)

提示:在通过类的实例对象调用类中的普通方法时,并不需要传入self参数的值,self会自动对应调用该方法时所使用的对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#例:类中普通方法定义及调用示例
1 class Student: #定义Student类
2 name='Unknown' #定义Student类中有一个name属性
3 def SetName(self, newname): #定义类的普通方法SetName
4 self.name=newname #将self对应实例对象中的name属性值赋为newname
5 def PrintName(self): #定义类的普通方法PrintName
6 print('姓名: %s'%self.name) #输出self对应实例对象中的name属性值
7 if __name__=='__main__':
8 stu1=Student() #定义Student类对象stu1
9 stu2=Student() #定义Student类对象stu2
10 stu1.SetName('李晓明') #通过stu1对象调用SetName方法
11 stu2.SetName('马红') #通过stu1对象调用SetName方法
12 stu1.PrintName() #通过stu1对象调用PrintName方法
13 stu2.PrintName() #通过stu2对象调用PrintName方法

image.png

私有属性

私有属性,是指在类内可以直接访问、而在类外无法直接访问的属性

Python中规定, 在定义类时,如果一个类属性名是以__ (两个下划线) 开头,则该类属性为私有属性。

1
2
3
4
5
6
7
8
9
10
11
12
13
class Student: #定义Student类                                                                  
name='未知' #定义Student类中有一个name属性
__id='未知' #定义Student类中有一个__id私有属性
def SetInfo(self,newname,newid): #定义SetInfo方法
self.name=newname #将self对应实例对象的name属性赋为newname
self.__id=newid #将self对应实例对象的__id属性赋为newid
def PrintInfo(self): #定义PrintInfo函数
print('姓名: %s,身份证号: %s'%(self.name,self.__id))
if __name__=='__main__':
stu=Student() #定义Student类对象stu
stu.SetInfo('李晓明','120XXXXXXXXXXXXXXX') #通过stu调用 #SetInfo方法
stu.PrintInfo() #通过stu对象调用PrintInfo方法
#print('身份证号: %s'%stu.__id) #取消前面的注释,则程序会报错

类中的方法本质上就是前面所学习的函数,因此,类中的方法也可以有默认参数值。

例如,可以将第4行代码修改为:def SetInfo(self,newname,newid=’Unknown’): #定义SetInfo方法

将第9行代码修改为:stu.SetInfo(‘李晓明’) #通过stu调用SetInfo方法

构造方法

构造方法是Python类中的内置方法之一, 它的方法名为_init_,在创建一个类对象时会自动执行,负责完成新
创建对象的初始化工作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 只有一个参数的构造方法示例
1 class Student: #定义Student类
2 def __init__(self): #定义构造方法
3 print('构造方法被调用! ')
4 self.name='未知' #将self对应对象的name属性赋值为“未知”
5 def PrintInfo(self): #定义普通方法PrintInfo
6 print('姓名: %s'%self.name) #输出姓名信息
7 if __name__=='__main__':
8 stu=Student() #创建Student类对象stu,自动执行构造方法
9 stu.PrintInfo() #通过stu对象调用PrintInfo方法

#输出:
构造方法被调用!
姓名:未知
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 带默认参数的构造方法示例
1 class Student: #定义Student类
2 def __init__(self,name='未知'): #定义构造方法
3 print('构造方法被调用! ')
4 self.name=name #将self对应对象的name属性赋为形 #参name的值
5 def PrintInfo(self): #定义普通方法PrintInfo
6 print('姓名: %s'%self.name) #输出姓名信息
7 if __name__=='__main__':
8 stu1=Student() #创建Student类对象stu1自动执行构造方法
9 stu2=Student('李晓明')
10 stu1.PrintInfo() #通过stu1对象调用PrintInfo方法
11 stu2.PrintInfo() #通过stu1对象调用PrintInfo方法

#输出:
构造方法被调用!
构造方法被调用!
姓名:未知
姓名:李晓明

析构方法

析构方法是类的另一个内置方法,它的方法名为__del__ ,在销毁一个类对象时会自动执行,负责完成待销毁对象的资源清理工作,如关闭文件等。

提示:类对象销毁有如下三种情况:

(1)局部变量的作用域结束。(2)使用del删除对象。(3)程序结束时,程序中的所有对象都将被销毁。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#析构方法示例
1 class Student: #定义Student类
2 def __init__(self,name): #定义构造方法
3 self.name=name #将self对应对象的name属性 #赋值为形参name的值
4 print('姓名为%s的对象被创建! '%self.name)
5 def __del__(self): #定义析构方法
6 print('姓名为%s的对象被销毁! '%self.name)
7 def func(name):
8 stu=Student(name) #创建Student类对象stu
9 if __name__=='__main__':
10 stu1=Student('李晓明') #创建Student类对象stu1
11 stu2=Student('马红') #创建Student类对象stu2
12 stu3=stu2
13 del stu2 #使用del删除stu2对象
14 func('张刚') #调用func函数
15 del stu3 #使用del删除stu3对象
16 stu4=Student('刘建') #创建Student类对象stu4

#实例:
姓名为李晓明的对象被创建!
姓名为马红的对象被创建!
姓名为张刚的对象被创建!
姓名为张刚的对象被销毁!
姓名为马红的对象被销毁!
姓名为刘建的对象被创建!
姓名为李晓明的对象被销毁!
姓名为刘建的对象被销毁!

注意:如果多个变量对应同一片内存空间, 则只有这些变量都删除后才会销毁这片内存空间中所保存的对象,也才会自动执行 析构方法。

常用内置方法

__str__:调用str函数对类对象进行处理时或者调用Python内置函数format()和print()时自动执行, __str__方法的返回值必须是字符串。

1
2
3
4
5
6
7
8
9
1   class Complex: #定义复数类Complex
2 def __init__(self,real,image): #定义构造方法
3 self.real=real #将self对应对象的real属性赋值为形参 #real的值
4 self.image=image #将self对应对象的image属性赋值 #为形参image的值
5 def __str__(self): #定义内置方法__str__
6 return str(self.real)+'+'+str(self.image)+'i'
7 if __name__=='__main__':
8 c=Complex(3.2,5.3) #定义Complex类对象c
9 print(c) #输出“3.2+5.3i”

image.png

1
2
3
4
5
6
7
8
9
10
11
1   class Student: #定义Student类
2 def __init__(self, name, age): #定义构造方法
3 self.name=name #将self对应对象的name属性赋为形参 #name的值
4 self.age=age #将self对应对象的age属性赋为形参age的值
5 def __le__(self, other): #定义内置方法__le__
6 return self.age<=other.age
7 if __name__=='__main__’:
8 stu1=Student('李晓明',19) #定义Student类对象stu1
9 stu2=Student('马红',20) #定义Student类对象stu2
10 print('马红的年龄小于等于李晓明的年龄: ', stu2<=stu1)
#马红的年龄小于等于李晓明的年龄: False

继承的概念

继承允许开发者基于已有的类创建新的类。

如果一个类C1通过继承已有类C而创建,则将C1称作子类(sub class),将C称做基类、父类或超类(base class、super class)。

子类会继承父类中定义的所有属性和方法,另外也能够在子类中增加新的属性和方法。

如果一个子类只有一个父类,则将这种继承关系称为单继承;如果一个子类有两个或更多父类,则将这种继承关系称为多重继承。

image.png

子类的定义

定义子类时需要指定父类,其语法格式为:

class 子类名(父类名1, 父类名2, …, 父类名M):
语句1
语句2

语句N

当M等于1时,则为单继承;当M大于1时,则为多重继承。例:继承示例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
1          class Person: #定义Person类
2 def SetName(self, name): #定义SetName方法
3 self.name=name #将self对应对象的name属性赋为形参name的值
4 class Student(Person): #以Person类作为父类定义子类Student
5 def SetSno(self, sno): #定义SetSno方法
6 self.sno=sno #将self对应对象的sno属性赋为形参sno的值
7 class Teacher(Person): #以Person类作为父类定义子类Teacher
8 def SetTno(self, tno): #定义SetTno方法
9 self.tno=tno #将self对应对象的tno属性赋为形参tno的值
10 class TA(Student,Teacher): #以Student类和Teacher类作为父类 #定义子类TA
11 def SetTeacher(self, teacher): #定义SetTeacher方法
12 self.teacher=teacher #将self对象的teacher属性赋为形参 #teacher的值
13 if __name__=='__main__':
14 stu=Student() #定义Student类对象stu
15 stu.SetSno('1810100') #调用Student类中定义的SetSno方法
16 stu.SetName('李晓明') #调用Student类从Person类继承过来的SetName #方法
17 print('学号: %s,姓名: %s'%(stu.sno,stu.name)) #输出学号和姓名
18 t=Teacher() #定义Teacher类对象t
19 t.SetTno('998012') #调用Teacher类中定义的SetTno方法
20 t.SetName('马红') #调用Teacher类从Person类继承过来的SetName方法
21 print('教工号: %s,姓名: %s'%(t.tno,t.name)) #输出教工号和姓名

#学号: 1810100,姓名:李晓明
#教工号: 998012,姓名:马红

方法重写和鸭子类型

方法重写:是指子类可以对从父类中继承过来的方法进行重新定义,从而使得子类对象可以表现出与父类对象不同的行为。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Person: #定义Person类
def __init__(self, name): #定义构造方法
self.name=name #将self对象的name属性赋为形参name的值
def PrintInfo(self): #定义PrintInfo方法
print('姓名: %s'%self.name)
class Student(Person): #以Person类作为父类定义子类Student
def __init__(self, sno, name): #定义构造方法
self.sno=sno #将self对象的sno属性赋为形参sno的值
self.name=name #将self对象的name属性赋为形参name的值
def PrintInfo(self): #定义PrintInfo方法
print('学号: %s,姓名: %s'%(self.sno,self.name))
def PrintPersonInfo(person): #定义普通函数PrintPersonInfo
print('PrintPersonInfo函数中的输出结果', end='#')
person.PrintInfo() #通过person调用PrintInfo方法
if __name__=='__main__':
p=Person('李晓明') #创建Person类对象p
stu=Student('1810100','李晓明') #创建Student类对象stu
p.PrintInfo()
stu.PrintInfo()
PrintPersonInfo(p)
PrintPersonInfo(stu)

image.png

鸭子类型:在鸭子类型中,关注的不是对象所属的类,而是一个对象能够如何使用。

在Python中编写一个函数,传递实参前其参数的类型并不确定,在函数中使用形参进行操作时只
要传入的对象能够支持该操作程序就能正常执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1          class Person: #定义Person类
2 def CaptureImage(self): #定义CaptureImage方法
3 print('Person类中的CaptureImage方法被调用! ')
4 class Camera: #定义Camera类
5 def CaptureImage(self): #定义CaptureImage方法
6 print('Camera类中的CaptureImage方法被调用! ')
7 def CaptureImageTest(arg): #定义CaptureImageTest方法
8 arg.CaptureImage() #通过arg调用CaptureImage方法
9 if __name__=='__main__':
10 p=Person() #定义Person类对象p
11 c=Camera() #定义Camera类对象c
12 CaptureImageTest(p)
13 CaptureImageTest(c)

#Person类中的CaptureImage方法被调用!
#Camera类中的CaptureImage方法被调用!

实际上,Python中的多态也是借助鸭子类型实现,与C++、Java等语言中的多态并不是同一含义。
“如果走起来像鸭子,叫起来像鸭子,它就是鸭子!”

super方法

super方法用于获取父类的代理对象,以执行已在子类中被重写的父类方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
1          class Person: #定义Person类
2 def __init__(self, name): #定义构造方法
3 print('Person类构造方法被调用! ')
4 self.name=name #将self对象的name属性赋为形参name的值
5 class Student(Person): #以Person类作为父类定义子类Student
6 def __init__(self, sno, name): #定义构造方法
7 print('Student类构造方法被调用! ')
8 super().__init__(name) #调用父类的构造方法
9 self.sno=sno #将self对象的sno属性赋为形参sno的值
10 class Postgraduate(Student): #以Student类作为父类定义子类Postgraduate
11 def __init__(self, sno, name, tutor): #定义构造方法
12 print('Postgraduate类构造方法被调用! ')
13 super().__init__(sno, name) #调用父类的构造方法
14 self.tutor=tutor #将self对象的tutor属性赋为形参tutor的值
15 if __name__=='__main__':
16 pg=Postgraduate('1810100','李晓明','马红') #创建Postgraduate类对象pg
17 print('学号: %s,姓名: %s,导师: %s'%(pg.sno,pg.name,pg.tutor))

#Postgraduate类构造方法被调用!
#Student类构造方法被调用!
#Person类构造方法被调用!
#学号: 1810100,姓名:李晓明,导师:马红

内置函数isinstance、 issubclass和type

isinstance 用于判断一个对象所属的类是否是指定类或指定类的子类

issubclass 用于判断一个类是否是另一个类的子类

type 用于获取一个对象所属的类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Person: #定义Person类
pass
class Student(Person): #以Person类作为父类定义子类Student
pass
class Flower: #定义Flower类
pass
if __name__=='__main__':
stu=Student() #创建Student类对象stu
f=Flower() #创建Flower对象
print('stu是Person类或其子类对象: ', isinstance(stu,Person))
print('stu是Student类或其子类对象: ', isinstance(stu,Student))
#stu是Person类或其子类对象: True
#stu是Student类或其子类对象: True
print('f是Person类或其子类对象: ', isinstance(f,Person))
print('Student是Person类的子类: ', issubclass(Student,Person))
print('Flower是Person类的子类: ', issubclass(Flower,Person))
#f是Person类或其子类对象: False
#Student是Person类的子类: True
#Flower是Person类的子类: False
print('stu对象所属的类: ', type(stu))
print('f对象所属的类: ', type(f))
print('stu是Person类对象: ', type(stu)==Person)
print('stu是Student类对象: ', type(stu)==Student)
#stu对象所属的类: <class '__main__.Student'>
#f对象所属的类: <class '__main__.Flower'>
#stu是Person类对象: False
#stu是Student类对象: True

如果我们要判断一个对象的类型是否是指定类或该类的子类,则可以使用isinstance函数。
如果我们要判断一个对象的类型是否是指定类,则可以使用“type(对象名)==类名”的方式。

类方法和静态方法

类方法是指使用@classmethod修饰的方法,其第一个参数是类本身,而不是类的实例对象。

类方法的特点是既可以通过类名直接调用,也可以通过类的实例对象调用。

装饰器:

装饰器可以实现在特定条件下为某些函数在不改动函数体的时候为函数新添加一些功能,本质上是一个语法糖

基于@语法和函数闭包,将原函数封装在闭包中,然后将函数赋值为一个新的函数

在不改变函数内部代码和调用的前提下,实现在函数执行拓展功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#类方法
1 class Complex: #定义Complex类
2 def __init__(self,real=0,image=0): #定义构造方法
3 self.real=real #初始化一个复数的实部值
4 self.image=image #初始化一个复数的虚部值
5 @classmethod #必须单写一行
6 def add(cls,c1,c2): #定义类方法add,实现两个复数的加法运算
7 print(cls) #输出cls
8 c=Complex() #创建Complex类对象c
9 c.real=c1.real+c2.real #实部相加
10 c.image=c1.image+c2.image #虚部相加
11 return c
12 if __name__=='__main__':
13 c1=Complex(1,2.5)
14 c2=Complex(2.2,3.1)
15 c=Complex.add(c1,c2) #直接使用类名调用类方法add
16 print('c1+c2的结果为%.2f+%.2fi'%(c.real,c.image))

#<class '__main__.Complex'>
#c1+c2的结果为3.20+5.60i

将第15行的“c=Complex.add(c1,c2) ”改为“c=c1.add(c1, c2) ”或 “c=c2.add(c1, c2)” ,程序运行后可得到相同的输出结果,即类方法也可以使用实例对象调用。

通过“print(cls) ”输出类方法add的第一个参数,从输出结果中可以看到cls是Complex类。

作用:用来使用类的属性或者是给类的属性赋值,可以在类方法中使用cls参数来实现

静态方法:

静态方法是指使用@staticmethod修饰的方法。

与类方法相同, 静态方法既可以直接通过类名调用, 也可以通过类的实例对象调用。

与类方法不同的地方在于,静态方法中没有类方法中的第一个类参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
1          class Complex: #定义Complex类
2 def __init__(self,real=0,image=0): #定义构造方法
3 self.real=real #初始化一个复数的实部值
4 self.image=image #初始化一个复数的虚部值
5 @staticmethod
6 def add(c1,c2): #定义类方法add,实现两个复数的加法运算
7 c=Complex() #创建Complex类对象c
8 c.real=c1.real+c2.real #实部相加
9 c.image=c1.image+c2.image #虚部相加
10 return c
11 if __name__=='__main__':
12 c1=Complex(1,2.5)
13 c2=Complex(2.2,3. 1)
14 c=Complex.add(c1,c2) #直接使用类名调用类方法add
15 print('c1+c2的结果为%.2f+%.2fi'%(c.real,c.image))

#c1+c2的结果为3.20+5.60i

作用:静态方法逻辑上属于类,但是和类本身没有关系,也就是说在静态方法中,不会涉及到类中的属性和方法的操作。可以理解为,静态方法是个独立的、单纯的函数,它仅仅托管于某个类的名称空间中,便于使用和维护。

动态扩展类与实例

动态扩展类与实例:

Python作为一种动态语言,除了可以在定义类时定义属性和方法外,还可以动态地为已经创建的对象绑定新的属性和方法。

给类绑定方法,直接进行赋值即可

在给对象绑定方法时,需要使用types模块中的MethodType函数,其第一个参数是要绑定的函数名,第二个参数是绑定的对象名。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1          from types import MethodType #从types模块中导入MethodType函数
2 class Student: #定义学生类
3 pass
4 def SetName(self,name): #定义SetName函数
5 self.name=name
6 def SetSno(self,sno): #定义SetSno函数
7 self.sno=sno
8 if __name__=='__main__':
9 stu1=Student() #定义Student类对象stu1
10 stu2=Student() #定义Student类对象stu2
11 stu1.SetName=MethodType(SetName,stu1)#为stu1对象绑定SetName方法
12 Student.SetSno=SetSno #为Student类绑定SetSno方法
13 stu1.SetName('李晓明')
14 stu1.SetSno('1810100')
15 #stu2.SetName('张刚') #取消注释则会报错
16 stu2.SetSno('1810101')

提示:给一个对象绑定方法后,只能通过该对象调用该方法,其他未绑 定该方法的对象则不能调用。例如,没有为stu2对象绑定SetName方法,因此,如果将第15行前面的注释符取消,则程序运行时系统会报错。
而第12行为Student类绑定了SetSno方法,则Student类中的所有实例对象都有该方法。

@property装饰器

类中的属性可以直接访问和赋值,这为类的使用者提供了方便,但也带来了问题:类的使用者可能会给一个属性赋上超出有效范围的值。

为了解决这个问题, Python提供了@property装饰器,可以将类中属性的访问和赋值操作自动转为方法调用,这样可以在方法中对属性值的取值范围做一些条件限定。

直接使用@property就可以定义一个用于获取属性值的方法(即getter)。

如果要定义一个设置属性值的方法(setter),则需要使用名字”@属性名.setter”的装饰器。

如果一个属性只有用于获取属性值的getter方法,而没有用于设置属性值的setter方法,则该属性是一个只读属性,只允许读取该属性的值、而不能设置该属性的值。

例:通过@property装饰器使得学生成绩的取值范围必须在0~100之间。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
1          import datetime
2 class Student: #定义Student类
3 @property
4 def score(self): #用@property装饰器定义一个用于获取score值的方法
5 return self._score
# 注意:在类的setter和getter方法中使用self访问属性时,需要在属性名前加上下划线,否则系统会因不断递归调用而报错。
6 @score.setter
7 def score(self, score): #用score.setter定义一个用于设置score值的方法
8 if score<0 or score>100: #不符合0~100的限定条件
9 print('成绩必须在0~100之间! ')
10 else:
11 self._score=score
12 @property
13 def age(self): #用@property装饰器定义一个用于获取age值的方法
14 return datetime.datetime.now().year-self.birthyear
15 if __name__=='__main__':
16 stu=Student() #创建Student类对象stu
17 stu.score=80 #将stu对象的score属性赋值为80
18 stu.birthyear=2000 #将stu对象的birthyear属性赋值为2000
19 print('年龄: %d,成绩: %d'%(stu.age,stu.score))#年龄: 23,成绩: 80
20 #stu.age=19 #取消前面的注释符则会报错
21 stu.score=105 #将stu对象的score属性赋值为105
22 print('年龄: %d,成绩: %d'%(stu.age,stu.score))#成绩必须在0~100之间!年龄: 23,成绩: 80