授课: 尚煜茗
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:.1 f} cm(范围:{boy_min:.1 f} cm ~ {boy_max:.1 f} cm)" )print (f"女孩:{girl_height:.1 f} cm(范围:{girl_min:.1 f} cm ~ {girl_max:.1 f} cm)" )
Python语法元素分析 程序的格式框架 (1)缩进
Python语言采用严格的“缩进”来表明程序的格式框架。缩进指每一行代码开始前的空白区域,用来表示代码之间的包含和层次关系。
1个缩进 = 4个空格。用以在Python中标明代码的层次关系,缩进是Python语言中表明程序框架的唯一手段。
单层缩进
多层缩进
(2)注释
命名与保留字 (1)Python 3.x保留字列表 (33个)
(2)命名表示
逻辑与值
1.True/False:布尔值常量,表示逻辑真/假
1 2 3 4 5 6 7 8 9 print (True ==1 )print (False ==0 )print (True ==1.0 )print (False ==0.0 )print (True =="True" )print (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 access_granted = is_admin or (is_vip and has_2fa) 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) 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 count = 1 while count <= 10 : if count==5 : count+=1 continue print (count) if count==8 : break count+=1
函数与类
7.def:定义函数
1 2 3 def greet (name ): return f"hello,(name)!" print (greet("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 ))
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 print ("内部函数 x=" ,x) inner() print ("外部函数 x=" ,x) outer() def outer (): x=10 def inner (): nonlocal x x=20 print ("内部函数 x=" ,x) inner() print ("外部函数 x=" ,x) outer()
导入&命名
13.import/from/as: 模块导入与命名
import:用于导入Python 模块或包,让当前脚本可以使用其他模块的功能。
from:用于从模块中导入特定的函数、类或变量,避免导入整个模块。
as:用于简化代码、避免名称冲突或提高可读性。
1 2 3 4 from math import sqrt as sqprint (sq(25 ))
删除&通过
14.del:用于删除变量、列表元素、对象属性等,释放内存。
pass:占位符,用于语法上需要代码但实际不执行任何操作。
1 2 3 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 ))
生成器
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字符串的两种序号体系。
字符串中取字符: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>
(2)input()函数
获得用户输入之前,input()函数可以包含一些提示性文字
<变量> = input(<提示性文字>)
1 2 3 4 5 6 >>>input ("请输入: " ) 请输入: python 'python' >>> input ("请输入: " )请输入: 1024.256 '1024.256'
(3)分支语句
(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 import turtleturtle.setup(650 ,350 ,200 ,200 ) turtle.penup() turtle.fd(-250 ) turtle.pendown() turtle.pensize(25 ) turtle.pencolor("purple" ) turtle.seth(-40 ) for i in range (4 ): turtle.circle(40 ,80 ) turtle.circle(-40 , 80 ) turtle.circle(40 ,80 /2 ) turtle.fd(40 ) turtle.circle(16 ,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 turtlescreen = turtle.Screen() screen.title("正三角形绘制" ) t = turtle.Turtle() t.shape("turtle" ) t.color("blue" ) t.pensize(3 ) for _ in range (3 ): t.forward(200 ) t.left(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 turtleturtle.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 turtleturtle.setup(1000 ,600 ,200 ,200 ) turtle.pensize(10 ) turtle.penup() turtle.seth(0 ) turtle.fd(-150 ) turtle.pendown() turtle.pencolor("blue" ) turtle.circle(60 ,360 ) turtle.penup() turtle.fd(150 ) turtle.pendown() turtle.pencolor("black" ) turtle.circle(60 ,360 ) turtle.penup() turtle.fd(150 ) turtle.pendown() turtle.pencolor("red" ) turtle.circle(60 ,360 ) turtle.penup() turtle.seth(45 ) turtle.fd(-45 ) turtle.pendown() turtle.pencolor("green" ) turtle.circle(60 ,360 ) turtle.penup() turtle.seth(5 ) turtle.fd(-190 ) turtle.pendown() turtle.pencolor("yellow" ) turtle.circle(60 ,360 ) turtle.done()
函数封装 蟒蛇程序功能 可以分成两类:绘制图形前对画笔的设置,包括颜色、尺寸、初始位置等以及绘制Python蟒蛇的功能。
由于蟒蛇绘制的功能相对独立,可以用函数来封装
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import turtledef 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 turtleimport mathturtle.speed(0 ) 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 twidth = 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.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))
浮点数类型 带有小数点及小数的数字。
Python语言中浮点数的数值范围存在限制,小数精度也存在限制。这种限制与在不同计算机系统有关。
(1)浮点数间运算存在不确定尾数,不是bug
(2)浮点数间运算存在不确定尾数,不是bug
(3)浮点数间运算存在不确定尾数
复数类型 与数学中的复数概念一致, 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)操作符是完成运算的一种符号体系
(2)二元操作符有对应的增强赋值操作符
数字类型的关系 (1)类型间可进行混合运算,生成结果为”最宽”类型
三种类型存在一种逐渐”扩展”或”变宽”的关系:整数 -> 浮点数 -> 复数
例如:123 + 4.0 = 127.0(整数+浮点数 = 浮点数)
可以用type()函数进行类型判断
(2)内置的数值运算函数:Python解释器提供了一些内置函数,在这些内置函数之中,有6个函数与数值运算相关
数字类型的转换 (1)数值运算操作符可以隐式地转换输出结果的数字类型
例如,两个整数采用运算符“/”的除法将可能输出浮点数结果。此外,通过内置的数字类型转换函数可以显式地在数字类型之间进行转换
(2)三种类型可以相互转换
函数:int(), float(), complex()
示例:int(4.5) = 4 (直接去掉小数部分)、float(4) = 4.0 (增加小数部分)、complex(4) = 4 + 0J
复数不能转化为浮点数、整数,会报错!
数字类型的判断 函数:type(x),返回x的类型,适用于所有类型的判断
示例:
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 mathmath.ceil(10.2 )
第二种,from math import <函数名>。对math库中函数可以直接采用<函数名>()形式使用
1 2 3 from math import floorfloor(10.2 )
math库解析 (1)math库包括4个数学常数
(2)math库包括16个数值表示函数
(3)math库中包括8个幂对数函数
(4)math库包括六个“三角、双曲函数”
(5)math库包括4个高等特殊函数
天天向上的力量 1.一年365天,以第1天的能力值为基数,记为1.0,当好好学习时能力值相比前一天提高1%,当没有学习时由于遗忘等原因能力值相比前一天下降1%。每天努力和每天放任,一年下来的能力值相差多少呢?
1 2 3 4 5 import mathdayup = math.pow ((1.0 + 0.001 ), 365 ) daydown = math.pow ((1.0 - 0.001 ), 365 ) print ("向上: {:.2f}, 向下: {:.2f}." .format (dayup, daydown))
运行结果如下,每天努力1%,一年下来将提高44%,好像不多?请继续分析。
2.一年365天,如果好好学习时能力值相比前一天提高5%,当放任时相比前一天下降5%。效果相差多少呢?
1 2 3 4 5 import mathdayup = math.pow ((1.0 + 0.005 ), 365 ) daydown = math.pow ((1.0 - 0.005 ), 365 ) print ("向上: {:.2f}, 向下: {:.2f}." .format (dayup, daydown))
运行结果如下,每天努力5%,一年下来将提高6倍!
3.一年365天,如果好好学习时能力值相比前一天提高1%,当放任时相比前一天下降1%。效果相差多少呢?
1 2 3 4 5 6 import mathdayfactor = 0.01 dayup = math.pow ((1.0 + dayfactor), 365 ) daydown = math.pow ((1.0 - dayfactor), 365 ) print ("向上: {:.2f}, 向下: {:.2f}." .format (dayup, daydown))
运行结果如下,每天努力1%,一年下来将提高37倍。这个相当惊人吧!
4.一年365天,一周5个工作日,如果每个工作日都很努力,可以提高1%,仅在周末放任一下,能力值每天下降1%,效果如何呢?
1 2 3 4 5 6 7 8 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 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 dayupdayfacotr = 0.01 while (dayUP(dayfactor)<37.78 ): dayfactor += 0.001 print ("每天的努力参数是: {:.3f}." .format (dayfactor))
如果每周连续努力5天,休息2天,为了达到每天努力1%所达到的的水平,则就需要在工作日将提高的程度达到约2%,即要努力1倍才仅是为了休息2天。这就是天天向上的力量。
字符串类型及其操作 字符串 (1)由0个或多个字符组成的有序字符序列
(2)不同表示方法的作用
字符串类型的转换 大多数数据类型都可以通过str()函数转换为字符串
字符串的序号 正向递增序号和反向递减序号
字符串的使用 使用[ ]获取字符串中一个或多个字符
*注意:字符串的“驻留”
Python对于短小字符串会自动驻留,使其指向同一块内存
字符串切片高级用法 使用[M: N: K]根据步长对字符串切片
字符串的特殊字符 转义符 \
字符串切片相关事例内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 s="Hello World" print (s[4 ])print (s[1 :])print (s[:-1 ])print (s[-6 ])print (s[6 :10 ])print (s[-5 :-2 ])print (s[2 :5 :1 ])print (s[2 :5 :2 ])print (s[5 :2 :-1 ])print (s[-5 :-1 :3 ])print (s[::-1 ])eval ("print('Hello World')" )只去掉一层引号
字符串操作符 (1)操作符及使用
由0个或多个字符组成的有序字符序列。如果*后面是负数,会怎样。
(2)获取星期字符串
输入:1-7的整数,表示星期几。输出:输入整数对应的星期字符串。例如:输入3,输出星期三
1 2 3 4 5 6 7 8 9 10 weekStr = "星期一星期二星期三星期四星期五星期六星期日" weekId = eval (input ("请输入星期数字(1-7):" )) pos = (weekId–1 ) * 3 print (weekStr[pos: pos+3 ])weekStr = "一二三四五六日" weekId = eval (input ("请输入星期数字(1-7):" )) print ("星期" + weekStr[weekId-1 ])
字符串处理函数 (1)一些以函数形式提供的字符串处理功能
(2)一些以函数形式提供的字符串处理功能
(3)Unicode编码: Python字符串的编码方式
统一字符编码,即覆盖几乎所有字符的编码方式
从0到1114111 (0x10FFFF)空间,每个编码对应一个字符
Python字符串中每个字符都是Unicode编码字符
例子:
字符串处理方法 (1)”方法”在编程中是一个专有名词
(2)一些以方法形式提供的字符串处理功能
观察例子:
字符串类型的格式化 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(<逗号分隔的参数>)
默认的参数序号:
改变默认的参数序号:
按照关键词插入:
槽内部对格式化的配置方式。{ <参数序号> : <格式控制标记>}
时间
1 2 3 4 for i in range (10 ): print ("hello world" +str (i)+"\r" ,end="" ) 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())b=a.upper() print (b.lower())d='aa bb cc dd ee' print (d.split(' ' ))f='aa,bb,cc,dd,ee' print (f.split(',' ))s=' hello world ' print (s.split(" " ))t='##hello###world##' print (t.split("#" ))print (t.split("##" ))q='###hello#####world###' print (q.split("###" ))print (q.replace("#" ,"o" ))w='hello world' print (w.split(' ' ))x='hello' print (x.center(20 ,"*" )) y=' hello world ' print (y.split(' ' )) print (y.strip())a='pythonpython==' print (a.strip('py=' ))li='12345' print (li.join(' ' ))print (' ' .join(li))a='test' b='work' print (a+b)
1 2 3 4 print ("{}的概率是{}%,这个概率小于阈值{}" .format ('事件发生' ,95 ,98 ))print ("{1}的概率是{2}%,这个概率小于阈值{0}" .format ('事件发生' ,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 ])text="My name is {0} and I am {1} years old." .format ("Alice" ,25 ) print (text)text="My name is {name} and I am {age} years old." .format (name="Alice" ,age=25 ) print (text)content="{:=^50}" .format ("Train" ) print (content)content="{:-^50}" .format ("Test" ) print (content)content="{:-^50,}" .format (123123123123 ) print (content)content="{:-^50,.2}" .format (3.14159265 ) print (content)content="{:-^50,.2f}" .format (3.14159265 ) print (content)content="{:-^50,.2e}" .format (3.14159265 ) print (content)content="{:-^50,.2E}" .format (3.14159265 ) print (content)content="{:-^50,.2%}" .format (3.14159265 ) print (content)content="{:-^50b}" .format (16 ) print (content)content="{:-^50d}" .format (16 ) print (content)content="{:-^50o}" .format (16 ) print (content)content="{:-^50x}" .format (16 ) print (content)content="{:-^50X}" .format (15 ) print (content)content="{:-^50c}" .format (97 ) print (content)content="{:-^50c} hello world {:->20c}" .format (97 ,10010 ) print (content)content="{:-^50c} hello world {:+<20c}" .format (97 ,8888 ) print (content)content="{1:-^50c} hello world {0:+<20c}" .format (97 ,98 ) print (content)content="{0:=^20}" .format ("PYTHON" ) print (content)content="{0:*>20}" .format ("BIT" ) print (content)content="{:10}" .format ("BIT" ) print (content)
文本进度条 简单的开始 利用print()函数实现简单的非刷新文本进度条。
基本思想是按照任务执行百分比将整个任务划分为100个单位,每执行N%输出一次进度条。每一行输出包含进度百分比,代表已完成的部分(**)和未完成的部分(..)的两种字符,以及一个跟随完成度前进的小箭头,风格如下:
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 timescale=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 import timefor 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 import timescale = 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 -----------执行结束---------- '''
五花八门的进度条设计函数
专门的进度条库tqdm Tqdm是python中专门用于处理和实现进度条的库。简单、易用、功能强大。将一个进度条包装在可迭代对象上,显示其执行时间
(1)基本用法
1 2 3 4 5 from tqdm import tqdmimport timefor 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 tqdmimport timefor 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 timewith 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
正则表达式,就是高效处理上述问题的有力工具。其核心就是“模式匹配”
正则表达式的常见语法 正则表达式中包括了【普通字符】和【特殊字符】
普通字符 :没有特殊含义,如月/每/元
特殊字符 :在正则表达式语法中承担特殊功能的字符,如 * ? []
(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)区分贪婪模式与非贪婪模式
(6)对特殊字符的转义
(7)用反斜杠匹配某种字符类型
(8)[]方括号表示匹配几个字符之一
(9)^不在方括号中,表示匹配文本的起始位置
正则表达式分为单行和多行模式,匹配的是行的开头
(10)$表示匹配文本的结尾,同样分为多行模式和单行模式
(11)( )表示分组
正则表达式切分字符串
练习题 (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 mathdef 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:.2 f} ' 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:.2 f} , 体积为{volume_of_cube:.2 f} ' def circle (radius ): """接收圆的半径,返回圆形的面积,圆周率用math.pi""" area_of_circle = math.pi * radius ** 2 return f'圆形的面积为{area_of_circle:.2 f} ' 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:.2 f} , 体积为{volume_of_sphere:.2 f} ' 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:.2 f} , 体积为{volume_of_cylinder:.2 f} ' 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:.2 f} , 体积为{volume_of_cone:.2 f} ' 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:.2 f} , 体积为{volume_of_tri_prism:.2 f} ' 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 mathchord = 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 mathmoney=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语句后与该语句同级别的下一条语句。
if语中<条件>部分可以使用任何能够产生True或False的语句
形成判断条件最常见的方式是采用关系操作符
*Python语言共有6个关系操作符:
(1)If x == True:可简写做 If x(2)If支持链式比较: if 0 < x < 10:(3)判断是否为空,要用 is None(4)Python列表推导式中,可以用if进行过滤
条件组合:*用于条件组合的三个操作符
1 2 3 4 5 6 7 8 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 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>
多分支结构是二分支结构的扩展,这种形式通常用于设置同一个判断条件的多条执行路径。
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
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 height, weight = eval (input ("请输入身高(米)和体重\(公斤)[逗号隔开]: " )) bmi = weight / pow (height, 2 ) print ("BMI数值为:{:.2f}" .format (bmi))wto, dom = "" , "" if bmi < 18.5 : wto = "偏瘦" elif bmi < 25 : wto = "正常" elif bmi < 30 : wto = "偏胖" else : wto = "肥胖" if bmi < 18.5 : dom = "偏瘦" elif bmi < 24 : dom = "正常" elif 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 <遍历结构>: <语句块>
*遍历循环的应用
计数循环(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: <语句块> >>> 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 : <语句块> 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 : <语句块> 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中处理时间的标准库:计算机时间的表达、提供获取系统时间并格式化输出功能、提供系统级精确计时功能,用于程序性能分析
time库包括三类函数:
时间获取:time() ctime() gmtime()
时间格式化:strftime() strptime()
程序计时:sleep(), perf_counter()
时间获取
random库的使用 随机数在计算机应用中十分常见,Python内置的random库主要用于产生各种分布的伪随机数序列。random库采用梅森旋转算法(Mersenne twister)生成伪随机数序列,可用于除随机性要求更高的加解密算法外的大多数工程应用。
使用random库主要目的是生成随机数,因此,读者只需要查阅该库的随机数生成函数,找到符合使用场景的函数使用即可。这个库提供了不同类型的随机数函数,所有函数都是基于最基本的random.random()函数扩展而来。
random库解析 生成随机数之前可以通过seed()函数指定随机数种子,随机种子一般是一个整数,只要种子相同,每次生成的随机数序列也相同。 这种情况便于测试和同步数据。
1 2 3 4 5 6 7 8 >>>seed(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 ) >>>"{}.{}.{}" .format (randint(1 ,10 ),randint(1 ,10 ),randint(1 ,10 )) '4.4.10'
π的计算 π(圆周率)是一个无理数,即无限不循环小数。精确求解圆周率π是几何学、物理学和很多工程学科的关键。
对π的精确求解曾经是数学历史上一直难以解决的问题之一,因为π无法用任何精确公式表示,在电子计算机出现以前,π只能通过一些近似公式的求解得到,直到1948年,人类才以人工计算方式得到π的808位精确小数。
随着计算机的出现,数学家找到了另类求解π的另类方法:蒙特卡罗方法,又称随机抽样或统计试验方法。当所要求解的问题是某种事件出现的概率,或者是某个随机变量的期望值时,它们可以通过某种“试验”的方法,得到这种事件出现的频率,或者这个随机变数的平均值,并用它们作为问题的解。这就是蒙特卡罗方法的基本思想。
应用蒙特卡罗方法求解π的基本步骤如下:随机向单位正方形和圆结构,抛洒大量“飞镖”点。计算每个点到圆心的距离从而判断该点在圆内或者圆外。用圆内的点数除以总点数就是π/4值。随机点数量越大,越充分覆盖整个图形,计算得到的π值越精确。实际上,这个方法的思想是利用离散点值表示图形的面积,通过面积比例来求解π值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 from random import randomfrom math import sqrtfrom time import clockDARTS = 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.016477 s
异常处理机制 异常处理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>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 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) for i in sample.items(): print (i) for i in sample.values(): print (i) 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) sentiment = ['kaixin' ,'shangxin' ,'kaixin' ,'shangxin' ] for i in zip (years,scores,sentiment): print (i) import timestart=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))
循环
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 for s in "PYTHON" : if s=="T" : continue print (s,end="" ) for s in "PYTHON" : if s=="T" : break print (s,end="" )
时间
1 2 3 4 5 6 7 8 9 10 11 12 13 import timeprint (time.time())start=time.time() end=time.time() print (end-start)import timetime.strptime('2025-04-08 20:12:30' ,'%Y-%m-%d %H:%M:%S' ) 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 randomrandom.seed(15 ) random.random() import randomrandom.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 randomimport matplotlib.pyplot as pltplt.rcParams['font.sans-serif' ] = ['SimHei' ] plt.rcParams['axes.unicode_minus' ] = False population_height = [random.uniform(150 , 200 ) for _ in range (10000 )] 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 randomimport matplotlib.pyplot as pltdef 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:.6 f} (using {num_points} points)' ) plt.legend() plt.xlabel("x" ) plt.ylabel("y" ) plt.axis("square" ) plt.show() return pi_estimate 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 )
函数的参数传递 参数个数:函数可以有参数,也可以没有,但必须保留括号
def <函数名>():
<函数体>
return <返回值>
def fact():
print(“我也是函数")
可选参数传递 函数定义时可以为某些参数指定默认值,构成可选参数(可选参数必须在后边,否则在调用时会引起混乱)
def <函数名>(<非可选参数>,<可选参数>): <函数体> return <返回值>
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 >>> fact(10 )3628800 >>> fact(10 ,5 )725760
可变参数传递 函数定义时可以设计可变数量参数,既不确定参数总数量
def <函数名>(<参数>, *b):
<函数体>
return <返回值>
带星号的参数必须出现在参数列表最后通过元组类型接收多个值(0个也可!)
1 2 3 4 5 6 7 8 9 10 11 12 def fact (n,*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
参数传递的两种方式:函数调用时,参数可以按照位置或名称方式传递
Python中的可变参数
关键词位置可变参数*args
关键词可变参数 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 : return “False ” 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())[1 ,2 ,3 ,4 ,5 ,6 ,7 ] >>> 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=10 ,100 def fact (n ): s=1 for i in range (1 ,n+1 ): s*=i return s print (fact(n),s) >> 3628800 100
规则2:局部变量为组合数据类型且未创建,等同于全局变量
1 2 3 4 5 6 7 8 9 ls =["F" ,"f" ] def func (a ): ls.append(a) return func("c" ) 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个基本线条组成,七段数码管可以有固定顺序,不同数字显示不同的线条
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import turtledef 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:获得一串数字,绘制对应的数码管
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import turtledef drawLine (draw ): …(略) def drawDigit (digit ): …(略) def drawDate (date ): for i in date: drawDigit(eval (i)) 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 turtledef 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 ): 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()
函数的递归 函数定义中调用函数自身的方式
类似数学归纳法
两个关键特征:
链条:计算过程存在递归链条;基例:存在一个或多个不需要再次递归的基例
如何实现?
1 2 3 4 def fact (n ): if n == 0 : return 1 else : return n*fact(n-1 )
函数 + 分支语句
递归本身是一个函数,需要函数定义方式描述
函数内部,采用分支语句对输入参数进行判断
基例和链条,分别编写对应代码
函数递归实例解析
(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个台阶,返回有多少种走法。
斐波那契数列:
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)
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 ()) annual_salary = float (input ()) portion_saved = float (input ()) / 100 semi_annual_raise = float (input ()) / 100 portion_down_payment = 0.3 def down_payment (): down_payment = total_cost * portion_down_payment return down_payment down_payment = down_payment() print ('首付' , down_payment) current_savings = 0 number_of_months = 1 monthly_salary = annual_salary / 12 monthly_deposit = monthly_salary * portion_saved 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)) 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为素数。完成以下函数的定义并按要求完成问题:
定义素数函数is_ prime(n) 将素数的判定代码定义为一个函数,接受用户输入的正整数n,返回n是否是素数,n为素数时返回True,不是素数时返回False。 一个整数若可以进行因数分解,那么分解时得到的两个数一定是一个小于等于sqrt(n),一个大于等于sqrt(n),所以对于每个数n,并不需要从2判断到n-1,只需要遍历到sqrt(n)即可。因为若sqrt(n)左侧找不到因数,那么右侧也一定找不到因数,这样可以显著提升算法的效率。
定义一个函数output_prime(n),接受一个正整数number为参数,在函数中调用问题1中定义的判定素数函数,对不大于number的整数一一判定,在同一行中输出不大于n的全部素数。此函数无返回值,直接输出找到的素数。 调用all_prime(n)函数前,先接收用户输入的一个正整数,作为函数调用时的参数。
定义寻找回文素数函数 回文是指数或者字符串具有首尾回环性质,从后向前按位颠倒后与原文一样。首尾回环的数字就是回文数,如:12321;首尾回环的字符串就是回文串,如:’上海自来水来自海上’。 如果一个整数是素数,同时,其对应的字符串是回文字符串时,便称其为回文素数。 编写一个函数,调用前面定义好的素数判定函数和题目给定的回文判定函数完成回文素数的判定,函数无返回值,直接输出找到的回文素数。 输入一个正整数,输出小于这个数的所有回文素数。
寻找反素数 反素数是指一个将其逆向拼写后也是一个素数的非回文数。例如:17和71都是素数且均不是回文数,所以17和71都是反素数。 输入一个正整数n,按从小到大顺序输出所有反素数。
哥德巴赫猜想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 = 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.用户登录的三次机会
给用户三次输入用户名和密码的机会,要求如下:
如输入第一行输入用户名为 ‘Kate’,第二行输入密码为 ‘666666’,输出 ‘登录成功!’,退出程序;
当一共有 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 randominput_str = input () a, b = map (int , input_str.split(',' )) seed = a + b random.seed(seed) 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)。
集合类型 *定义
集合是多个元素的无序组合 ,集合元素可以是:整数、浮点数、字符串、元组;不可以是:列表、集合、字典。
集合类型与数学中的集合概念一致
集合元素之间无序,每个元素唯一,不存在相同元素
集合元素不可更改,不能是可变数据类型
集合用大括号 {} 表示,元素间用逗号分隔
建立集合类型用 {} 或 set():set的参数必须为可迭代的数据类型
建立空集合类型,必须使用set():如果写成{},Python解释器认为是空字典而不是空集合
1 2 3 4 5 6 >>> A = {"python" , 123 , ("python" ,123 )} {123 , 'python' , ('python' , 123 )} >>> B = set ("pypy123" ) {'1' , 'p' , '2' , '3' , 'y' } >>> C = {"python" , 123 , "python" ,123 }{'python' , 123 }
*集合间操作
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' }
*集合处理方法
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 >>> Aset ()
*集合类型应用场景
(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个或多个数据项的不可变序列类型。元组生成后是固定的,其中任何数据项不能替换或删除。列表则是一个可以修改数据项的序列类型,使用也最灵活。
序列类型有12个通用的操作符和函数
元组类型定义 (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 ]
*列表类型操作函数和方法
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' ]
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' ]
*列表功能默写
基本统计值计算 以最简单的统计问题为例,求解一组不定长数据的基本统计值,即平均值、标准差、中位数。
一组数据表示为S=s0, s1, …, sn-1,其算术平均值、标准差分别表示为:
由于平均数、标准差和中位数是三个不同的计算目标,使用函数方式编写计算程序。
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 from math import sqrtdef 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) 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)映射是一种键(索引)和值(数据)的对应
(2)字典类型是“映射”的体现
键值对:键是数据索引的扩展
字典是键值对的集合,键值对之间无序
采用大括号{}和dict()创建,键值对用冒号: 表示{<键1>:<值1>,<键2>:<值2>, … ,<键n>:<值n>}
字典类型的用法 在字典变量中,通过键获得值
1 2 3 4 5 6 7 >>> d = {"中国" :"北京" , "美国" :"华盛顿" , "法国" :"巴黎" }>>> d {'中国' : '北京' , '美国' : '华盛顿' , '法国' : '巴黎' } >>> d["中国" ]'北京' >>> de = {} ; type (de) <class 'dict' >
字典处理函数及方法
1 2 3 4 5 6 7 >>> d = {"中国" :"北京" , "美国" :"华盛顿" , "法国" :"巴黎" }>>> "中国" in d True >>> d.keys()dict_keys(['中国' , '美国' , '法国' ]) >>> d.values()dict_values(['北京' , '华盛顿' , '巴黎' ])
1 2 3 4 5 6 7 >>> d = {"中国" :"北京" , "美国" :"华盛顿" , "法国" :"巴黎" }>>> d.get("中国" ,"伊斯兰堡" )'北京' >>> d.get("巴基斯坦" ,"伊斯兰堡" )'伊斯兰堡' >>> d.popitem()('美国' , '华盛顿' )
*字典功能默写
*字典类型应用场景
(1)映射的表达
映射无处不在,键值对无处不在
例如:统计数据出现的次数,数据是键,次数是值
最主要作用:表达键值对数据,进而操作它们
(2)元素遍历
(3)统计某个特征的数量、构建树形结构、配置文件
jieba库的使用 分词 分词的目的,就是把中文文本按照词语切分开
(1)基于规则的分词
正向最大匹配(FMM):南京市长江大桥
逆向最大匹配(RMM):研究生命的起源
双向最大匹配:结婚的和尚未结婚的
(2)基于统计额分词:基于N-Gram模型的分词
(3)基于深度学习的分词:序列标注任务
(4)混合方法:多种方法一起用
jieba是Python中一个重要的第三方中文分词函数库,jieba库是第三方库,不是安装包自带,需要通过pip指令安装。
1 2 3 >>>import jieba >>>jieba.lcut("中国是一个伟大的国家" ) ['中国' , '是' , '一个' , '伟大' , '的' , '国家' ]
jieba库的解析 分词冗余度:全模式 > 搜索引擎模式 > 精确模式
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的乘积是单词与文档之间相关性的一种有效度量
基于TF-IDF算法
(2)TextRank算法
TextRank是一种图排序算法,基于PageRank的思想,将文本中的词语看作图中的节点,通过词语共现关系构建边,迭代计算节点权重(重要性)。
关键词提取:将句子中的词语作为节点,用窗口内共现关系构建边,权重由共现次数决定。
基于TextRank算法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 import jiebadef read_text (file_path ): with open (file_path, 'r' , encoding='utf-8' ) as f: text = f.read() return text 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)]) return ['' .join(ngram) for ngram in ngrams]
文本词频统计 需求:一篇文章,出现了哪些词?哪些词出现得最多?该怎么做呢?
英文文本: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 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 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 import jiebatxt = open ("threekingdoms.txt" , "r" , encoding="utf-8" ).read() words = jieba.lcut(txt) counts = {} for word in words: if len (word) == 1 : 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 import jiebaexcludes = {"将军" ,"却说" ,"荆州" ,"二人" ,"不可" ,"不能" ,"如此" } 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 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 字节)
文件的打开关闭
文件的打开
文件路径
打开模式
文件的关闭
文件内容的读取 文件内容的读取
文件的全文本操作
文件的逐行操作
数据的文件写入
数据组织的维度
一维数据 (1)表示
a.如果数据间有序:使用列表类型
ls = [3.1398, 3.1349, 3.1376]
列表类型可以表达一维有序数据、for循环可以遍历数据,进而对每个数据进行处理
b.如果数据间无序:使用集合类型
st = {3.1398, 3.1349, 3.1376}
集合类型可以表达一维无序数据、for循环可以遍历数据,进而对每个数据进行处理
(2)存储
(3)处理
二维数据 (1)表示
(2)CSV格式与二维数据存储
国际通用的一二维数据存储格式,一般.csv扩展名。每行一个一维数据,采用逗号分隔,无空行。Excel和一般编辑软件都可以读入或另存为csv文件。
如果某个元素缺失,逗号仍要保留。二维数据的表头可以作为数据存储,也可以另行存储。逗号为英文半角逗号,逗号与数据之间无额外空格。
按行存?按列存?
按行存或者按列存都可以,具体由程序决定。一般索引习惯:ls[row][column],先行后列。根据一般习惯,外层列表每个元素是一行,按行存。
(3)处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 fo = open (fname) ls = [] for line in fo: line = line.replace("\n" ,"" ) ls.append(line.split("," )) fo.close() 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展示
高维数据的格式化 与一维二维数据不同,高维数据能展示数据间更为复杂的组织关系。为了保持灵活性,表示高维数据不采用任何结构形式,仅采用最基本的二元关系,即键值对。 JSON格式可以对高维数据进行表达和存储。JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于阅读和理解。JSON格式表达键值对<key, value>的基本格式如下,键值对都保存在双引号中:”key” : “value”
当多个键值对放在一起时,JSON有如下一些约定:数据保存在键值对中;键值对之间由逗号分隔;大括号用于保存键值对数据组成的对象;方括号用于保存键值对数据组成的数组。
Json里的对象——>Python里的字典、Json里的数组——>Python里的列表
json库的使用
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) >>>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数据分析
读取数据并可视化、异常数据检测、数据预测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 pltimport numpy as npplt.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 jiebatxt = "中华人民共和国教育部考试中心委托专家制定了全国计算机等级考试二级程序设计考试大纲" 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 )
面向对象概述 面向对象是当前流行的程序设计方法,其以人类习惯的思维方式,用对象来理解和分析问题空间,使开发软件的方法与过程尽可能接近人类认识世界、解决问题的思维方法与过程。
面向对象方法的基本观点是一切系统都是由对象构成的,每个对象都可以接收并处理其他对象发送的消息,它们的相互作用、相互影响,实现了整个系统的运转。
类和对象的概念: 类和对象是面向对象程序设计的两个重要概念。
类和对象的关系即数据类型与变量的关系,根据一个类可以创建多个对象,而每个对象只能是某一个类的对象。
类规定了可以用于存储什么数据,而对象用于实际存储数据,每个对象可存储不同的数据。
类的定义和创建实例 类的定义:
在一个类中,除了可以包含前面所说的属性,还可以包含各种方法。属性对应一个类可以用来保存哪些数据,而方法对应一个类可以支持哪些操作(即数据处理)。
类的定义形式多样:
我们既可以直接创建新的类,也可以基于一个或多个已有的类创建新的类;我们既可以创建一个空的类,然后再动态添加属性和方法,也可以在创建类的同时设置属性和方法。
封装性:
类中的属性对应前面所学习的变量,而类中的方法对应前面所学习的函数。通过类,可以把数据和操作封装在一起,从而使得程序结构更加清晰,这也就是所谓的类的封装性。
提示:每次创建对象时,系统都会在内存中选择一块区域分配给对象,每次选择的内存通常是不一样的。因此,实际运行时会看到一个不同的stu对象地址。
类属性定义及其访问
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 Student : name='Unknown' if __name__=='__main__' : print ('第4行输出: ' ,Student.name) stu1=Student() stu2=Student() print ('第7行输出: stu1 %s,stu2 %s' %(stu1.name,stu2.name)) Student.name='未知' print ('第9行输出: ' ,Student.name) print ('第10行输出: stu1 %s,stu2 %s' %(stu1.name,stu2.name)) stu1.name='李晓明' stu2.name='马红' print ('第13行输出: ' ,Student.name) print ('第14行输出: stu1 %s,stu2 %s' %(stu1.name,stu2.name)) Student.name='学生' print ('第16行输出: ' ,Student.name) print ('第17行输出: stu1 %s,stu2 %s' %(stu1.name,stu2.name))
为对象动态绑定新属性
Python作为一种动态语言,除了可以在定义类时指定类属性外,还可以动态地为已经创建的对象绑定新的属性。
例:为对象动态绑定新属性示例。
1 2 3 4 5 6 7 8 9 1 class Student : 2 name='Unknown' 3 if __name__=='__main__' :4 stu1=Student() 5 stu2=Student() 6 stu1.age=19 7 print ('stu1姓名: %s,年龄: %d' %(stu1.name,stu1.age)) 8 9
类中普通方法定义及调用 类中的方法实际上就是执行某种数据处理功能的函数。与普通函数定义一样,类中的方法在定义时也需要使用def 关键字。
类中的方法分为两类:普通方法和内置方法。普通方法需要通过类的实例对象根据方法名调用;内置方法是在特定情况下由系统自动执行。
普通方法定义和调用
在定义类的普通方法时,要求第一个参数需要对应调用方法时所使用的实例对象(一般命名为self,但也可以改为其他名字)。
当使用一个实例对象调用类的普通方法时,其语法格式为:实例对象名.方法名(实参列表)
提示:在通过类的实例对象调用类中的普通方法时,并不需要传入self参数的值,self会自动对应调用该方法时所使用的对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 1 class Student : 2 name='Unknown' 3 def SetName (self, newname ): 4 self .name=newname 5 def PrintName (self ): 6 print ('姓名: %s' %self .name) 7 if __name__=='__main__' :8 stu1=Student() 9 stu2=Student() 10 stu1.SetName('李晓明' ) 11 stu2.SetName('马红' ) 12 stu1.PrintName() 13 stu2.PrintName()
私有属性 私有属性,是指在类内可以直接访问、而在类外无法直接访问的属性
Python中规定, 在定义类时,如果一个类属性名是以__ (两个下划线) 开头,则该类属性为私有属性。
1 2 3 4 5 6 7 8 9 10 11 12 13 class Student : name='未知' __id ='未知' def SetInfo (self,newname,newid ): self .name=newname self .__id =newid def PrintInfo (self ): print ('姓名: %s,身份证号: %s' %(self .name,self .__id )) if __name__=='__main__' : stu=Student() stu.SetInfo('李晓明' ,'120XXXXXXXXXXXXXXX' ) stu.PrintInfo()
类中的方法本质上就是前面所学习的函数,因此,类中的方法也可以有默认参数值。
例如,可以将第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 : 2 def __init__ (self ): 3 print ('构造方法被调用! ' )4 self .name='未知' 5 def PrintInfo (self ): 6 print ('姓名: %s' %self .name) 7 if __name__=='__main__' :8 stu=Student() 9 stu.PrintInfo() 构造方法被调用! 姓名:未知
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 1 class Student : 2 def __init__ (self,name='未知' ): 3 print ('构造方法被调用! ' )4 self .name=name 5 def PrintInfo (self ): 6 print ('姓名: %s' %self .name) 7 if __name__=='__main__' :8 stu1=Student() 9 stu2=Student('李晓明' )10 stu1.PrintInfo() 11 stu2.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 : 2 def __init__ (self,name ): 3 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) 9 if __name__=='__main__' :10 stu1=Student('李晓明' ) 11 stu2=Student('马红' ) 12 stu3=stu213 del stu2 14 func('张刚' ) 15 del stu3 16 stu4=Student('刘建' ) 姓名为李晓明的对象被创建! 姓名为马红的对象被创建! 姓名为张刚的对象被创建! 姓名为张刚的对象被销毁! 姓名为马红的对象被销毁! 姓名为刘建的对象被创建! 姓名为李晓明的对象被销毁! 姓名为刘建的对象被销毁!
注意:如果多个变量对应同一片内存空间, 则只有这些变量都删除后才会销毁这片内存空间中所保存的对象,也才会自动执行 析构方法。
常用内置方法 __str__: 调用str函数对类对象进行处理时或者调用Python内置函数format()和print()时自动执行, __str__方法的返回值必须是字符串。
1 2 3 4 5 6 7 8 9 1 class Complex : 2 def __init__ (self,real,image ): 3 self .real=real 4 self .image=image 5 def __str__ (self ): 6 return str (self .real)+'+' +str (self .image)+'i' 7 if __name__=='__main__' :8 c=Complex(3.2 ,5.3 ) 9 print (c)
1 2 3 4 5 6 7 8 9 10 11 1 class Student : 2 def __init__ (self, name, age ): 3 self .name=name 4 self .age=age 5 def __le__ (self, other ): 6 return self .age<=other.age7 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)。
子类会继承父类中定义的所有属性和方法,另外也能够在子类中增加新的属性和方法。
如果一个子类只有一个父类,则将这种继承关系称为单继承;如果一个子类有两个或更多父类,则将这种继承关系称为多重继承。
子类的定义 定义子类时需要指定父类,其语法格式为:
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 : 2 def SetName (self, name ): 3 self .name=name 4 class Student (Person ): 5 def SetSno (self, sno ): 6 self .sno=sno 7 class Teacher (Person ): 8 def SetTno (self, tno ): 9 self .tno=tno 10 class TA (Student,Teacher): 11 def SetTeacher (self, teacher ): 12 self .teacher=teacher 13 if __name__=='__main__' :14 stu=Student() 15 stu.SetSno('1810100' ) 16 stu.SetName('李晓明' ) 17 print ('学号: %s,姓名: %s' %(stu.sno,stu.name)) 18 t=Teacher() 19 t.SetTno('998012' ) 20 t.SetName('马红' ) 21 print ('教工号: %s,姓名: %s' %(t.tno,t.name))
方法重写和鸭子类型 方法重写:是指子类可以对从父类中继承过来的方法进行重新定义,从而使得子类对象可以表现出与父类对象不同的行为。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class Person : def __init__ (self, name ): self .name=name def PrintInfo (self ): print ('姓名: %s' %self .name) class Student (Person ): def __init__ (self, sno, name ): self .sno=sno self .name=name def PrintInfo (self ): print ('学号: %s,姓名: %s' %(self .sno,self .name)) def PrintPersonInfo (person ): print ('PrintPersonInfo函数中的输出结果' , end='#' ) person.PrintInfo() if __name__=='__main__' : p=Person('李晓明' ) stu=Student('1810100' ,'李晓明' ) p.PrintInfo() stu.PrintInfo() PrintPersonInfo(p) PrintPersonInfo(stu)
鸭子类型:在鸭子类型中,关注的不是对象所属的类,而是一个对象能够如何使用。
在Python中编写一个函数,传递实参前其参数的类型并不确定,在函数中使用形参进行操作时只 要传入的对象能够支持该操作程序就能正常执行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 1 class Person : 2 def CaptureImage (self ): 3 print ('Person类中的CaptureImage方法被调用! ' )4 class Camera : 5 def CaptureImage (self ): 6 print ('Camera类中的CaptureImage方法被调用! ' )7 def CaptureImageTest (arg ): 8 arg.CaptureImage() 9 if __name__=='__main__' :10 p=Person() 11 c=Camera() 12 CaptureImageTest(p)13 CaptureImageTest(c)
实际上,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 : 2 def __init__ (self, name ): 3 print ('Person类构造方法被调用! ' )4 self .name=name 5 class Student (Person ): 6 def __init__ (self, sno, name ): 7 print ('Student类构造方法被调用! ' )8 super ().__init__(name) 9 self .sno=sno 10 class Postgraduate (Student ): 11 def __init__ (self, sno, name, tutor ): 12 print ('Postgraduate类构造方法被调用! ' )13 super ().__init__(sno, name) 14 self .tutor=tutor 15 if __name__=='__main__' :16 pg=Postgraduate('1810100' ,'李晓明' ,'马红' ) 17 print ('学号: %s,姓名: %s,导师: %s' %(pg.sno,pg.name,pg.tutor))
内置函数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 : pass class Student (Person ): pass class Flower : pass if __name__=='__main__' : stu=Student() f=Flower() print ('stu是Person类或其子类对象: ' , isinstance (stu,Person)) print ('stu是Student类或其子类对象: ' , isinstance (stu,Student)) print ('f是Person类或其子类对象: ' , isinstance (f,Person)) print ('Student是Person类的子类: ' , issubclass (Student,Person)) print ('Flower是Person类的子类: ' , issubclass (Flower,Person)) print ('stu对象所属的类: ' , type (stu)) print ('f对象所属的类: ' , type (f)) print ('stu是Person类对象: ' , type (stu)==Person) print ('stu是Student类对象: ' , type (stu)==Student)
如果我们要判断一个对象的类型是否是指定类或该类的子类,则可以使用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 : 2 def __init__ (self,real=0 ,image=0 ): 3 self .real=real 4 self .image=image 5 @classmethod 6 def add (cls,c1,c2 ): 7 print (cls) 8 c=Complex() 9 c.real=c1.real+c2.real 10 c.image=c1.image+c2.image 11 return c12 if __name__=='__main__' :13 c1=Complex(1 ,2.5 )14 c2=Complex(2.2 ,3.1 )15 c=Complex.add(c1,c2) 16 print ('c1+c2的结果为%.2f+%.2fi' %(c.real,c.image))
将第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 : 2 def __init__ (self,real=0 ,image=0 ): 3 self .real=real 4 self .image=image 5 @staticmethod 6 def add (c1,c2 ): 7 c=Complex() 8 c.real=c1.real+c2.real 9 c.image=c1.image+c2.image 10 return c11 if __name__=='__main__' :12 c1=Complex(1 ,2.5 )13 c2=Complex(2.2 ,3. 1 )14 c=Complex.add(c1,c2) 15 print ('c1+c2的结果为%.2f+%.2fi' %(c.real,c.image))
作用:静态方法逻辑上属于类,但是和类本身没有关系,也就是说在静态方法中,不会涉及到类中的属性和方法的操作。可以理解为,静态方法是个独立的、单纯的函数,它仅仅托管于某个类的名称空间中,便于使用和维护。
动态扩展类与实例 动态扩展类与实例:
Python作为一种动态语言,除了可以在定义类时定义属性和方法外,还可以动态地为已经创建的对象绑定新的属性和方法。
给类绑定方法,直接进行赋值即可
在给对象绑定方法时,需要使用types模块中的MethodType函数,其第一个参数是要绑定的函数名,第二个参数是绑定的对象名。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 1 from types import MethodType 2 class Student : 3 pass 4 def SetName (self,name ): 5 self .name=name6 def SetSno (self,sno ): 7 self .sno=sno8 if __name__=='__main__' :9 stu1=Student() 10 stu2=Student() 11 stu1.SetName=MethodType(SetName,stu1)12 Student.SetSno=SetSno 13 stu1.SetName('李晓明' )14 stu1.SetSno('1810100' )15 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 datetime2 class Student : 3 @property 4 def score (self ): 5 return self ._score6 @score.setter7 def score (self, score ): 8 if score<0 or score>100 : 9 print ('成绩必须在0~100之间! ' )10 else :11 self ._score=score 12 @property 13 def age (self ): 14 return datetime.datetime.now().year-self .birthyear15 if __name__=='__main__' :16 stu=Student() 17 stu.score=80 18 stu.birthyear=2000 19 print ('年龄: %d,成绩: %d' %(stu.age,stu.score))20 21 stu.score=105 22 print ('年龄: %d,成绩: %d' %(stu.age,stu.score))