第一章 环境搭建
python是什么
Python是一种跨平台、开源、免费、的高级程序设计语言。
Python是面向对象、解释型、动态数据类型的高级程序设计语言。
Python是一种脚本语言
python特点
Python的设计哲学为:优雅、明确、简单 ,相比C或C++代码量大大减少,代码质量大大提高,“Life is short,you need Python” 即“人生苦短,我用Python”
Python是一种扩充强大的编程语言,拥有丰富和强大的库,Python能够把其它语言制作的各种模块轻松的链接在一起(尤其是C/C++),又称为“==胶水==”语言
其实⽬前很多知名的机器学习、⼈⼯智能以及深度学习框架也都是基于Python语⾔进⾏开发的:
Google开源机器学习框架:TensorFlow开源社区主推学习框架:Scikit-learn百度开源深度学习框架:Paddle
python的版本变迁
2020 年 1 月 1 日, 停止 Python 2 的更新,Python 2.7 被确定为最后一个 Python 2.x 版本
版本对比:
注意:
Python2.0对中文字符串支持性能不够好
Python2.0与3.0系列版本的开发思想相同,只有少量语法差别
由于扩展库的发行总是滞后于python版本的发行,所以有些扩展库还不支持3.0系列版本(动态变化)
版本选择应该以开发目的、使用到的扩展库、扩展库支持的最高版本为选择标准来选择python版本
Python2.0版本的代码不能直接在3.0的环境下运行,可以使用一些工具进行2.0代码与3.0代码转换,如:2to3.py等
在生产环境中,⼀般不会选择最新版本,因为可能会存在未知Bug,所以⼀般强烈建议大家在选择软件版本时,向前推1 ~ 2个版本。所以咱们课程主要讲解Python3.10版本。
搭建python的环境
python解释器
解释器下载网址:https://www.python.org/
选择安装包:Windows installer (64bit)
安装解释器:
选择Customize installation 自定义安装,建议不要选择上面的默认安装
Add Python3.8 to PATH一定要打勾,表示自动配置环境变量
Documentation(安装帮助文档)
pip(安装下载python包的工具pip)
td/tk and IDLE(安装Tkinter和IDLE开发环境)
Python test suite (安装标准测试套件)
py launcher (启动器)
for all users (安装所有用户都可启动python的快捷方式)
测设安装是否成功:打开运行输入CMD启动命令行输入python :
pycharm集成开发环境
Professional(专业版本) : 功能更加强大,主要是为Python和web开发者而准备,是需要付费
community(社区版本) :轻量级,主要是为Python和数据专家而准备的
新建项目:选择 Create New Project
新建项目设置
Location:设置项目文件夹位置,可以实现新建一个目录,以pychon版本号命名,选择该目录即可
New environment using: 为项目创建一个新的环境,选择Virtualenv环境模式,Virtualenv用来创建一个虚拟pychon环境,解决了多个pychon程序共用一个解释器和插件的情况。
Location:设置虚拟环境目录,默认即可,该目录在pychon项目目录下
Base interpreter :设置python解释器的路径,稍微等待一下,会自动检索配置
Inherit global site-packages:勾选上代表创建的新项目需要copy一份全局包到虚拟环境,即可以使用base interpreter中的第三方库,不选将和外界完全隔离,==必须勾选==
Make available to all projects:勾选上,表示,当在虚拟环境下安装包的时候,copy一份到全局
注意:
全局包存放在python安装目录下:C:\Users\Administrator\AppData\Local\Programs\Python\Python38\Lib\site-packages(要打开隐藏)
虚拟环境包安装在关联的项目目录下面的${虚拟环境名}\Lib\site-packages子目录里
本机的:D:\Python\test\venv\Lib\site-packages)
新建python程序源文件
工作环境设置
改变编辑界面字号:File->Settings->Editor->Font->Size->20
添加解释器:File->Settings->Project :项目名>Project Interpreter ->点击加号(+)输入解释器名进行搜索安装
更换下载库源:File->Settings->Project :项目名>Project Interpreter ->点击加号(+)->Manage Repositories->删除默认源->添加新源(阿里云https://mirrors.aliyun.com/pypi/simple)->重启pycharm
pip 默认下载源更改
pip : 是python默认的软件工具包,安装python时默认自动安装
Python 的 pip 工具安装第三方包时默认会去 https://pypi.org/ 下载,由于“某些原因”,下载速度会很慢
配置阿里云镜像的pypi(Python 编程语言的软件存储库):
在Windows中定位目录:C:\Users\Administrator
新建目录:pip
进入pip目录后新建配置文件:pip.ini
点击pip.ini配置文件单右选择“编辑
输入阿里源的配置命令:
[global]
index-url = https://mirrors.aliyun.com/pypi/simple/
[install]
trusted-host=mirrors.aliyun.com
保存退出,在命令行中输入 pip install pygame 进行测试
pip命令格式: pip <command> [options]
查看帮助:pip help
升级pip:pip install --upgrade pip 或者 pip install -U pip
安装:pip install 包名
安装指定版本:pip install 包名==版本号(如:pip install matplotlib\==3.4.1)
临时指定源来安装:pip install -i pip源地址 包名
清华: https://pypi.tuna.tsinghua.edu.cn/simple
阿里云: http://mirrors.aliyun.com/pypi/simple/
中国科技大学 https://pypi.mirrors.ustc.edu.cn/simple/
华中理工大学: http://pypi.hustunique.com/
山东理工大学: http://pypi.sdutlinux.org/
豆瓣: http://pypi.douban.com/simple/
例:pip install -i http://mirrors.aliyun.com/pypi/simple/ pygame
下载包但是不安装:pip download 包名 -d "某个路径"
卸载:pip uninstall 包名
更新:pip install --upgrade 包名
查看所有安装的包:pip list
查看需要升级包:pip list -o
查看某个包信息:pip show -f 包名
第一个python程序:九九乘法表
import time #导入模块
print("Loading:",end='')
for i in range(5):
print(".",end = '',flush = True)
time.sleep(0.5)
print("\n\t\t\t九九乘法表")
print(end='\t')
for i in range(1,10):
print(i,end='\t')
print()
print(end='\t')
for i in range(1,34):
print(end='-')
print()
for i in range(1,10):
print(i,end='\t')
for j in range(1,10):
if i>=j:
print(i*j,end='\t')
print()
运行:点击RUN 或 绿三角 或 ALT+SHIFT+F10 或 F9
注释
作用:更易于阅读理解代码,编译时会忽略,运行结果不显示,但在代码维护、解释、测试等等方面,发挥着不可或缺的重要作用,具体的注释专题,有大量的高水平文章和论述,请自行搜索并学习
语法:
单行注释:#注释内容 ,一般用于解释语句
#!/usr/bin/python3
# 下面这个方法的作用是…..
# 第一个注释
# 我是单行注释
# 这是一个空的函数,它什么都不干。本条注释也是句废话。
defmain():
pass # pass表示占位,什么都不做。那我为什么要注释它呢???
pass语句是占位语句,它什么都不做,只是为了保证语法的正确性而写。以下场景中,可以使用pass语 句:
当你不知道后面的代码怎么写的时候
当你不需要写代码细节的时候
当语法必须,又没有实际内容可写的时候
其它的一些你觉得需要的场景
多行注释:‘’’注释内容’’’ 或 “””注释内容””” ,一般用于python的文件、模块、类等添加版权、功能等注释信息,并为 _doc_文档提供内容,这些内容可以通过现成的工具,自动收集起来,形成帮助文档,也是一种文档注释
def func(a, b):
""" 这个是函数的说明文档。
:param a: 加数
:param b: 加数
:return: 和
"""
return a+b
class Foo:
"""
这个类初始化了一个age变量
"""
def __init__(self, age):
self.age = age
==需要强调的是这类注释必须紧跟在定义体下面,不能在任意位置==
代码头两行
很多时候,我们在一些py脚本文件的开头都能看到类似的以#开头的这样两行代码,它们不是注释,是一些设定
#!/usr/bin/env python
# # -*- coding:utf-8 -*-
第一行,用于指定运行该脚本的Python解释器,Linux专用,windows不需要。env方式下,系统会自动使用环境变量里指向的Python
第二行,是程序自己本身的字符编码方式,-*-没有特殊作用,只是美化代码
代码规范(PEP8:python增强建议书8代码样式指南)
通过缩进表示代码块包含控制关系,不需要写{},一般推荐为tab(4个空格)或空格,同一代码块空格个数必须一致
一行可以书写多条语句,使用分号隔开,但不推荐,因为这样会造成阅读理解困难,维护耗时,容易出错,若一条语句太长可以使用(\)反斜杠实现多行语句,如:
string = "i love this country,"\
+"because it is very beautiful!"\
+"how do you think about it?"\
+"Do you like it too?"
在 [], {}, 或 () 中的多行语句,可以不需要使用反斜杠(),直接回车,接着写。例如:
result = subprocess.Popen("ipconfig /all",
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
shell=True, check=True)
PEP8建议:每一行的字符不超过80个。该换行时咱就换行!
区分大小写字母
变量不需要直接定义即可使用
print 默认输出是换行的,如果要实现不换行需要在变量末尾加上 end=""
2.第二章 基本数据类型
2.1概念:按被定义的性质、表示形式、占据空间大小、构造特点进行分类,结构如下。
list列表 一维数组 []
tuple元组() 不能该值
dictionart { }
2.2.常量
2.2.1.概念:在程序运行期间,值不会发生变化的量,一般通过人工初始
化或键盘输入实现
2.2.2整数(int)
十进制格式:数字、正负号组成,位数任意 如:100、256、0、-248,python3可以使用下划线 _ 对数据进行分割,以便阅读记忆
a=21_47_48_36_47
b=-2048
C=0123
八进制格式:以0o开头或00开头,后面跟上八进制数字0-7,如:0o12 0o7770o789(错误)
python2中八进制是以0开头的注意:可以调用oct()方法输出八进制
a=7777
print(oct(a))
十六进制格式:以0x或0X开头,后面跟上十六进制数字(0-9,A-F),如:0 xFFFF0x25 0xAA -0x456 可以使用hex()函数实现十六进制的输出
a=65535
print(hex(a))
二进制格式:以0b或者0B开头后跟上0或1,逢二进一,如:0b10110B1101,调用bin()函数实现二进制的输出
a=127
print(bin(a))
2.2.3 浮点数(float)
小数表示法:由符号、数字、小数点组成,如:-2.5,3.0 ,15.
科学计数法:又叫指数表示法,由符号、尾数、阶码符号(E或e)、阶码数字组成 如:xey
如 -2.5e3 -> -2.5*10^3 3E5 3.4e-3
原则如下: xEy
E后必为整数
e后不能由空格
x和y一个都不能少
注意:注意:浮点数运算可能出现小数位不确定的情况,如:0.1+0.2数学上为0.3,实际python解释器计算时为0.30000000000000004,这是由于浮点数转为二进制时会有误差,尽量避免浮点数的比较
如
if 0.1+0.7 == 0.8:
print('yes')
else:
print('no')
2.2.4 布尔类型(boolean)
作用:用于表示真与假,本质为数字类型
组成:True False
True和False 第一个字母必须大写
意义:True表示1,False表示0,可以进行数学运算,如
print(True+1) # 2
注意:python2中无布尔类型,使用1和0表示
2.2.5 字符串
本质:python中的字符串本质是一种序列,其值本质为串首地址,是一个抽象的概念,值不可改变
定界符:‘单引号’ ”双引号“ ”“”三引号“”“
注意:定界符首尾得相同
三引号使字符串分布多行
a="""china
china
china"""
作用:以反斜杠(\)开头的特定字符串序列,表述特殊功能的字符串
常见转义字符
转义字符 | 作用 |
\n | 回车换行hang |
\r | 回车(输入点置为行首) |
\t | 制表符,tab键 |
\b | 退格键,光标向左移动一列(不会删除) |
\f | 换页 |
\\ | 输出一个反斜杠 |
\' | 输出一个单引号 |
\" | 输出一个双引号 |
\000 | 空 |
\yyy | 以开头后跟三位八进制 |
\xyy | 以x开头后跟2位十六进制数字 |
print('\100',\x40')
print('a\bi\'lh\bovi\be\'\\\byou\'\n')
输出为:i'love'you'
a被i盖住了 会覆盖
转义字符功能失效:使得转义字符功能失效,只需在定界符之前增加r或R
print(r'c:\windows\new') 或print('c:\\windows\\new')
2.3变量
2.3.1变量名
变量名又称为标识符,用于标识变量空间、函数、类等的名称
组成:字母、下划线、数字组成,不能以数字开头,name:mod_123 3word(错误) a.dat(错误) print
注意:变量名字母区分大小写
变量名不能使用python保留字(关键字),保留字查看
import keyword
print(keyword.kwlist)
#结果
['False', 'None', 'True', 'and', 'as', 'assert', 'async', 'await', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield']
python以下划线开头的标识符有特殊意义,一般需要避免使用
单下划线开头,如:_ width,表示不能直接访问的类属性双下划线开头,如: _ _ add,类私有成员双下划线开头和结尾,_ _ _init _ _()构造函数
python支持汉语变量名,但不推荐,
中国='china'
print(中国)
2.3.2.变量定义·格式:变量名=value(=念做赋值,不是等于)python中变量不需要声明类型,通过存储的数据动态变化
a = 4
b = 'china'
c = []
d = 95
e = a+d
新的变量通过赋值动作进行开辟内存空间,保存数据,若变量未赋值直接引用会抛出异常
X
print(x)
Traceback (mostrecentcalllast):
File"D:\python\testl\test.py",line1,in<module>
X
NameError:name'x'isnotdefined
变量类型是通过赋值动态变化的:
number =2048
print(type(number))
number'china'
print(type(number))
number =3.14
print(type(number))
#结果:
<class'int'>
<class'str'>
<class'float'>
#type()测试数据类型的函数
2.3.3 变量是什么
python中一切数据皆为对象,变量是对象的引用
对象是分配的一块内存空间,拥有特定的值,支持特定的操作,是一种容器
例子
a=b=1024
print(id(a),id(b))
a=2048
print(id(a),id(b))
a=2系统执行2步,建立一个对象空间存储数据2,对其贴上标签2进行绑定
a=10,将标签a从存储数据2的对象空间中撕下来,贴到存储10的对象空间中
b=a,表示对象10贴了2个标签a和b
变量是一个系统表元素,拥有指向对象的链接空间,可以理解为是一种标签或名字
2.3.4 整形变量对象占用字节数
import sys
print(sys.getsizeof(int()))
print(sys.getsizeof(float()))
#结果 24 24
import sys
a=0
print('a=0',sys.getsizeof(a))
a=1
print('a=-1',sys.getsizeof(a))
a=-1
print('a=1',sys.getsizeof(a))
a=2**30-1
print('a=2**30-1'sys.getsizeof(a))
a=2**30
print('a=2**30'sys.getsizeof(a))
a=2**60-1
print('a=2☆*60-1',sys.getsizeof(a))
a=2**60
print('a=2**60',sys.getsizeof(a))
python3中不再区分int(普通) 和 long int (长整型),统称int
python3中int型是动态长度,理论支持无限大的数字(不能超出虚拟内存大小)
结论:python3中int型数据0占用24B,其它占用28B,每逢230增量4B,float数据占24B
2.4.运算符与表达式
2.4.1.常见云算符优先级
运算符 | 作用 |
** | 幂(最高优先级) |
~ + - | 取反 、 正号 、 负号 |
* / % // | 乘 除 取余 取整数 |
+ - | 加法 减法 |
>> << | 右移 左移 |
& | 按位与 |
^ | 按位异或 (相同为0 , 不同为1) |
| | 按位或 |
<= < > >= | 比较运算符 |
== != | 等于 不等于 |
is is not | 身份运算符 |
in not in | 成员运算符 |
not and or | 逻辑运算符 |
= %= /= //= += -= &*= | 赋值运算符 |
, | 逗号运算符 (最低) |
2.4.2.算术运算符
组成:+·*/川(取商的整数)**(幂)
除法():结果为浮点数,如:1/2->0.5
整除():又称为地板除,计算除法,返回值不大于除法结果的一个最大整数,余数舍弃 7//3 -> 2 -9//2 -> -5
例:计算一元二次方程的2个实根,a!=且b^2-4ac>0
import math
a = float(input('请输入二次项系数'))
b = float(input('请输入一次项系数'))
c = float(input('请输入常数项'))
x1 = (-b+math.sqrt(b*b-4*a*c)) / (2*a)
x2 = (-b-math.sqrt(b*b-4*a*c)) / (2*a)
print('x1=', x1, 'x2=', x2)
注意:math.sqrt()开平方根函数,之前需要导入,input()是输入函数,由于返回值为字符串则需要使用floati进行强制类型转换
取余(%)
取出表达式的余数即模运算,取余左右两边可以为小数,a%b结果符号与除数b相同,且除数b不能为0
例子:5%3-> 2 3%5-> 3 1.5%2-> 1.5 3.5%2-> 1.5 -1%2-> 1 5%-2> -1 50%30->20
例子:输入一个四位数,输出每一位及后三位
如:1234
千位:1
百位:2
十位:3
个位:4
后三位:234
x = int(input('请输入一个四位数:'))
print('千位=', x//1000)
print('百位=', x//100%10)
print('十位=', x//10%10)
print('个位=', x%10)
print('后三位=', x%1000)
常见数学运算函数
int():强制类型转化为int型
float():强制转为float型
str():强制转为字符串
abs():返回整数的绝对值
math.modf(): 返回小数的整数部分和小数部分
math.sqrt(): 计算算术平方根
round(x,n):四舍五入,保留n位小数
例:对浮点数进行四舍五入,如8.32433->8.32 8.32533->8.33
#法一
x=float(input('请输入一个四位数:))
print(round(x,2))
#法二
x=float(input('请输入一个四位数:'))
X=int(x*100+0.5)/100
print('四舍五入:',x)
8.3233*100
832.533+0.5
833.033int
833/100
8.33
2.4.3 赋值运算符
简单赋值运算符
作用:将赋值运算符右侧的结果存储到左侧空间中,本质为覆盖
注意:赋值运算符左侧只能是变量,例:3=5 错误, a+1=10 错误
例子:交换变量
#法一
a=3
b=5
t=a
a=b
b=t
print(a,b)
#法二
a=3
b=5
a=a+b#a->8
b=a-b#b->3
a=a-b#a->5
print(a,b) #空间复杂度小
#法三
a=3
b=5
a,b=b,a
print(a,b)
#法四
a=3
b=5
a=a^b #按位异或
#0011
#0101
#110#a=6
b=a^b
#0110
#0101
#0011#b=3
a=a^b
#0110
#0011
#0101#a=5
print(a,b)
复合赋值运算符
符号:+= -= *= /= %= //= ……
作用:复合赋值运算,运算时进行展开
例子:
a=5
a+=2->a=a+2
a=5
a*=3+2 # a=a*(3+2) #注意:展开后原右侧表达式会自带圆括号,提升优先级
print(a)
2.4.4 关系运算符
组成:> >= < <= == !=
作用:进行比较运算
结果:关系运算符组成的关系表达式运算结果为true (1成立) ,false(0不成立)
例子:true > 0 ->true
a<b<c 等价于a<b and b<c
例子: x%2==0 (常用) !(x%2) x==x//2*2 偶数的判断
注意:== 表示左右结果是否相等,与 赋值号=应有所区别,如:a=12==3 a->False
2.4.5 身份运算符:is
作用:用来判断两个变量是否引用自同一个对象,即is是用来判断两个变量的地址是否相同,is not 是判断两个变量是不是引用自同一个对象
例子:在pycharm脚本模式下执行
a=1000
b=1000
print(a==b)#true
print(aisb)#true
print(id(a),id(b))
#脚本执行时,会被认同为一个代码块,变量值若以存在,会被重用
例子:在交互式的命令提示符中输入(console):
>>>a=b=1000 # 用一个代码块
>>>print(aisb )
#true
#a=b=1000,命令行中一行为一个代码块,在同一个代码块中初始化对象时,会检查其值是否已存在,若存在直接重用
>>>a=50
>>>b=50
>>>print(aisb)
#true
>>>a=256
>>>b=256
>>>print(aisb)
#True
>>>a=257
>>>b=257
>>>print(aisb)
#flase
#python的垃圾回咋机制有一个称为“小整数对象池”技术,为了优化执行速度,节省内存存储空间,解释器会把[-5,256]之间的数据提前存放至小整数对象池空间中,程序中只要引用到[-5,256]之间的整数则不会重新建立内存空间,都是引用对象池中的数据,若超出其范围则会重新开辟内存空间来存储
2.4.6逻辑运算符
优先级:not > and > or
注意:
x or y : x为真,值为x ,短路运算
x and y : x为假 ,值为假 ,短路运算
数字零、空对象、特殊对象None都被认作False
2.4.7成员运算符 : in 和 not in
python独有的运算符(都是小写字母),用于判断对象是否是某个集合的元素之一,运算速度快,返回值为布尔类型
例:
list1 = [1, 2, 3, 4, 5, 6]
a = 1
if a in list1:
print('a是list1的元素之一')
else:
print('a不是list1的元素')
2.4.8三目运算符
格式:result= 为真的结果 if 判断条件 else 为假时的结果
例
a = int(input())
b = int(input())
max = a if a>b else b
print(max)
2.5输入与输出
2.5.1标准print()函数实现输出
格式:print(*objects,sep=' ',end='\n',file=sys.stdout)
参数
object:表示输出对象,数量自定,输出多个对象时xu'y增加逗号作为间隔符
sep:间隔符,默认为一个空格
end:用来设定什么作为输出结尾,默认为\n,
file:要写入的文件对象
输出示例
print(1, 2, 3, 4, 5) #1 2 3 4 5
print(1, 2, 3, 4, 5, sep=',') # 1,2,3,4,5
print('hello', 'world') # hello world
print('www.openlab.com') # www.openlab.com
print('www', 'openlab', 'com', sep='.') # www.openlab.com
for i in range(5):
print(i, end='\t') #0 1 2 3 4
for i in range(100):
print(i, end='\t')
if i%10 == 0:
print()
print()
str = 'hello '
print(str*2) # 注意:* 表示复制几份
print(5*str) # hello hello hello hello hello
print(str+'wprld') # 注意: + 表示字符串链接 hello wprld
fp = open(r'd:\test.txt', 'w') # 打开文件
print('2023,你好', file=fp)
fp.close() # 关闭文件
2.5.2 格式化print()输出
无符号八进制:%o,无符号十六进制:%x(%X),无符号整数:%u,整数:%d
num1=10
num2=20
print('八进制输出:0o%o,0o%o'%(nUm1,num2))
#八进制输出:0o12,0o24
print('十六进制输出:0x%X,0x%X'%(nUm1,nUm2))
#十六进制输出:0xA 0x14
%f:浮点型数据,小数后6位,第7位四合五入
print('%f'%1.23456789)
%e:科学计数法输出
print('%e'%123.456) #1.23456e+02
%g:保留六位有效数字的前提下,使用小数方式,否则使用科学计数法
%s:输出字符串
print('%s'%'china')
2.5.3 带有修饰符的格式化输出
%md:表示输出m位十进制,m位最小列宽,默认右对齐,若小于m位,则左起补空格,若大于m列,则原样输出,例子:
a=123
b=456
print('%5d' % a) #输出 123 左边两空格
print('%2d' % a) #输出123 原样输出
print('%05d' % a) #输出00123
print('%-5d%d' % (a,b) #输出123 456 左对齐
%m.nf:表示输出float小数,m为总宽度(包含小数点),n为小数位数,小于n表示小数位数不足则右起补零,大于n则n+1位四舍五入,m省略时值同n
a=123.456
print('%10.4f'%a) # 123.4560
print('%10.2f'%a) # 123.46
print('%.2f'%a) #123.46
str = 'hello world'
print('%10.2s'%str)
# he
print('%-10.2s%s'%(str,str))#he hello world
2.5.4使用input()函数实现输入
格式:变量名=input(提示文字)
返回值:字符串
注意:需要使用强制类型转换函数进行转换
age=int(input('请输入年龄:'))
2.6图形化程序设计
2.6.1Turtle是python()内置的绘图函数,可以实现线条、矩形、圆等形状绘制
2.6.2 常见方法
方法 | 作用 |
showturtle() | 显示当前的位置及方向 |
write(string) | 绘制一个文本字符串 |
forward(int) | 向箭头方向移动int个像素并绘制直线 |
right(int) | 转向int度 |
color(string) | 颜色 |
goto(int,int) | 移动到指定位置 |
penup() | 抬起笔 |
pendown() | 放下笔 |
circle(int) | 绘制半径为int的圆 |
done() | 绘制完毕 |
import turtle
turtle.pensize(10) # 粗细
turtle.right(60) # 画笔转向
turtle.forward(100)
turtle.right(120)
turtle.forward(100)
turtle.right(120)
turtle.forward(100)
turtle.done() # 三角形
import turtle
t.pensize(10)
t.color('red')
t.right(72)
t.forward(100)
t.right(144)
t.forward(100)
t.right(144)
t.forward(100)
t.right(144)
t.forward(100)
t.right(144)
t.forward(100)
t.done()
import turtleast
t.pensize(5)
t.color('blue')
t.penup()
t.goto(-110,-25)
t.pendown()
t.circle(45)
t.penup()
t.color('black')
t.goto(0,-25)
t.pendown()
t.circle(45)
t.penup()
t.color('red')
t.goto(110,-25)
t.pendown()
t.circle(45)
t.penup()
t.color('yellow')
t.goto(-55,-75)
t.pendown()
t.circle(45)
t.penup()
t.color('green')
t.goto(55,-75)
t.pendown()
t.circle(45)
t.done()
第三章 程序流程控制
3.1顺序结构
3.1.1程序设计的一般面向过程思路
变量初始化(名称 个数 初始值)
输入(input())
处理 (算法)
输出 (print())
3.1.2原则:自顶向下,逐步细化,由上到下逐条执行,即书写顺序就是执行顺序,清晰第一,效率第二
3.1.3 例:输入一个华氏温度,要求输出摄氏温度,公式,c=5/9*(f-32)
#定义变量初始化 输入
F=int(input('请输入一个华氏温度'))
#算法
c=5/9*(F-32)
#输出
print('摄氏温度',c)
3.1.4例子:从键盘输入2个整数a和b,合成一个新四位数c a=12 b=34 c=1324
a = int(input('请输入一个两位数:'))
b = int(input('请输入一个两位数:'))
c = a//10*1000+b//10*100+a%10*10+b%10
print('新四位为:', c)
3.1.5例子:财务人员给员工发工资时经常遇到如下问题:根据每个人的工作金额计算人民币的张数,且要求总张数最少
z = int(input('请输入金额'))
print('100的张数', z//100)
z = z%100
print('50的张数', z//50)
z = z%50
print('20的张数', z//20)
z = z%20
print('10的张数', z//10)
z = z%10
print('5的张数', z//5)
print('1的张数', z%5)
3.1.6例子:输入三角形的三边长度,计算面积:
已知三角形三边长度为a,b,c,面积公式为:area=sqrt(s(s-a)(s-b)(s-c))其中s=(a+b+c)/2
import math
a = int(input('a='))
b = int(input('b='))
c = int(input('c='))
if (a+b<= c) | (a+c<= b) | (b+c<= a):
print('该三边无法形成三角形')
else:
s = (a+b+c) /2
area = math.sqrt(s* (s-a) * (s-b) * (s-c))
# area = (s * (s - a) * (s - b) * (s - c))**0.5
print('area=', area)
3.2 选择结构
3.2.1 单分支结构
语法:
if 表达式:
语句块
流程图:
例1:输入2个数,输出最大值
a = int(input())
b = int(input())
max = a
ifa<b:
max = b
print('max=', max)
注意:
表达式一般由常量,变量,关系表达式,逻辑表达式组成
优先级:!(非)> 算术 > 关系 > and > or
if之后的表达式只检测是否为非0或非空,非空字符串
注意分支缩进
3.2.2 双分支结构
语法:
if 表达式:
语句块1
else:
语句块2
流程图
例1:输入一个整数,判断奇数偶数
num = int(input('请输入数字:'))
if num%2 == 0:
print('偶数')
else:
print('奇数')
例2:输入一个数,判断是否被7或11整除,不能同时整除
num = int(input('请输入数字:'))
if (num%7 == 0 or num%11 == 0) and num%77!= 0:
print('yes')
else:
print('no')
例3:判断是否是闰年
year = int(input('请输入四位数的年份:'))
if year%4 == 0 and year%100!= 0 or year%400 == 0:
print('闰年') # 能被4整除但不能被100整除或者能被400整除
else:
print('平年')
3.2.3多分枝结构
语法1:
if 表达式1:
语句块1
else:
if表达式2:
语句块2
else:
if 表达式3:
语句块3
……
语句2:
if表达式1:
语句块1
elif 表达式2:
语句块2
elif 表达式3:
语句块3
else:
……
程序流程图:
例子:输入一个百分制成绩,输出等级成绩
x>=90 优秀
90>=x>=80 良好
80>=x>=60 合格
x<60 补考
#法一
num = int(input('请输入一个百分制成绩:'))
if num<0 or num>100:
print('请再输入0-100之间的程序')
else:
if num>= 90:
print('优秀')
else:
if num>= 80:
print('良好')
else:
if num>60:
print('合格')
else:
print('补考')
#法二
num = int(input('请输入一个百分制成绩:'))
if num<0 or num>100:
print('请再输入0-100之间的程序')
elif num>= 90:
print('优秀')
elif num>= 80:
print('良好')
elif num>60:
print('合格')
else:
print('补考')
3.2.4注意:
if和else之后的冒号不能省略
else elif不能单独使用必须配合if进行处理
if-else是通过tab缩进表达控制关系,需要注意
3.3 循环结构
3.3.1while循环
格式:
while 条件表达式:
循环体
流程图:
3.3.2 for循环
格式:
for 迭代的变量 in 对象(列表等):
循环体
for 迭代变量 in range(start,step)
循环体
range()函数
python3内置函数,用于生成一系列的连续整数
start:计数的起始值,省略则为0
end:计数的终止值,不包含,如:range(7),代表生成0-6,end参数不可省略
step:步长,若省略默认为1
例子:计算1+2+3+4+……100
# while
sum = 0
i = 1
while i<= 100:
sum += i
i = i+1
print(sum)
# for
sum = 0
for i in range(1, 101):
sum += i
i += 1
print('sum:', sum)
注意
循环条件一般为关系表达式或者逻辑表达式,为非0时执行循环体,0时循环结束
循环条件尽量使用开区间
循环嵌套:长循环在内短循环在外以减少循环跨越次数,提高效率
for i in range(10):
for j in range(3):
pass
for j in range(3): # 选择
for i in range(10):
pass
3.4 程序实例
3.4.1 累加和
框架
sum=0
for i in range(终止值):
sum=sum+新项
新项一般与循环迭代变量i有关或者与前后项关系有关
例子:计算1+1/2+1/3+1/4+……1/100
sum = 0
for i in range(1, 101):
sum = sum+1/i;
i += 1
print('sum=', sum)
#结果sum= 5.187377517639621
例子:计算1-1/2+1/3-1/4+1/5……-1/100
sum = 1
f = -1
for i in range(2, 101):
sum = sum+1/i*f
f = -f # 符号位切换
print('sum=', sum)
#sum= 0.688172179310195
例子:计算1+1/2-1/3+1/4-1/5……+1/100
sum = 1
f = -1
for i in range(2, 101):
sum = sum+1/i*-f
f = -f
print('sum=', sum)
计算下列多项式:
n = int(input('n:'))
sum1 = 0
sum2 = 0
for i in range(1, n+1):
sum1 = sum1+i
sum2 = sum2+1/sum1
print('sum=%.6f', sum2)
例子:计算下列多项式的结果:前20项之和
新的分子=旧的分子+旧分母新的分母=旧分子
a = 2
b = 3
sum = 0
for i in range(20):
sum = sum+b/a
t = a+b
m = b
b = t
a = m
print('sum=.6f'%sum)
例子:计算下列多项式的结果:n的值
pi = 1
i = 3
f = -1
while 1/i>1e-6:#多项式某项值大于1e-6说明误差太大需要独述铁代
pi = pi+1/i*f
f = -f
i += 2# 分母
print('pai=%.6f'% (pi*4))
例子:用泰勒级数计算e的近似值,e=1+1/1!+1/2!+1/3!+……1/n!
sum = 1
t = 1
i = 1
while 1/t>1e-6:
t = t*i
sum = sum+1/t
i += 1
print('e=%.6f'%sum)
#e=2.718282
例子:计算a+aa+aaa+aa...aa ,若a=2,计算前6项之和
2 a=2
22 a=a*10+2 ? a
222
2222
22222
a = 2
sum = 0
for i in range(6):
sum += a
a = a*10+2
print('sum=', sum)
#sum=246912
3.4.2 素数判断
break语句:终止当前循环,执行循环外的下一跳语句,一般会和if配对使用,例:计算的r=1到r=10的圆面积,直到100为止
import math
for r in range(1, 11):
area = math.pi*r*r
if area>100:
break
print('r:', r, 'area is :%.6f '%area)
continue语句:跳出当次循环,继续执行下一次循环,continue语句之后循环语句之前所有的语句不再执行,例子:计算100到150之间不能被3整除的数,要求一行输出10个(加速循环)
i = 0
for n in range(100, 151):
if n%3 == 0:
continue
print(n, end=' ')
i += 1
if i%10 == 0:
print()
for-else结构:for循环执行完毕(for循环不是通过break跳出而中断的)或者未进入循环的情况下执行else后的语句
for i in range(1, 100):
if i%2 == 0 and 1%3 == 0 and 1%5 == 0:
print('%d是2、3、5的最小公倍数'%i)
break
else
print('未找到')
执行过程:当for循环正常执行完毕(range()中超出范围)则执行else之后的语句块,若执行break异常跳出循环则不会执行else后的语句块此例中break不可删除,若删除则不能保证找到最小公倍数,同时由于没有中断机制使得for顺利执行完毕则会执行else后的语句块,输出结果矛盾
注意:for…if......break..else…为基本结构
while......else也同理
素数:只能被1和自己整除
例子:输入一个整数,判断是否为素数
#法1
prime=int(input('请输入一个大于等于2的整数:'))
if prime<2:
print('数据错误,请输入大于等于2的整数')
else:
for i in range(2,prime):
if prime%i==0:
print('平数')
break
else:
print('素数')
例子:
#法2
i=2
prime=int(input('请输入一个大于等于2的整数:'))
if prime<2:
print('数据错误,请输入大于等于2的整数')
else:
while prime%i:
i=i+1
if i == prime:
print('素数')
else:
print('平数')
例3:
#筛选法:素数的倍数一定不是素数,给出序列2-50,去掉2的倍数,去掉3的倍数,去掉4的倍数……,剩余一定为素数
3.4.3 穷举搜索
原则:在指定范围内寻找符号条件的数
框架:
for i in range(起始值,终止值):
if 条件判断:
处理
例子:输出100以内的素数
for i in range(2, 100): # 穷举2-99之间
for j in range(2, i-1): # 判断i是否为素数
if i%j == 0:
break
else:
print(i, end=' ')
例2:输出大于m且紧随m的k个素数,如:m=5,k=3,结果为:7 11 13
m = int(input('请输入起始值'))
k = int(input('请输入个数:'))
i = m+1 # 从m+1开始搜索
count = 0# 记录找到的素数个数
while count<k: # 找到的素数个数小于要求的个数时需要继续查找
for j in range(2, i): # 判断素数
if i%j == 0:
break
else:
print(i) # 输出素数
count += 1 #记录素数个数
i = i+1 # 方便下一次搜索
例3 输出200-400之间的非素数
for i in range(200, 400):
for j in range(2, i):
if i%j == 0:
print(i, end=' ')
break
例子:输出水仙花数:是一个三位数、每一位的立方和等于原值,153=1^3+5^3+3^3
for i in range(100, 1000):
if (i%10) **3+ (i//10%10) **3+ (i//100) **3 == i:
print('水仙花数:', i)
#水仙花数: 153
#水仙花数: 370
#水仙花数: 371
#水仙花数: 407
例子:输出1000以内的完数,完数:因子之和等于原值,6==1+2+3
for i in range(6, 1000): #穷举6-999
sum = 0#因子之和清零
for j in range(1, i): # 查找因子
if i%j == 0:
sum += j
if sum == i: # 判断完数
print(i, end='\t') # 6 28 496
例子:查找100以内的同构数,同构数:一个正整数出现在它的平方数右侧,如:5==25 6==36
25==625
for i in range(1, 100):
if i == i*i%10 or i == i*i%100:
print(i, end='\t')
#1 5 6 25 76
例子:输出100以内能被9整除余数为2的整数,并计算平均值的平方根
sum = 0
a = 0
num = 0
for i in range(1, 100):
if i%9 == 2:
print(i, end=' ')
num = num+1
sum += i
a = (sum/num) **0.5
print()
print(a)
3.4.4 数学问题
例1:判断回文数
m = int(input('请输入整数:'))
n = m
t = 0
while n>0: # 得相反的数字
t = t*10+n%10
n = n//10
if t == m:
print('yes')
else:
print('no')
例2:求整数a与b的最小公倍数
#法1
a = int(input('请输入第一个整数:'))
b = int(input('请输入第二个整数:'))
i = 1
while 1: # 恒真执行
if i%a == 0 and i%b == 0:
print('最小公倍数:', i)
break # 由于升序检索,找到第一个公倍数时就跳出,保证为最小公倍数
i = i+1#a=5 b=7 循环35次
#法2
a = int(input('请输入第一个整数:'))
b = int(input('请输入第二个整数:'))
i = 0
while 1: # 恒真执行
i = i+a
if i%b == 0:
print('最小公倍数:', i)
break # 由于升序检索,找到第一个公倍数时就跳出,保证为最小公倍数
#a=5 b=7 循环7次
例3:输入一个四位数正整数,输出其对应的英文单词,如:1024 one zero two four
m = int(input('请输入四位数正整数'))
t = 1000
if m>= 1000 and m<= 10000: # 防止输入数据超出范围
while t>0: # 数字位数大于0
if m//t%10 == 0: # 判断属于0到9中
print('zero', end=' ')
elif m//t%10 == 1:
print('one', end=' ')
elif m//t%10 == 2:
print('two', end=' ')
elif m//t%10 == 3:
print('three', end=' ')
elif m//t%10 == 4:
print('four', end=' ')
elif m//t%10 == 5:
print('five', end=' ')
elif m//t%10 == 6:
print('six', end=' ')
elif m//t%10 == 7:
print('seven', end=' ')
elif m//t%10 == 8:
print('eight', end=' ')
elif m//t%10 == 9:
print('nine', end=' ')
t = t//10 # 由左向右取数
else:
print('数据有误')
例4:输出斐波那契数字 1 1 2 3 5 8……
a1 = 1
a2 = 1
for i in range(10):
print(a1, a2, end=' ')
a1 = a1+a2 # 当前项等于前两项之和
a2 = a1+a2
例5:在Fibonacci数列中输出大于t的最小值,如:t=10 输出13
a1 = 0
a2 = 1
a3 = 1
t = int(input('请输入一个正整数:'))
while a3<= t:
a1 = a2
a2 = a3
a3 = a1+a2 # 当前等于前2项之和
print('最小值', a3)
例6:有一张足够大的纸,厚度为0.09mm,问对这多少次后其厚度超过珠穆朗玛峰的高度(8848m)
a = 0.09e-3
n = 0
while a<8848:
a = a*2
n += 1
print('对折次数:', n)
例7:爱因斯坦阶梯问题:有多级台阶,每步跨2阶余1阶,每步跨3阶余2阶,每步跨5阶余4阶,每步跨6阶余5阶,每步跨7阶都正好到顶,问阶梯总数
n = 7
while 1:
if n%2 == 1 and n%3 == 2 and n%5 == 4 and n%6 == 5:
break
n = n+7
print('阶梯总数:', n)
例8:百钱买百鸡问题:鸡翁值钱五,鸡母值钱三,鸡雏三只一钱,百钱买百鸡,鸡翁、鸡母、鸡雏各几何?
for cocks in range(101):
for hens in range(101):
for chicks in range(101):
if cocks+hens+chicks == 100 and cocks*5+hens*3+chicks//3 == 100 and chicks%3 == 0:
print('公鸡=', cocks, '母鸡=', hens, '小鸡=', chicks)
例9:搬砖问题:36人搬36块砖,男搬4、女搬3、2个小孩抬一块砖,一次性搬完需要男、女、小孩各多少人
for man in range(37):
for woman in range(37):
for children in range(37):
if man+woman+children == 36 and man*4+woman*3+children//2 == 36 and children%2 == 0:
print('男孩:', man, '女孩:', woman, '孩子:', children)
例10:猴子偷桃:一次吃一半还要多吃一个,第7天吃完,问偷桃总数
n = 0
for i in range(7): # 逆置
n = (n+1) *2
print('总数:', n)
3.4.5 打印如下图像
分析:
打印7行
每一行需要打印空格,星号,\n
h = int(input('请输入图像高度:'))
for i in range(h): # 打印4行
for j in range(h-i-1): # 输出空格
print(' ', end='')
for k in range(2*i+1): # 输出星号
print('*', end='')
print()
3.5综合案例:打印日历
3.5.1需求分析
输入:年份四位,如:2023,月份:1-12
输出:标准日历
结构:
for循环结构
if-else 结构
功能:
打印总标题:=====2023年1月======
打印日历列标题:一 二 三 四 五 六 日
打印每月的日期:方阵
输入月份的判断:1-12月
判断闰年
判断大月:1 3 5 7 8 10 12
判断小月:4 6 9 11
判断2月:闰月为29 平月 28
调用泰勒公式判断每月第一天是星期几
输出每月日期时需要逢7折行
蔡勒公式:
w:0-6 对应星期日到星期六
c:年份前2位
y:年份后2位
m:1月、2月为上一年的13月及14月
d:日
y = int(input('请输入四位数年份:'))
m = int(input('请输入月份:'))
t = 0 # 标志位,表示为否为闰年
if y%4 == 0 and y%100!= 0 or y%400 == 0:
t = 1 # 标识位置为闰年标志
if m == 1 or m == 3 or m == 5 or m == 7 or m == 8 or m == 10 or m == 12:
d = 31 # 大月天数
elif m == 2 and t == 0: # 当前m为2月且为平年
d = 28
elif m == 2 and t == 1:
d = 29
elif m == 4 or m == 6 or m == 11: # 判断小月
d = 30
if m>= 1 and m<= 12: # 保证月份在1-12之间
print('\n======', y, '年', m, '月', '======\n')
if m == 1:
y = y-1
m = 13
elif m == 2:
y = y-1
m = 14
# 蔡勒公式:计算1582年10月4日之后任意日期是星期几
w = (y%100) + (y%100//4) + (y//100//4) - (2* (y//100)) +26* (m+1) //10+1-1
w = (w%7+7) %7 # 保证为正数
if w == 0:
w = 7 # 泰勒公式中计算星期几默认为0-6,即星期日为0,此程序修改为星期日为7
print('一\t二\t三\t四\t五\t六\t日')
i = 1
while i<w:
print('\t', end='')
i = i+1 # 将本月第一天与星期几对齐
i = 1
while i<= d: # 输出本月每一天的值,并逢7换行
print('%2d'%i, '\t', end='')
w = w%7 # 逢7换行
if w%7 == 0:
print()
w = w+1
i = i+1
print('\n==========================\n')
else:
print('输入错误')
import calendar
y = int(input('请输入四位数年份:'))
m = int(input('请输入月份:'))
cal = calendar.month(y, m)
print(cal)
3.6 建议
3.6.1 多看官方文档
3.6.2 面向搜索引擎的编程
3.6.3 规范命名
3.6.4认认真真注释
3.6.5 不要重复性的造‘轮子’
3.6.6 多读多写代码
3.6.7 预留开发时间
3.6.8 大胆的重构
3.6.9师傅领进门,修行靠个人
4 第四章 容器
4.1 容器的概念
python中可以包含其它对象的对象,称之为容器,是一种数据结构
4.1.2 常用的容器:序列(列表、元组),映射:字典
4.2列表
4.2.1概念:将多种数据类型使用逗号分割后放置在中括号中的一组可变序列
4.2.2 创建列表
格式:listname=[元素1,元素2,元素3……元素n]
listname:列表名,必须符合标识命名规则
元素:列表项,个数无限制,可以为任意合法的数据类型
例子:
num=[2,5,8,13,1.2]
str1 ['china','hello','world']
str2=[45.6,he11o','中国']
创建空列表:
t1=1ist()
t2=[]
print(tl,t2)
print(type(t1),type(t2))
#<class 'list'> <class 'list'>
使用range()循环迭代创建列表
t3 = list(range(10, 20, 2))
print(t3)
注意
list()函数用于生成列表或类型转换,其中内容必须为可迭代对象,若为不可迭代的对象则报错,如:t4=list(10)
将列表转换为列表无意义且浪费资源
t5 = [1, 2, 3, 4, 5]
t6 = list(t5)
print(t6)
4.2.3删除列表
格式1:del listname
team = ['皇马', '拜仁', '利物浦']
delteam
print(team)
格式2:listname.clear() ,清空列表中的内容,框架还存在
team = ['皇马', '拜仁', '利物浦']
team.clear()
print(team) # 结果: []
4.2.4通过索引访问列表
作用:在序列中每一个元素都有一个唯一的编号(下标),用于访问操作
原则:由左向右从0开始递增,也可以由右向左从-1开始递减,例:
team=[114,98.6,'world','春眠不觉晓']
114 | 98.6 | world | 春眠不觉晓 |
索引:0 | 1 | 2 | 3 |
索引: -4 | -3 | -2 | -1 |
引用:listname[索引] ,例:team[0] team[-1]
注意:空列表时不可以通过索引引用
4.2.5列表输出:print(listname)
4.2.6列表的切片
作用:通过列表切片操作可以访问一定范围的列表元素,也可以生成新列表
格式:listname[start : end : step]
start: 切片开始的索引(包含),若省略则为0
end:切片截止的索引(不包含),若省略则为整个列表长度
step:切片长度,若省略则为1,step省略则最后一个冒号也可以省略,若为负值则由由向左反向切片
t1 = [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
# 0 1 2 3 4 5 6 7 8 9
# -10 -9 -8-7 -6 -5 -4 -3 -2 -1
print(t1[0:7:4]) # 从0索引开始到6索引,间隔四个元素
print(t1[1:5]) # 从1索引访问到4索引
print(t1[2:]) # 从2索引开始到整体长度
print(t1[:]) # 四种写法意义相同
print(t1[::])
print(t1[0:])
print(t1)
print(t1[:-1]) # 从0索引访问到-2索引
print(t1[::-1]) # 倒置访问
print(t1[0:6:0]) # 报错,step不能为0
4.2.7列表的相加
作用:将相同类型的序列进行连接操作,但不会去除重复值
符号:+
例:
t1 = ['hello']
t2 = ['world']
t3 = t1+t2
print(t3)
注意:列表不能与字符串常量进行连接吗,否则报错
t1=['hello','world']
print(t1+'china')
4.2.8列表相乘
作用:使用数字乘以一个列表相当于进行复制
符号:*
t1=['hello','world']
print(t1*3)
print(2*t1)
4.2.9列表包含与不包含检查
作用:检查某个列表是否包含某数值
格式:value in listname 或者 value not in listname
4.2.10常用的列表的函数
计算列表长度:len(listname)
计算列表最大值:max(listname)
计算列表的最小值:min(listname)
计算列表元素之和:sum(listname)
4.2.11列表遍历
处理数值:
for item in listname:
处理item
处理索引与数值
for index,item in enumerate(listname):
处理index 和 item
例1:输出列表中的最大值
importrandom
t1 = random.sample(range(10, 30), 10) # 在10-30 之间产生10个随机数
print(t1)
max = t1[0] # 保存列表中第一个元素
foriint1:
ifmax<i:
max = i
print('max=', max)
importrandom
t1 = random.sample(range(10, 30), 10) # 在10-30 之间产生10个随机数
print(t1,'\t','max=',max(t1))
例2:将列表中索引为奇数且值为偶数的元素输出
import random
t1 = random.sample(range(10, 30), 10) # 在10-30 之间产生10个随机数
print(t1)
for index, item in enumerate(t1):
if index%2 == 1 and item%2 == 0:
print('索引:', index, '值:', item)
例3:将列表中索引为奇数且值为偶数的元素不处理剩余输出
import random
t1 = random.sample(range(10, 30), 10) # 在10-30 之间产生10个随机数
print(t1)
for index, item in enumerate(t1):
if index%2 == 1 and item%2 == 0:
pass # 不处理
else:
print('索引:', index, '值:', item)
例4:筛选法:输出素数
t1 = list(range(0, 101))
print(t1)
i = 2 # 从索引2开始,索引与值相同
while i<100:
j = t1[i] *2 # 计算倍数
while j<100: # 倍数置为0
t1[j] = 0
j = j+t1[i]
i = i+1
while t1[i] == 0: # 跳过已经被置为0的元素
i = i+1
for i in range(2, 100):
if t1[i] != 0:
print(t1[i], end=' ')
#2 3 5 7 11 13 17 19 23 29 31 37 ……
4.2.12 列表中添加元素
添加元素:listname.append
例1:将值为奇数、下标为偶数的值存储到另一个列表中
import random
t1 = random.sample(range(10, 30), 10)
t2 = []
print(t1)
for index, item in enumerate(t1):
if index%2 == 0 and item%2 == 1:
t2.append(item)
print(t2)
注意:append()是一个列表内置方法,用于将元素或列表追加到另一个列表的尾部,extend ( )整列表追加
4.2.13 删除元素
根据索引删除:del listname[index]
根据内容删除:listname.remove(obj)
例:删除列表的指定元素
import random
t1=random.sample(range(10,30),10)
print(t1)
n=int(input('请输入需要删除的元素:'))
ift1.count(n)>0: # 先判断元素是否存在
t1.remove(n)
print(tl)
4.2.14 列表统计
格式
:listname.count(obj)
作用:获取列表中某元素出现次数,只能精确匹配,count()一般与remove()配对使用
4.2.15列表的排序:
sort()方法排序
格式:listname.sort(key=None , reverse=False)
key:元素排序时比较的键
reverse:排序规则,Ture为降序,False为升序,默认为升序
注意:sort()内置方法会改变列表的值,返回值为None
import random
t1 = random.sample(range(10, 30), 10)
print('排序前:', t1)
t1.sort()
print('升序排序后:', t1)
t1.sort(reverse=True)
print('降序排序后:', t1)
使用内置函数sorted()排序,可以不改变列表的值进行排序
格式:sorted(listname , key=None , reverse=False)
例:对列表进行降序排序
import random
t1 = random.sample(range(10, 30), 10)
print('排序前:', t1)
print('升序排序后:', sorted(t1))
print(t1) # 原始数据未变
使用选择法完成列表排序:
import random
t1 = random.sample(range(10, 30), 10)
print('排序前:', t1)
for i in range(len(t1) -1):
for j in range(i+1, len(t1)):
if t1[i] >t1[j]:
t1[i], t1[j] = t1[j], t1[i]
print('升序排序后:', t1)
插入排序:
import random
t1 = random.sample(range(0, 20), 20)
print('排序前:', t1)
for i in range(1, 20):
t = t1[i] # 备份待插入元素
j = i-1
while j>= 0 and t<t1[j]:
t1[j+1] = t1[j] # 比t大的向右覆盖
j = j-1
t1[j+1] = t # 补上插入元素
print('排序后:', t1)
4.2.16列表查找
index()方法:用来查找某个元素在列表中第一次出现的位置(索引值),若该元素不存在则会导致异常,最后使用count()方法进行判断
格式:listname.index(obj, start , end)
obj:查找的元素
start:起始位置
end:结束位置(不包含)
返回值为索引
list1 = [40, 65, 89, 6, 2, 100, 7, -2.5, -999]
print(list1.index(2))
print(list1.index(100, 3, 7))
print(list1.index(7, 4)) # 检索4之后元素
# print(list1.index(500)) # 不存在会抛出异常
使用in 和 not in 查找列表元素
list1 = [40, 65, 89, 6, 2, 100, 7, -2.5, -999]
print(2inlist1)
print(500notinlist1)
例:使用二分法查找列表元素(折半查找),要求列表必须有顺序则必须先排序
import random
t1 = random.sample(range(0, 20), 20)
t1.sort()
print(t1)
n = int(input('请输入查找元素:'))
i = 0
j = 20-1
while i<= j:
mid = (i+j) //2 # 计算中间元素索引
if t1[mid] == n: # 中间元素比较
print('找到了,值:', n)
break
else:
if n<t1[mid]:
j = mid-1 # 向左折半
else:
i = mid+1 # 向右折半
if i>j:
print('未找到')
4.2.17列表倒置
格式:listname.reverse()
例:
import random
t1 = random.sample(range(0, 20), 20)
print(t1)
t1.reverse()
print(t1)
4.2.18列表元素组合
作用:将列表元素组合成一个字符串
格式:char.join(seq)
char:是组合后的分隔符
seq:表示处理的对象,必须为列表、元组等序列元素
char = '-'
list1 = ['silicon', 'stone', 'education']
print(char.join(list1))
print('=='.join(list1))
print('\n'.join(list1))
# 结果:
silicon-stone-education
silicon==stone==education
silicon
stone
education
4.2.19列表的浅拷贝与深拷贝
列表之间的赋值
list1 = [1, 2, 3, 4]
list2 = list1
print(id(list1), id(list2))
for i in range(len(list1)):
list1[i] += 1 # list1列表中元素值加1
print(list1)
print(list2) # 值相同
分析:列表的赋值相当于取别名,即两者名称都指向同一个堆栈区地址列表对象,操作任意一个,另一个同步变化
列表浅拷贝
list1 = [1, 2, 3, 4]
list2 = list1.copy() # list2是list1的浅拷贝
print(id(list1), id(list2))
for i in range(len(list1)):
list1[i] += 1 # list1列表中元素值加1
print(list1)
print(list2) # 内容不同
# 结果:
19482213712641948221337984
[2, 3, 4, 5]
[1, 2, 3, 4]
分析:list2是列表list1的浅拷贝结果,id值与list1列表不同,这是因为通过浅拷贝时会产生一个新的地址列表与list2绑定,与list1地址列表完全不同,地址不同相互隔离。
注意:列表中有可变数据类型进行浅拷贝时无效,如:
list1 = [1, 2, [3, 4]]
list2 = list1.copy() # list2是list1的浅拷贝
print(id(list1), id(list2))
list1[0]+=1
list1[1]+=1
list1[2][0]+=1
list1[2][1]+=1
print(list1)
print(list2)
print(id(list1[2]))
print(id(list2[2]))
分析:list1列表有2个不可变的数据元素1和2,其进行改变并没有影响list2,但list1中可变元素[3,4]若改变则list2也会随之改变,list1与list2并没有完全隔离开来,虽然list1与list2的内存总的地址列表项相互独立但列表第三项绑定了同一个字列表,不能实现完全的地址隔离,若需要完全独立则需要深拷贝。
深拷贝
import copy
list1 = [1, 2, [3, 4]]
list2 = copy.deepcopy(list1) # list2是list1的深拷贝
print(id(list1), id(list2))
list1[0]+=1
list1[1]+=1
list1[2][0]+=1
list1[2][1]+=1
print(list1)
print(list2)
print(id(list1[2]))
print(id(list2[2]))
分析:通过深拷贝,字列表进行隔离,从实现与原列表真正的完全隔离
4.2.20列表推导式
作用:使用列表推导式可以生成新列表
格式:listname=[表达式 , for 循环变量 in range() ]
例1:创建0-19的数值列表
list1 = [x for x in range(20)]
print(list1)
相当于:
list1 = []
for x in range(20):
list1.append(x)
print(list1)
例2:创建范围100以内的20个整数的随机数列表
import random
# randint()产生一个随机数
list1 = [random.randint(0, 100) for i in range(20)]
print(list1)
根据旧列表产生一个新列表:newlistname=[表达式 , for 循环变量 in 旧列表名],例:
import random
list1 = [random.randint(0, 100) for i in range(20)]
list2 = [x/2 for x in list1] # 根据旧列表产生数值折半的新列表
print(list1)
print(list2)
例:根据旧列表产生数值为偶数的新列表
import random
list1 = [random.randint(0, 100) for i in range(20)]
list2 = [x for x in list1 if x%2==0 ] # 根据旧列表产生数值为偶数的新列表
print(list1)
print(list2)
注意:使用列表推导式创建新列表,应尽量简短,若代码超过2行则代码可读性降低,应考虑改为for循环
4.2.21程序实例
例1:将20个随机的十进制数存储到列表中,计算列表的奇数平均值、偶数平均值
import random
import numpy # 需要安装
list1 = random.sample(range(0, 50), 20)
ave1 = []
ave2 = []
foriinlist1:
ifi%2 == 1:
ave1.append(i)
else:
ave2.append(i)
print('奇数平均值:', numpy.mean(ave1))
print('偶数平均值:', numpy.mean(ave2))
print('偶数方差值:', numpy.var(ave2))
# 推导式写法
import random
import numpy
list1 = random.sample(range(0, 50), 20)
ave1 = [if or i in list1 if i%2 == 1]
ave2 = [if or i in list1 if i%2 == 0]
print('奇数平均值:', numpy.mean(ave1))
print('偶数平均值:', numpy.mean(ave2))
print('偶数方差值:', numpy.var(ave2))
例2:编写程序输入一行空格作为分隔符的数字,去重后输出该列表
原始:1 2 3 2 4 2 5 6 2
结果:123456
list1 = input('请输入空格间隔的数值:').split() # split()函数用于将字符串切片为字符串列表
for i in range(len(list1)): # 将字符串列表中每个元素转为数值型
list1[i] = int(list1[i])
print(list1)
list2 = []
for i in list1:
# 把list1中数据拿到list2中统计个数,若为0个则说明第一次出现,需要追加
if list2.count(i) == 0:
list2.append(i)
print(list2)
例3:将2个有序的列表合并成一个新的有序列表
list1 = list(eval(input('请输入第一个列表:'))) # eval() 用于将逗号间隔的字符串转为列表
list2 = list(eval(input('请输入第二个列表:'))) # eval() 用于将逗号间隔的字符串转为列表
list1.extend(list2) # list2追加到list1的尾部
list1.sort()
print(list1)
例3:编写程序判断列表是否为升序
list1 = list(eval(input('请输入第一个列表:')))
f = 1
for i in range(len(list1) -1):
if list1[i] >list1[i+1]: # 判断当前项是否大于右侧数据
f = 0
break
if f:
print('The list is already sorted')
else:
print('The list is not sorted')
例4:输入一个十进制转为二进制
m = int(input('请输入一个整数:'))
list1 = []
ifm == 0:
print('0000')
else:
while m:
m, r = divmod(m, 2) # divmod(x,y) 计算x%y返回商和余数
list1.append(r) # 将余数追加到新列表中
list1.reverse() # 逆序存储
print(list1)
例5:将列表中前p个元素平移到列表尾部
1 2 3 4 5 6 7
4 5 6 7 1 2 3
import random
list1 = random.sample(range(0, 50), 10)
print(list1)
p = int(input('请输入平移个数:'))
for i in range(p): # 将前p个元素移动到尾部
list1.append(list1[i])
list1 = list1[p:] # 利用切片覆盖原列表
print(list1)
4.2.22二维列表
创建格式1:listname=[[一维列表1],[一维列表2],[一维列表3],……,[一维列表n]]
list1 = [[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]
print(list1)
创建格式2:for循环创建
list1 = []
for i in range(行值):
list1.append([])
for j in range(列值):
list1[i].append(j)
print(list1)
创建格式3:列表推导式创建(常用)
list1 = [[jforjinrange(4)] foriinrange(3)]
print(list1)
例1:二维列表的随机数赋值
import random
list1 = []
for i in range(4):
list1.append([])
for j in range(5):
t = random.randint(10, 30)
list1[i].append(t)
for i in range(4):
print(list1[i])
例2:计算二维列表中每行最大值及每列最小值
import random
list1 = []
for i in range(4): # 创建二维列表
list1.append([])
for j inrange(5):
t = random.randint(10, 30)
list1[i].append(t)
for i in range(4):
print(list1[i])
max1 = []
min1 = []
for i in range(4): # 计算每一行的最大值
max1.append(max(list1[i]))
for j in range(5):
min1.append(list1[0][j]) # 存储每一列的第一个元素值
for i in range(4):
if min1[j] >list1[i][j]:
min1[j] = list1[i][j]
print('每行最大值:', max1)
print('每列最小值:', min1)
二维列表局部处理 : 只能处理行==列的正方形二维列表
左下半三角元素
foriinrange(行):
forjinrange(列):
ifi>j
处理
右上半三角元素
foriinrange(行):
forjinrange(列):
ifi<j
处理
主对角线:
foriirange(行):
处理list1[i][i]
副对角线:
foriirange(4):
处理list1[i][行-i-1]
例:打印杨辉三角的前10行
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
规律:第0列为1 ,主对角线为1 ,左下半三角元素为=上方值+左上方值
list1 = []
for i in range(10): # 创建10*10的二维列表,填充数值0
list1.append([])
for j in range(10):
list1[i].append(0)
for i in range(10):
print(list1[i])
for i in range(10):
for j in range(10):
if j == 0 or i == j: # 第0列 主对角线为数值1填充
list1[i][j] = 1
else:
if i>j: # 左下半三角元素填充表达式结果
list1[i][j] = list1[i-1][j] +list1[i-1][j-1]
for i in range(10):
for j in range(10):
if i>= j: # 只输出左下半三角元素及主对角线元素
print(list1[i][j], end=' ')
print() # 输出为方阵
二维列表的周边元素处理:计算4*6的二维列表周边元素的平均值
import random
list1 = []
for i in range(4):
list1.append([])
for j in range(6):
t = random.randint(10, 30)
list1[i].append(t)
for i in range(4):
print(list1[i])
sum = 0
for i in range(4):
for j in range(6):
if i == 0 or j == 0 or i == 4-1 or j == 6-1:
sum += list1[i][j]
print('平均值:', sum/16) # 注意周边元素的个数可能重复计算
4.3元组
4.3.1概念:元组(tuple)是一种使用园括号括起不可变数据类型元素集合
4.3.2==注意:元组中元素个数与值不可以改变,又称为不可变列表==
4.3.3元组中不允许的操作
修改、增加元素
删除元素(但可以整体删除元组)
如:remove、append、insert、pop等方法不可使用
4.3.4创建元组
格式:tuplename=(元素1,元素2,元素3……,元素n)
元素个数无限制、类型可以都不相同
num1 = (2, 3, 4, 5, 6)
num2 = (1,) # 重要,创建一个元素的元组,结尾逗号不能省略
num3 = (1) # 不是元组,只是数值为1的对象
num4 = () # 空元组
num5 = tuple(range(1, 10)) # 使用tuple()函数创建批量数据转为元组
str1 = ('china', 'hello', '123456') # 内容为字符串的元组
str2 = (82, 'python', '中国', [1, 2, 3, 4, 5]) # 混合类型元组
tup1 = 1, 2, 3, 5 # 定义元组时,可以省略园括号
print(type(tup1))
4.3.5整体删除元组
==注意:元组是不可变序列,存储的元组不可删除,但允许整体删除元组==
格式:del tuplename
tup1 = (12, 34, 56)
tup1[1] = 100 # 报错
Traceback (mostrecentcalllast):
File"D:\python\test1\test.py", line2, in<module>
tup1[1] = 100
TypeError: 'tuple'objectdoesnotsupportitemassignment
# 允许整体操作
tup1 = (12, 34, 56)
tup1 = (67, 89, 23, 45) # 允许整体修改
tup2 = tup1*2
print(tup2)
tup3 = tup1+tup2
print(tup3)
4.3.6注意:
元组只保证一级子元素不可变,对于嵌套的元素,不保证不可变
tup1 = (12, 34, 56, ['a', 'b'])
tup1[3][0] = 'A'
tup1[3][1] = 'B'
print(tup1)
# tup1元组嵌套可变序列列表,可以改变列表的元素
tup1 = (12, 34, 56, ('a', 'b'))
tup1[3][0] = 'A'
tup1[3][1] = 'B'
print(tup1)
Traceback (mostrecentcalllast):
File"D:\python\test1\test.py", line2, in<module>
tup1[3][0] = 'A'
TypeError: 'tuple'objectdoesnotsupportitemassignment
# tup1元组嵌套了一个元组,依然不可变
元组支持列表的相关操作,但注意以下问题
元组连接(+)时必须维持类型还是元组,即连接对象不能是字符串或列表
tup1 = (1, 2, 3)
list1 = [4, 5, 6]
# tup2 = tup1 + list1 # 报错
# tup3 = tup1 + 'china' # 报错
元组连接只有一个元素的元组时,必须加逗号
tup1 = (1, 2, 3)
tup2 = tup1+ (4,) # (4,)不能写成(4)
元组切片:切片与列表操作方式相同
import random
tup1 = tuple(random.sample(range(30), 10))
print(tup1)
print(tup1[1:3])
print(tup1[:4])
print(tup1[5:])
print(tup1[-2:])
print(tup1[-3:3:-1]) # 倒序
print(tup1[0:5:3])
元组的方法与函数与列表基本相同,更改内部元素的方法与函数都不可用
tup1 = (1, 2, 3, 4, 5, 6)
print(len(tup1), max(tup1), min(tup1))
print(sorted(tup1, reverse=True))
元组与列表数据互换
list():转为列表的函数
tuple():转为元组的函数
tup1 = (123, 'hello', 45.6)
list1 = list(tup1)
print(list1)
list1.append('china')
print(list1)
tup1 = tuple(list1)
print(tup1)
# 注意:可以将元组转为列表进行插入删除等操作,在转为元组,间接实现‘修改’元组
4.3.7元组与列表区别
元组与列表都属于序列,都可以按照特定的顺序存储一组数据,类型不受限制
区别:
列表为可变序列,元素可以任意删除、修改、插入
元组为不可变序列,元素不能做上述操作
元组不支持:append(),extend(),insert(),remove()等方法
元组与列表一样支持切片操作
元组比列表结构简单、占用资源少,能保护数据不被意外删除,比列表安全性要高
4.4字典
4.4.1概念:字典属于可变序列,使用“键:值(key:value)”的方式==配对==存储数据,类似于新华字典中“拼音:汉字”之间的映射关系
4.4.2格式:dictionary={key1:value1 ,key2:value2,……,keyn:valuen}
dictionary为字典名称
字典使用花括号{}作为标志
key为元素的键,必须唯一,且不可变,可以是字符串、数字、元组
value:元素的值,可以为任意数据,不需要唯一
4.4.3创建字典
dict1 = {'andy': 1001, 'fox': 1002, 'alice': 1003}
dict2 = {} # 创建空字典
dict3 = dict() # 函数初始化为空字典
print(dict1)
print(dict2)
print(dict3)
name = ['春香', '秋兰', '夏凝', '翠花']
sign = ['天秤座', '射手座', '金牛座', '双鱼座']
dict4 = dict(zip(name, sign)) # zip() 函数将列表或元组组合为字典
print(dict4)
dict5 = dict(a=98.5, b=88.7, c=55.9, d=77.3)
print(dict5)
注意:使用key=value方法创建字典时,key不能为常量必须为变量标识符
4.4.4字典访问
格式:dictname[键]
dict1 = {'name': 'zara', 'age': 18, 'class': 'first'}
print(dict1['name'], dict1['age'], dict1['class'])
通过key访问value
4.4.5字典元素增加
格式:dictname[键]=值
dict1 = {'西瓜': 5, '香蕉': 8, '荔枝': 10}
dict1['橘子'] = 6
print(dict1)
dict1['荔枝'] = 12
print(dict1)
4.4.6字典删除
删除特定元素:del 字典名[键]
清空字典内容:dictname.clear()
整体删除字典:del 字典名
dict1 = {'西瓜': 5, '香蕉': 8, '荔枝': 10, '草莓': 15}
del dict1['西瓜']
print(dict1)
dict1.clear()
print(dict1)
del dict1
4.4.7使用get()方法获取指定的值
格式:dictname.get(key, default)
key:指定键
default:可选,用于指定键不存在时返回的默认值,若省略则返回None
dict1 = {'西瓜': 5, '香蕉': 8, '荔枝': 10, '草莓': 15}
print(dict1.get('香蕉'))
print(dict1['香蕉'])
print(dict1.get('火龙果'))
print(dict1.get('车厘子',50)) # 访问的将不存在则执行default
4.4.8字典遍历
格式1:items()方法:返回(键:值)数据对
for i in dictname.items():
处理i
dict1 = {'西瓜': 5, '香蕉': 8, '荔枝': 10, '草莓': 15}
for i indict1.items():
print(i)
格式2:键:值方法
for key,value in dictname.items():
处理key和value
name = ['春香', '秋兰', '夏凝', '翠花']
sign = ['天秤座', '射手座', '金牛座', '双鱼座']
dict1 = dict(zip(name, sign))
for i, j in dict1.items():
print(i, '的星座是:', j)
格式3:keys():返回字典所有的键 , values():返回所有的值
name = ['春香', '秋兰', '夏凝', '翠花']
sign = ['天秤座', '射手座', '金牛座', '双鱼座']
dict1 = dict(zip(name, sign))
for i in dict1.keys():
print(i)
for j in dict1.values():
print(j)
4.4.9字典的fromkeys()方法
作用:建立字典的一种字典内置方法
格式:newdictname=dict.from.keys(seq,value)
seq:建立的字典列表,默认为键
value:字典的值,若省略为None
sq=['name','city']
dict1=dict.fromkeys(sq)
print(dict1)
4.4.10注意:字典的键不允许重复,否则只会记住后一个键的值
dict1 = {'num': 1001, 'score': 98.5, 'num': 1002}
print(dict1)
4.5集合
4.5.1概念:集合是一种无序==不重复==的元素集,一般用于去重和关系测试
4.5.2集合使用花括号进行括起
4.5.3创建集合
格式:setname={元素1,元素2,……元素n}
set1 = {1, 2, 3, 4, 5, 6}
set2 = {'name', 'num', 'age', 'score'} # 集合本质为无序可变序列,输出时可能顺序不同
set3=set('命运给与我们的不是失望之酒,而时机会之杯')
set4=set([1,2,3,4,5,6,7,8,9])
set5=set() # 空集合,不能使用{}
set6=set(('apple',)) # 创建只有一个元素的集合,需要加逗号
4.5.4集合的应用核心:去重
list1 = [1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5]
set1 = set(list1)
list1 = list(set1)
print(list1)
# 或 print(list(set(list1)))
4.5.5集合的添加与删除
添加元素:setname.add(元素)
set1 = set(['java', 'c', 'c#', 'android'])
set1.add('python')
print(set1)
set1.add('python') # 添加重复值会被保留一个
print(set1)
删除元素:
setname.remove(元素): 删除指定元素
setname.pop():随机删除一个元素
setname.clear() :清空内容
set1 = set(['java', 'c', 'c#', 'android'])
set1.remove('c')
print(set1)
set1.pop()
print(set1)
set1.clear()
print(set1)
4.5.6集合交并差集
交集:&
并集: |
差集: -
对称差集: ^ , 排除共同部分
例:
set1 = set('abcdefg')
set2 = set('efghijk')
print(set1&set2)
print(set1|set2)
print(set1-set2)
print(set1^set2)
#结果
{'e', 'g', 'f'}
{'b', 'i', 'c', 'd', 'a', 'g', 'k', 'j', 'f', 'e', 'h'}
{'b', 'a', 'c', 'd'}
{'b', 'i', 'd', 'a', 'c', 'k', 'j', 'h'}
4.5.7子集和父集
issubset():测试是否为子集,返回True或False
set1 = {1, 2, 3, 4}
set2 = {1, 2, 3, 4, 5, 6, 7, 8, 9}
print(set1.issubset(set2))
issuperset() : 测试是否为父集,返回True或False
set1 = {1, 2, 3, 4}
set2 = {1, 2, 3, 4, 5, 6, 7, 8, 9}
print(set2.issuperset(set1))
4.5.8集合追加到另一个集合
格式:update():将一个集合追加到另一个集合
set1 = {1, 2, 3, 4}
set2 = {5, 6, 7, 8, 9}
set1.update(set2)
print(set1)
4.5.9删除集合内与另一个集合重复的元素
格式:difference_update()
set1 = {1, 2, 3, 4}
set2 = {4, 5, 6, 7}
set1.difference_update(set2)
print(set1)
4.5.10冻结集合
概念:set是可变集合,使用frozenset可以改变集合为不可变序列,即冻结集合,定义好之后不允许修改,可以参考元组
x=frozenset([1,2,3,4,5])
x.pop() # 报错
Traceback (mostrecentcalllast):
File"D:\python\test1\test.py", line2, in<module>
x.pop()
AttributeError: 'frozenset'objecthasnoattribute'pop'
4.5.11查看集合内置方法:print(dir(set))
4.6列表、元组、字典、集合的区别
数据结构 | 是否可变 | 是否重复 | 是否有序 | 定义符号 |
列表(list) | 可变 | 可重复 | 有序 | [ ] |
元组(tuple) | 不可变 | 可重复 | 有序 | ( ) |
字典(dictionary) | 可变 | 可重复 | 无需 | {key:value} |
集合(set) | 可变 | 不可重复 | 无序 | { } |
4.7字符串
4.7.1概念:字符串是由‘和“包裹起来的任意不可变文本序列
print('吉多.范罗苏姆外号"龟叔"')
4.7.2拼接字符串:+
str1 = 'hello,'
str2 = '记忆是一种相遇,遗忘是一种自由'
print(str1+str2)
str1 = '剑未佩妥,出门已是江湖'
str2 = 2048
print(str1+str2)
# 报错,字符串不可以与数值数据连接
str1 = '剑未佩妥,出门已是江湖'
str2 = 2048
print(str1+str(str2)) #可以转为字符串在进行连接操作
4.7.3多行字符串
字符串多余一行时,可以使用三引号(三个双引号)将字符串包夹起来
str1 ="""china china
china china
china
"""
4.7.4字符串切片
原则:字符串属于不可变的序列,可以通过切片操作截取字符串
格式:string[start , end ,step]
str1 = '2023,加油,中国'
print(str1) #2023,加油,中国
print(str1[0]) #2
print(str1[5:]) #加油,中国
print(str1[:3]) #202
print(str1[2:6]) #23,加
print(str1[1:10:2]) #03加,国
print(str1[-1:-3:-1]) #国中
例:输入员工身份证号,输出出生日期
str1 = input('请输入身份证号:')
if int(str1[16]) %2 == 1:
print('性别:男')
else:
print('性别:女')
print('出生日期为:'+str1[6:10] +'年'+str1[10:12] +'月'+str1[12:14] +'日')
4.7.5分割合并字符串
分割字符串:将字符串分割为列表
格式:strname.split(sep,maxsplit)
sep:指定的分割符,可以包含:空格 \t \n None ,
maxsplit:指定分割次数,若省略则为1,
str1 = 'Python 解释器官网 >>> https://www.python.orgstr1 = 'Python 解释器官网 >>> https://www.python.org'
print('原串:', str1) # 原串: Python 解释器官网 >>> https://www.python.org
list1 = str1.split() # 默认为空格
print(list1) # ['Python', '解释器官网', '>>>', 'https://www.python.orgprint(list1) # ['Python', '解释器官网', '>>>', 'https://www.python.org']
list2 = str1.split('>>>')
print(list2) # ['Python 解释器官网 ', ' https://www.python.orgprint(list2) # ['Python 解释器官网 ', ' https://www.python.org']
list3 = str1.split('.')
print(list3) # ['Python 解释器官网 >>> https://wwwprint(list3) # ['Python 解释器官网 >>> https://www', 'python', 'org']
list4 = str1.split(' ', 2) # 2 表示最大切割次数
print(list4) # ['Python', '解释器官网', '>>> https://www.python.orgprint(list4) # ['Python', '解释器官网', '>>> https://www.python.org']
list5 = str1.split(',') # 分隔符未在原串中出现则原样显示
print(list5) # ['Python 解释器官网 >>> https://www.python.org']
合并字符串:将多个字符串采用固定的分隔符进行连接
格式:newstrname=string.join(iterable)
newstrname:合并之后的新字符串
string:合并的固定分隔符
iterable:可迭代对象,即要合并字符串
4.7.6字符串查找
count()方法
作用:检索字符串在另一个字符串中出现的次数,若不存在则返回0
格式:strname.count(sub) sub:要检索的子串
str1 = '****AB*CDE*****'
cnt1 = str1.count('*')
cnt2 = str1.count('%')
print('次数:', cnt1, cnt2) #10 0
str1 = 'aaaaaaaaaa'
cnt1 = str1.count('aa')
print('次数:', cnt1) # 结果为5,不会出现叠加次数
find () 方法
作用:检索是否包含指定字符串,若不存在则返回-1,若存在则返回首次出现的索引值
str1 = input('请输入主串:')
sub = input('请输入子串:')
num = str1.find(sub)
if num>-1:
print('存在,第一次出现的索引值为:', num)
else:
print('不存在')
注意:find()方法一般用于查找子串在主串中是否出现,也可以使用in实现,如:print(sub in str1 ) 返回True ,python还提供rfind()即从右侧开始进行检索
startswitch()方法:检索字符串是否以指定的字符串开头,是则返回True,否则返回False,格式:strname.startswitch(sub)
endswitch()方法:检索字符串是否以指定的字符串结尾,是则返回True,否则返回False,格式:strname.endswitch(sub)
4.7.7字符串大小写转换
大写转小写:strname.lower()
小写转大写: strname.upper()
大小写互换:strname.swapcase()
作用:字符串中大写转小写,小写转大写,原串不变
例:
str1 = input('请输入一个串:')
print(str1.swapcase())
print(str1)
4.7.8判断是否为字母
格式:strname.isalpha() ,成立返回True,否则返回False
str1 = input('请输入字符串')
cnt = {} # 空字典
for i in str1:
if i.isalpha() == True:
cnt[i] = cnt.get(i, 0) +1
print(cnt)
# get(i,0) 计算字典键i的对应值,初始为0
# cnt[i]表示字典的键值
4.7.9字符串删除
strname.strip(char) : 删除字符串左右两边的指定字符
strnamne.lstrip(char) : 删除字符串左侧指定字符
strname.rstrip(char) : 删除字符串右侧指定字符
例:统计单词个数:当前字符不是空格并且下一个字符是空格
str1 = input('请输入字符串:')
str1 = str1.strip() # 移除串头尾的空格
print(str1)
cnt = 1
i = 0
while i<len(str1) -1:
if str1[i] != ' ' and str1[i+1] == ' ':
cnt += 1
i += 1
if str1 == '':
cnt = 0
print(cnt)
例:删除前导星号后导星号所有星号
str1 = '*****ABC***EFG*******'
print(str1.strip('*'))
print(str1.lstrip('*'))
print(str1.rstrip('*'))
print(str1.replace('*', ''))
# str1.replace('*', '') ,replace字符串替换函数,通过查找星号替换为空串实现简介删除
4.7.10程序案例:
例1:编写程序:检测从键盘输入的字符串密码是否是一个合法密码,规则如下:
密码必须至少有8个字符
密码只能为英文或数字
密码至少包含2个数字
str1 = input('请输入密码:')
t = 0
for i in str1:
if i.isdigit(): # 计算字符串中数字个数
t += 1
if len(str1) >= 8: # 计算字符串的长度
if str1.isalnum(): # 判断字符串中是否只包含字母和数字,是返回True
if t>= 2:
print('密码正确')
else:
print('密码中包含的数字少于2个')
else:
print('密码中只能包含字母和数字')
else:
print('密码长度至少有8个字符')
例2:编写程序实现输入二进制字符串转为十进制数字输出,如:1001 结果为 9,相当于计算1*2^0^+0*2^1^+0*2^2^+1*2^3^
str1 = input('请输入二进制:')
str1 = str1[::-1] # 字符串逆序
d = 0 # 接收结果
t = 0 # 权值
f = 1 # f=1表示用户输入的字符串合法
for i in str1:
if i == '1' or i == '0':
d = d+int(i) *2**t
else:
print('无效数字')
f = 0 # 输入的字符串非法则f置为0
break
t += 1
if f == 1:
print('转换的十进制为:', d)
或者使用:
print(int(str1, 2))
```
```
例3:统计字符串中字母的个数并存储到列表b中,要求:字母a存储到b[0],b存储到b[1],z存储到b[25]中
# 法1
str1 = input('请输入字符串:')
b = []
str1 = str1.lower() # 字符串中字母都转为小写
for i in range(26):
b.append(str1.count(chr(97+i)))
print(b)
# chr(97+i) 将97+i的十进制ascii值转为字母
# 将转为的字母拿到str1中进行count()统计,其个数追加到列表中
# 法2
str1 = input('请输入字符串:')
b = [0] *26
str1 = str1.lower()
for i in str1:
if i.isalpha(): # 判断i是否为字母
b[ord(i) -97] += 1
print(b)
# 任意字母ASCII值减去首字母ASCII值为序号
注意:python内置函数:
chr():将数值转为字符
ord():将字符转为ASCII数值
例4:将字符串中大写字母改为为下一个字母,字母Z改写为字母A
str1 = input('请输入字符串:')
for i in str1:
if i>= 'A' and i<= 'Y':
i = chr(ord(i) +1)
else:
if i == 'Z':
i = 'A'
print(i, end=' ')
例5:将2个字符串逆序后交叉合并到原串中
str1:abcdefg
str2:123456789
str3:g9f8r7d6c5b4a321
str1 = input('请输入字符串:')
str2 = input('请输入字符串:')
str3 = ''
str1 = str1[::-1]
str2 = str2[::-1]
i = 0
j = 0
while i<len(str1) orj<len(str2): # 无论长短串都能处理
if i<len(str1):
str3 = str3+str1[i] # + 表示字符串拼接
i = i+1
if j<len(str2):
str3 = str3+str2[j]
j = j+1
print(str3)
例6:字符串排序
str1 = input('请输入字符串:')
list1 = list(str1) # 转为列表
list1.sort()
str1 = ''.join(list1) # 空串连接
print(str1)
例7:排除字符串收尾2个元素,剩余升序排序
str1 = input('请输入字符串:')
str2 = str1[1:len(str1) -1]
list1 = list(str2)
list1.sort()
str2 = ''.join(list1)
print(str1[0] +str2+str1[len(str1) -1])
4.7.11通过format()方法实现模板输出
格式:strname.format(args)
参数分析
strname:字符串的显示样式即模板名称
args:需要转换的部分,如有多项需要使用逗号进行间隔
模板格式:{index : fill align sign # width.precision type}
占位符:{} 和 :
index:索引位置,从0开始,若省略则自动分配
fill : 空白处填充的字符
align:设置的对齐方式,一般与width配合使用
< : 左对齐
>: 右对齐
=:内容右对齐,只针对数字类型,即将数字类型内容放在填充字符的最右侧
^ : 内容居中
sign:指有无符号
+:正数加正号,负数加负号
-: 正数不变,负数加负号
空格:正数加空格,负数加负号
# :值为二、八、十六进制数会显示0b 、0o、0x前缀
width:宽度
.precision: 保留小数位数
type:指定类型
例:
str1 = '编号: {:0>5s}\t公司名称:{:s} \t 官网:http://www.{:s}.com'
str2 = str1.format('1', '百度 ', 'baidu')
print(str2) # 编号: 00001 公司名称:百度 官网:http://www.baidu.com
str3 = str1.format('2', '腾讯 ', 'qq')
print(str3) # 编号: 00002 公司名称:腾讯 官网:http://www.qq.com
str4 = str1.format('3', '字节跳动', 'bytedance')
print(str4) # 编号: 00003 公司名称:字节跳动 官网:http://www.bytedance.com
importmath
print('¥{:,.2f}元'.format(2569+3788)) # ¥6,357.00元
print('{0:E}'.format(5300000.2)) # 5.300000E+06
print('{:.7f}'.format(math.pi)) # 3.1415927
print('二进制:{:#b}'.format(100)) # 二进制:0b1100100
print('八进制:{:#o}'.format(100), '十六进制:{:#x}'.format(100)) # 八进制:0o144 十六进制:0x64
print('天才是由{:.0%}的灵感, 加上{:.0%}的汗水!'.format(0.01, 0.99)) # 天才是由1%的灵感, 加上99%的汗水!
常见格式化字符:
格式化字符 | 作用 | 格式化字符 | 作用 |
s | 字符串 | b | 二进制 |
d | 十进制 | o | 八进制 |
c | unicode字符 | x 或X | 十六进制 |
e或E | 科学计数法 | f或F | 浮点数(6位小数) |
g或G | 自动在f和e之间切换 | % | %字符(6位小数) |
第五章 函数
5.1模块化程序设计
5.1.1基本设计思想:将一个大型程序按照功能分割成若干个小型模块
5.1.2特点
模块相对独立,功能单一,结构清晰,接口简单
减少程序复杂性
提高元器件的可靠性
缩短软件的开发周期
避免程序开发的重复劳动
5.1.3定义函数
- 格式:
def 函数名(形参列表):
"""函数注释"""
程序功能段代码
return 表达式
- 分析
def:定义函数的关键字
函数名:函数的名称,区别其它函数的标签,也是函数所在内存的入口地址,是一个常量,要见名知意
形参:
作用:函数接收数据的变量空间
原则:调用函数时,形参变量分配空间,调用结束空间释放
设计原则:名称、个数
注意:多个形参之间使用逗号分割
函数注释:可选,起到增加函数可读性、理解性,推荐书写
函数体:程序段,实现函数的功能
def summer(list1):
"""这里时函数说明文本的位置
list1:参数列表说明
return:返回值的说明
"""
t = 0
for i in list1:
t += 1
return t
函数代码块以def关键字开头,一个空格之后接上函数标识符与园括号,最后有一个冒号,函数体重第一行一般书写函数注释,最后以return结束,默认返回None
5.2.函数调用
5.2.1作用:传递参数,使用函数功能
5.2.2格式:函数名(实参列表)
5.2.3调用方式
fun(m) : 调用fun函数,传递参数m
n=fun(m) : 调用fun函数,返回值赋值给n
s=s*fun(m) : 调用fun函数,返回值参与后续运算
print(fun(m)) : 调用fun函数,返回值作为另一个函数的参数出现
fun() :调用fun函数,无参,无返回值
5.2.4例1:计算C(m,n)=m!/(n!*(m-n)!)
def fac(x): # 函数定义
facx = 1
for i in range(1, x+1): # 计算阶乘
facx *= i
return facx
m = int(input('请输入m的值:'))
n = int(input('请输入n的值:'))
C = fac(m) / (fac(n) *fac(m-n)) # 调用函数并参与后续运算
print('结果:', C)
5.3 return 语句
5.3.1 作用:表示函数执行到此结束,并且返回return之后的对象,函数若无返回值,则return语句可省略,后台默认返回None
5.3.2注意:一但函数执行到return语句,那么之后函数体若还有语句则不会执行,会被忽略掉,直接跳出函数体
def func():
pass
return # 此时,后面的代码无法执行
print()
abs(-1)
5.3.3注意:python中return可以返回任意对象
5.4函数参数
5.4.1位置参数(必需参数、必备参数):必需按照正确的顺序传递到函数中,实参与形参按位置对齐,个数相同
def fun(str1,str2):
print(str1,str2)
fun('hello','world') # 若省略一个实参则会报错
5.4.2关键字参数:使用形参的名字来确定输入参数的值,实参不需要与形参按位置完全对齐一致
def fun(str1,str2):
print(str1,str2)
fun(str2='world',str1='hello')
5.4.3默认参数:调用函数时,如果没有传入参数,会使用默认参数
def fun(str1,str2='world'):
print(str1,str2)
fun('hello')
注意:
默认值参数必须写在形参列表最后,否则报错
默认值形参尽量指向不可变数据类型的对象
例:面试题:
def fun(a=[]):
a.append('A')
return a
print(fun())
print(fun())
print(fun()) # 结果如下
['A']
['A', 'A']
['A', 'A', 'A']
# 而不是:
['A']
['A']
['A']
# 分析
# 原因:函数体在被读入内存后,默认值参数a指向空列表对象并被创建存储到内存中,默认值参数a也是一个变量,保存了指向对象[]的地址,每次调用函数后,a指向的列表地址不变,始终都是那个[]列表,变化的是内容,测设一下:
def fun(a=[]):
print('函数内部a的地址为:%s'%id(a))
a.append('A')
returna
b=fun()
print('b的值为:%s'%b)
print('函数外部b的地址为:%s'%id(b))
c=fun()
print('c的值为:%s'%c)
print('函数外部c的地址为:%s'%id(c))
d=fun()
print('d的值为:%s'%d)
print('函数外部d的地址为:%s'%id(d))
# 如何避免,使用不可变默认值参数
def fun(a=None):
if a is None:
a=[]
a.append('A')
return a
print(fun())
print(fun())
print(fun())
5.4.4不定长参数(可变参数):传入的参数可以是任意多个
*形参 :一个星号,可以接收多个参数存储到元组中
def fun(str1, *str2):
print(str1, str2)
fun('hello', 'china', 'world', '123456')
# 结果:
hello ('china', 'world', '123456')
def fun(str1, *str2):
print(str1, str2)
fun('hello') # 没有给带星号的形参传递数据则返回空元组
# 结果:
hello ()
**形参:两个星号,以关键字参数形式传入,以字典形式存储
def fun(str1, **str2):
print(str1, str2)
fun('hello', a='world', b='china', c='123456')
# 结果:
hello {'a': 'world', 'b': 'china', 'c': '123456'}
注意:若形参列表中只有单独的星号,对应实参必须以关键字参数形式传递
def fun(str1,*, str2):
print(str1, str2)
fun('hello', str2='world')
5.5函数的递归调用
5.5.1作用:一个函数在它的函数体内部调用自身称为递归调用
5.5.2例:递归计算n!
def fun(n):
if n == 0:
return 0
else:
if n>1:
x = fun(n-1) *n
else:
x = 1
return x
m = int(input('请输入一个正整数:'))
print('阶乘结果:', fun(m))
5.5.3注意
每一次递归都是通过栈(stack)这种数据结构实现的,每次进入递归时,栈会增加一层,函数返回时栈会减少一层,由于栈的大小不是无限制的所以递归调用次数过多时可能会出现栈溢出,为了防止溢出,递归深度不要超过1000层
递归必须在内部使用条件判断的方法来退出递归,否则会出现循环无休止的执行
递归虽然使用程序变得简洁一些,增加程序可读性,但这是以牺牲存储空间为代价,由于每一次递归都会存储相关的变量和参数,会增加时间开销
5.6匿名函数
5.6.1使用lambda关键字创建匿名函数
匿名:不再使用def关键字这样标准的形式来定义函数
lambda只是一个表达式,不是一段代码,函数体一般要比传统的函数要简单
只能在lambda表达式中封装有限的功能及逻辑,也拥有自己的命名空间
5.6.2格式:lambda 参数 :表达式
lambda x: x*x
# lambda是关键字表示匿名函数,冒号前的x表示函数参数,x*x是执行代码
# 相当于
def fun(x)
returnx*x
5.6.3注意:匿名函数只能有一个表达式,不同也不能书写return语句,表达式的结果就是返回值
5.7open()函数
5.7.2格式:f=open(filename,mode,encoding)
open()函数返回值为一个file对象,可以赋值给一个变量
filename:访问的文件名称,一般需要增加路径,本质是一个字符串
mode:打开文件的方式
encoding:字符编码,一般为UTF-8
5.7.3文件的打开方式
模式 | 操作 | 说明 |
r | 只读 | 默认方式,如果文件不存在会报错 |
w | 写入 | 若文件不存在则会新建然后写入,若文件已存在则会清空已有内容在写入 |
a | 追加 | 若文件不存在则会新建然后写入,若文件已存在则会追加数据 |
x | 新建 | 若文件已存在则报错,若文件不存在则会新建再写入,比w模式安全 |
b | 二进制模式 | 以bytes类型操作文件,一般与之前的模式结合使用,如:rb、wb |
+ | 读写 | 如:r+ w+ a+ |
# 打开一个文件
f = open('t1.txt', 'w')
f.write('python 是一种非常好用的语言!')
f.close()
5.7.4 b模式
二进制模式:一般用于读取图片、视频等文件
注意:读写时是以bytes类型读写的,因此获得是一个bytes对象而不是字符串,读写时需要指定字符编码
s='this is a test'
b=bytes(s,encoding='utf-8')
f=open('t2.txt','w')
f.write(s)
f.write(b)
s='this is a test'
b=bytes(s,encoding='utf-8')
f=open('t3.txt','wb') # wb 用于bytes类型
f.write(b)
f.close()
5.7.5 + 模式
w+模式:在读写之前会清空文件内容
a+模式:永远在文件尾部写入
r+模式:读写模式,配合seek()tell()方法可以实现更多操作
5.7.6文件写入方法:write()
作用:将字符串或bytes类型写入文件中
注意:write()一般都是在内存中执行,并不会立刻写入硬盘,当执行到close()方法后才会将数据写入硬盘,如果需要在内存读写且立刻反应到硬盘上则需要执行f.flush方法
5.7.7close()方法:关闭文件对象,当处理完一个文件后,调用f.close()或关闭文件且释放系统资源,文件关闭后,数据会同步到磁盘
第六章 模块与包
6.1模块(Modules)
6.1.1概念:将实现某一特定功能的代码放置在文件中,以便与其它程序进行导入,可以避免函数名或变量名的冲突,该文件称为模块,扩展名.py
6.1.2模块=函数+类+变量
6.1.3分类
内置模块:目前python内置模块大概在200多个,如:
自定义模块:第三方模块
6.1.4模块导入的方法:五种
import 模块名
from 模块名 import 功能名
from 模块名 import *
import 模块名 as 别名
from 模块名 import 功能名 as 别名
6.1.5使用import 导入模块
格式1:import 模块名
格式2:import 模块名1 , 模块名2 ,…… 模块名n
使用方法:模块名.功能名()
import math
print(math.sqrt(9))
6.1.6使用from……import部分导入
意义:使用import导入后会把所有内部功能全部导入到当前的文件中,比较臃肿一些,若需要导入部分功能可以使用from语句
例:
from math import sqrt, floor
print(sqrt(9), floor(10.88))
注意:使用时不需要书写模块名
6.1.7使用as关键字为导入模块或功能命名别名
原因:某些情况下导入的模块或功能名称过长,可以使用较短的别名对齐命名,使用时较为方便
例:
import time as tt
print('hello')
tt.sleep(3)
print('world')
注意:别名命名后不能在使用原有的模块名
6.1.8模块的搜索目录
当使用import语句导入模块时,默认情况下会按照如下顺序进行模块查找:
执行python文件的当前项目目录
环境变量:PYTHONPATH
python解释器安装目录中
可以通过sys.path查找目录的路径:
import sys
print(sys.path)
6.1.9自定义模块
作用:将相关的代码编写在一个单独的文件中,并命名为模块名.py,可以导入到程序中使用,注意自行创建的模块名不能与python自带的标准库中模块名重名
例:新建一个模块文件prime.py,实现素数判断:
def fun_prime(num):
if num<2:
print('请输入大于2的正整数')
else:
for i in range(2,num):
if num%i==0:
return 0
else:
return 1
新建一个python文件加载导入上述模块,实现100以内的素数判断输出
import prime
for i in range(2, 100):
if prime.fun_prime(i) == 1:
print(i, end=' ')
自定义模块中的功能测试
作用:编写完自定义模块后,最好在模块内部对代码进行测试,以防止出现问题
魔方方法:_ _ name _ _ ,每个模块中都会有一个字符串变量,记录模块名称,随着运行页面的不同,返回值结果也不相同
当前页面执行:返回值为_ _ main_ _
def fun_prime(num):
if num<2:
print('请输入大于2的正整数')
else:
for i in range(2, num):
if num%i == 0:
return 0
else:
return 1
print(__name__) #结果:_ _ main_ _
在第三方页面导入执行时,返回值:模块名称
import prime
for i in range(2, 100):
if prime.fun_prime(i) == 1:
print(i, end=' ')
# 输出 prime 模块名
基于以上特性,可以吧_ _name _ _编写在自定义模块汇总,格式如下:
if _ _name _ _ ==' _ _ name_ _ _'
处理
def fun_prime(num):
if num<2:
print('请输入大于2的正整数')
else:
for i in range(2, num):
if num%i == 0:
return 0
else:
return 1
if __name__ == '__main__':
if fun_prime(5) == 1:
print('素数')
else:
print('平数')
6.1.10 os模块
作用:os模块用于处理python的文件及目录
os模块判断系统类型:
import os
print(os.name)
# nt 为windows系统, posix表示linux或mac os
判断目录是否存在
格式:os.path.exists(path)
返回值:存在为True,否则为Fasle
import os
print(os.path.exists('c:\demo')) # 判断目录
print(os.path.exists('test.py')) # 判断文件
创建目录:
创建一级目录:os.mkdir(path)
importos
os.mkdir('c:\\demo')
# 二次执行,会抛出异常,一般会与判断目录是否存在一同使用
import os
path = 'c:\\demo'
if not os.path.exists(path):
os.mkdir(path)
print('目录已创建')
else:
print('目录已存在')
创建多级目录:os.makedirs(path)
递归方式创建目录
例:
import os
os.makedirs('c:\\t1\\t2\\t3')
例:批量创建20个目录
import os
os.mkdir('c:\\python')
for i in range(1,21):
os.mkdir('c:\\python\\第{}次课'.format(i))
删除目录:
格式:os.rmdir(path )
例:
import os
os.rmdir('c:\\demo')
6.2包(package)
6.2.1概念:
将有联系的模块组织在一起放到同一个文件夹下,并且该文件夹下创建一个名称为_ _ init_ _ .py的文件,此集合称为包
6.2.2结构图:
6.2.3 _ _ init _ _ .py文件在创建包之后自动生成,默认为空,作为为:
包的标识,该文件不能删除
文件中定义all 语句规定那些模块可以导入
注意:编写的_ _ init_ _ .py文件不建议编写程序,应保证精简
6.2.4 制作包:左侧侧边栏单右->New->python package->输入包名->回车
导入包
格式1:import 包名.模块名 , 使用模块的方法时:包名.模块名.方法名
格式2:from 包名 import 模块名 , 使用时:模块名.方法名
6.2.5使用pip命令下载安装第三方模块
格式:pip 命令动词 模块名
动词:install list 等,通过pip help
编写模块sort1.py 实现选择法升序排序,通过第三方程序导入使用,模块内部实现自我测试
7.第七章 面向对象
7.1.1概念:
面向对象在编程的时候尽可能去模拟现实世界,其中任何一个操作都需要一个实体来完成,实体就是动作的支配者,没有实体没有动作发生
7.1.2思考:报名学习,分成几步:
开始->学员提出报名,提供相关的资料->学生缴费,获得缴费凭证->教师根据缴费凭证分配班级->班级增加学生信息->结束
上例为由开始到结束,按照流程依次执行,是一种面向过程的思考问题当时
面向对象的分析
第一步:分析那些动作由那些实体发出的:
学生:提出报名
学生:提供资料
学生:缴费
机构:收费
教师:分配教室
班级:增加学生信息
整个过程:一共有四个实体:学生、机构、教师、班级
第二步:定义这些实体,为其添加相应的属性及功能
属性:就是实体固有的信息特征,本质就是以前的变量,如:
实体 | 属性 |
手机 | 价格、品牌、操作系统、尺寸、颜色、配置参数 |
人 | 姓名、性别、年龄、学历、电话、籍贯 |
功能:实体可以完成的动作,本质就是以前的函数或方法
报名示例的实体与属性:
第三步:让实体去执行相应的功能或动作
学生:提出报名
学生:提供相关资料
教师:登记学生信息
学生:缴费
机构:收费
教师:分配教师
班级:增加学生信息
7.1.3面向过程向面向对象的思想迁移
以前面向过程编写代码:首先考虑实现什么功能,然后调用什么函数,最后按部就班的实现需求
以后面向对象编写代码:
首先考虑有什么样的实体去实现什么样的功能
然后分装实体的属性及功能
通过实体实现对应功能
7.1.4面试题:面向过程和面向对象的区别
面向过程与面向对象都可以实现模块化编程代买也可以重用,但是面向对象的模块化更深,数据更封闭更安全
现象对象的思维方式更加贴近现实生活,更容易解决大型的复杂业务逻辑
从前期开发角度来说,面向对象比面向过程更复杂,但从维护或扩展的角度来说,面向对象远比面向过程简单
面向过程的代码执行效率更高
7.2面向对象的专业术语
7.2.1面向对象开发的三大流程:
面向对象分析->面向对象设计->面向对象编程
7.2.2类
类是对现实世界一种模拟,在现实世界中任何一个实体都有一个类别
==类就是具有相同或相似属性和动作的一组实体集合==
图1:
图2:
7.2.3对象(object)
概念:是一种抽象概念,对象是类实例化的结果
对象分为2部分
静态属性:客观存在,不可忽视,如:人的姓名、性别……
动态属性:行为,对象执行动作,如:人能跑步
总结:对象使用属性保存数据,对象使用方法管理数据
7.3类的定义即使用
7.3.1面向对象开发的基本流程:
第一步:设计一个类
第二步:使用类名()方法创建对象,创建对象分成2步:
内存为对象分配空间
调用初始化方法_ _ init_ _ () 为对象初始化
7.3.2定义一个类
经典类:
class类名:
"""类的帮助信息"""
代码
新式类:
class类名():
"""类的帮助信息"""
代码
注意
类名遵循标识符命名规则(数字、字母、下划线组成,不能以数字开头)
类名为方法名区分开,应使用驼峰命名法,类中每个单词的首字母大写,而不使用下划线
对象名都应小写,单词之间使用下划线间隔
例:基本架构:
class Person():
"""创建一个人类"""
def eat(self):
print('我爱吃零食')
def drink(self):
print('我喜欢喝可乐')
class Geese:
'''大雁类'''
pass
类本质也是一个特殊的对象
python一切皆为对象,类是一个特殊的对象即类对象
程序运行时,类会被加载的到内存中,类对象只有一份,可以创建出多个对象实例
7.3.3类的实例化
类的实例化就是把抽象的类具体实例化为现实世界的实体,即通过类得到对象
分析:
定义完毕一个类之后是不会创建一个实例对象的,若类好比一个汽车的设计图纸,该图纸只能告诉你怎么去造车,但图纸本身不是一辆车,不能开走他,只能制作车
类本身什么都做不了,必须利用类得到一个实例化对象,利用对象实现功能
根据类创建出对象的过程称为实例化
格式:对象名 = 类名()
例:把Person类实例化出一个对象
# 1.定义一个类
class Person():
def eat(self):
print('我爱吃零食')
def drink(self):
print('我喜欢喝可乐')
# 2.根据类实例化出对象
p1 = Person()
p2 = Person()
# 3. 调用对象的方法解决问题
p1.eat()
p2.drink()
7.3.4类中self关键字
self是python关键字之一,作用:==指向类实例对象本身==,用于访问类汇总属性和方法,在方法调用时会自动传递实际参数self
# 1.定义一个类
class Person():
def speak(self):
print(self)
print('Nice to meet you')
# 2.根据类实例化出对象
p1 = Person()
print('对象地址:', p1) # 输出对象名,输出对象地址
p1.speak()
# 3. 调用对象的方法解决问题
p2 = Person()
print('对象地址:', p2)
p2.speak()
总结:类中self就是谁实例化了对象,则self就指向该对象,本质为对象的首地址,即代表对象本身
7.3.5通过_ _ init_ _ ()方法进行初始化
python中_ _ xx_ _ () 方法称为魔术方法,是就有特殊功能的函数
类创建后,手动编写_ _ init_ _ () 方法,类似于java的构造方法,创建对象时会被自动调用,用于默认属性值的初始化,使用双下划线开头和结尾,是一种特殊的约定,旨在区分其它方法
_ _ init_ _ (self) 本身再带self参数,必须时第一个位置,指向对象本身
class Person():
def __init__(self, name, age):
self.name = name
self.age = age
p1 = Person('孙悟空', 500)
print(p1.name)
p2 = Person('猪八戒',400)
print(p2.name)
self.属性=传递属性 , 表示创建对象时传递的参数赋值给哪个对象的哪个属性
7.3.6创建类的静态方法
在开发时,如果需要在类中封装一个方法,该方法需要做到:
既不需要其它对象调用,会自动执行
用于打印一些提示、帮助信息等功能
格式:@staticmethod,写在类中方法之前,用于修饰类中的方法,使其可以不创建类实例的情况下直接执行调用,优点:执行效率高,不需要默认的self参数
例:
# 开发一款游戏
class Game():
@staticmethod # 装饰器声明以下方法为静态方法
def menu():
print('1、开始游戏')
print('2、游戏暂停')
print('3、退出游戏')
Game.menu() # 不需要创建对象,直接通过类名.静态方法名 访问
7.3.7创建类的属性
概念:定义在类中且在函数体外部的变量称为类属性,类属性是所有对象的公共属性,在所有类的对象中共享
结构图:
例:
class Geese:
'''定义大雁类'''
neck = '脖子老长了'
wing = '翅膀震动频率高'
leg = '腿位于身体中心点'
geese1 = Geese()
geese2 = Geese()
print(geese1.neck) # 通过对象.属性名 方法访问
print(geese2.wing)
print(Geese.leg) # 通过类名.属性名 方法访问
class Geese:
'''定义大雁类'''
neck = '脖子特别特别长' # 类属性变更,对象属性也会变化
wing = '翅膀震动频率高'
leg = '腿位于身体中心点'
geese1 = Geese()
geese2 = Geese()
print(geese1.neck)
print(geese2.neck)
注意:类属性用于计数、控制、包含某个对象
7.3.8对象属性
对象属性一般是在类外面进行创建或获取
class Person:
pass
p1 = Person()
p1.name = '老王' # 为p1对象添加私有属性
p1.age = 18
p1.address = '西安市雁塔区电子城街道融鑫路3号'
p2 = Person()
print(p2.name) # 报错,不可以访问p1的私有对象属性
在类的内部获取外部定义的属性
class Person:
def speak(self):
print(self.name,self.age,self.address)
p1 = Person()
p1.name = '老王' # 为p1对象添加私有属性
p1.age = 18
p1.address = '西安市雁塔区电子城街道融鑫路3号'
p1.speak()
7.4魔术方法
7.4.1python中_ _ xx _ _()函数称为魔术(魔法)方法,具有特殊功能
7.4.2_ _ str _ _() 方法
当使用print()输出对象时,默认打印的是对象的内存地址
如果类中定义_ _ str_ _ ()方法,则若再次print()输出对象时会输出_ _ str_ _ ()方法return的结果
例:
# 1.定义一个类
class Car():
# 首先定义一个__init__()方法,初始化实例对象的属性
def __init__(self, brand, model, color):
self.brand = brand
self.model = model
self.color = color
# 在定义一个__str__()方法,用于输出小汽车的信息
def __str__(self):
returnf'汽车品牌:{self.brand},汽车星号:{self.model},汽车颜色:{self.color}'
# 2.实例化一个对象
c1 = Car('奔驰', 's600', '黑色')
print(c1)
# 结果:
汽车品牌:奔驰,汽车星号:s600,汽车颜色:黑色 ,注意:不再是对象的地址
注意:类的内部定义_ _ str_ _ ()方法,其return的结果会返回一个字符串数据类型
7.4.3_ _ del_ _() 方法
称为删除方法或者析构方法
注意:当删除对象时,python解释器会默认调用该方法
例:
class Preson:
def __init__(self, name, age):
self.name = name
self.age = age
def __del__(self):
print('对象已经删除')
p1 = Preson('白骨精', 100)
del p1
注意:_ _ del_ _() 方法主要用于删除对象后的后续操作,如:关闭文件、关闭数据库连接等‘
7.5综合案例
7.5.1例1:定义学员信息类,包含:姓名、成绩属性,定以成绩打印方法:90分以上优秀、80分以上良好、60分以上及格、60以下补考
分析:
程序:
# 1.定义学员类
class Student():
# 2. 定义实例属性
def __init__(self, name, score):
self.name = name
self.score = score
# 3. 定义一个方法,打印成绩
def print_grade(self):
if self.score>= 90: # 必须增加self表明哪个对象的属性
print('学员姓名:', self.name, '百分制成绩:', self.score, '等级成绩: 优秀')
elif self.score>= 80:
print('学员姓名:', self.name, '百分制成绩:', self.score, '等级成绩: 良好')
elif self.score>= 60:
print('学员姓名:', self.name, '百分制成绩:', self.score, '等级成绩: 及格')
else:
print('学员姓名:', self.name, '百分制成绩:', self.score, '等级成绩: 补考')
name1 = input('请输入姓名:')
score1 = int(input('请输入百分制成绩:'))
# 4. 实例化出一个对象
stu1 = Student(name1, score1)
# 5. 调用对象的方法实现功能
stu1.print_grade()
7.5.2例2:编写Prime类实现输出大于m且紧随m的k个素数
# 1.定义一个类
class Prime():
# 2. 初始化实例属性
def __init__(self, start_value, number):
self.start_value = start_value
self.number = number
# 3.创建实现功能的函数方法
def prime_number(self):
count = 0
i = self.start_value+1
while count<self.number:
for j in range(2, i):
if i%j == 0:
break
else:
count = count+1
print(i, end=' ')
i = i+1
m = int(input('请输入起始值:'))
k = int(input('请输入查找个数:'))
prime1 = Prime(m, k) # 4.实例化出一个对象
prime1.prime_number() # 5. 调用对象的方法实现功能
7.5.3例3:编写Mysort类实现列表的升序排序(选择法)
class Mysort():
def __init__(self, list1):
self.list1 = list1
def selection_sort(self):
if len(self.list1) == 0:
return'数据不能为空'
self.list1 = list(self.list1) # 转为字符串列表
self.list1 = [int(self.list1[i]) foriinrange(len(self.list1))] # 遍历字符串列表的每个元素,强制转为int
for i in range(len(self.list1) -1):
for j in range(i+1, len(self.list1)):
if self.list1[i] >self.list1[j]:
self.list1[i], self.list1[j] = self.list1[j], self.list1[i]
return self.list1
if __name__ == '__main__':
li = input('请输入需要排序的数字:')
mysort1 = Mysort(li)
print(mysort1.selection_sort())
7.6面向对象的三大特征--封装
7.6.1封装有2层含义
把主体的属性和方法卸载类里面的操作称为封装
class Person:
# 封装属性
# 封装方法
封装可以为属性和方法添加私有权限
7.6.2封装私有属性及私有方法
属性和方法分为两大类:
公有:无论在类内部还是类外部都可以对属性和方法进行操作
私有:不允许在类的外部对类内部的属性和方法进行操作
7.6.3私有属性的访问限制
设置私有属性方法:在属性名或方法名前增加两个下划线_ _即可
例:
class Girl():
def __init__(self, name):
self.name = name
self.__age = 18 # 私有属性
xiaomei = Girl('小美')
print(xiaomei.name)
print(xiaomei.__age) # 报错,提示Girl产生对象没有__age属性
7.6.4私有属性或方法设置访问接口
如果需要在类外部访问私有属性或方法,需要通过定义的接口来实现
python中一般使用函数名为get_xx命名的接口函数来获取私有属性,使用set_xx来修改私有属性
class Girl():
def __init__(self, name):
self.name = name
self.__age = 18 # 私有属性
def get_age(self): # 公共方法,提供给外部访问私有属性的接口
returnself.__age
def set_age(self, age): # 公共方法,提供给外部修改私有属性的接口
self.__age = age
xiaomei = Girl('小美')
print(xiaomei.name)
print(xiaomei.get_age())
xiaomei.set_age(25)
print(xiaomei.get_age())
注意:私有方法定义方式与私有属性一致,在方法名之前添加2个下划线即可
7.6.5封装到底有什么意义:
封装数据属性:明确区分内外,控制外部对隐藏的内部属性的操作,过滤掉异常数据
class People():
def __init__(self, name, age):
self.__name = name # 私有属性
self.__age = age # 私有属性
def tell_info(self):
print(self.__name, self.__age)
# 私有属性进行访问接口的设计
def set_info(self, name, age):
if not isinstance(name, str):
print('名字必须为字符串')
return
if not isinstance(age, int):
print('年龄必须时数值型')
return
self.__name = name
self.__age = age
p = People('jack', 38)
p.tell_info()
p.set_info(567, 35) # 传递错误数据,私有属性不会更改
p.tell_info() # 保留上一次结果
降低程序复杂度
class Atm:
def __card(self):
print('插卡')
def __auth(self):
print('认证')
def __print_bill(self):
print('打印账单')
def __take_money(self):
print('取款')
def withdraw(self): # 定义一个对外提供服务的公共方法
self.__card()
self.__auth()
self.__print_bill()
self.__take_money()
atm1 = Atm()
atm1.withdraw()
7.6.6装饰器@property封装
作用:通过@property装饰器将一个方法转换为属性,从而实现调用方法时相当于调用属性,不需要园括号,代码更简洁
格式:
@property
def 方法名(self):
方法体
例:
class Rect:
def __init__(self, width, height):
self.width = width
self.height = height
@property
def area(self):
return self.width*self.height
rect1 = Rect(600, 800)
print('面积为:', rect1.area) # area方法为装饰后的属性,使用时不需要园括号
7.7面向对象的三大特征--继承
7.7.1继承的几个相关概念
继承:一个类从另一个类获得其成员的相关特性
派生:从一个已有的类中产生一个新的类,称为派生,继承与派生其实是从不同方向来描述相同的概念,本质一致
父类:也称为基类,被继承的类
子类:称为派生类或扩展类
扩展:在子类中增加一些自己特有的特性,称为扩展,只有继承没有扩展则继承无意义
单继承:一个类只能继承自另一个类,不能继承多个类,称为单继承
多继承:一个类同时继承了多个父类
7.7.2继承基本语法
假设A类继承B类中所有属性和方法(私有属性和私有方法除外)
class B(object):
pass
class A(B): #A继承B
pass
class Person(object):
def eat(self):
print('i can eat food')
def drink(self):
print('i can drink')
class Teacher(Person): # 继承父类Person
pass
class Student(Person):
pass
teacher1 = Teacher()
teacher1.eat() # 子类teacher1可以使用父类的方法
student1 = Student()
student1.drink()
7.7.3单继承
单继承:一个类只能继承自另一个类,不能继承多个类
例:
class Car(object):
def run(self):
print('i can run')
class GasolineCar(Car): # 定义汽油车
pass
class EletricCar(Car): # 定义电车
pass
bmw = GasolineCar()
bmw.run()
object : 是一个类,是所有类的父类,在object类中定义了所有类的默认属性及方法
7.7.4多继承
概念:允许一个类同时继承自多个父类
图:
格式:
class B(object):
pass
class C(object):
pass
class A(B,C):
pass
注意:在实际开发中,应尽量避免使用多继承,因为如果两个类中出现了相同的属性和方法就会产生命名冲突
7.7.5方法重写
扩展特性:继承让子类继承父类的所有公共属性和方法,但仅仅是为了继承而继承,继承就没有实际意义,应该在继承后,子类拥有一些自己的属性好方法
例:
class Animal(object):
def eat(self):
print('i can eat')
def call(self):
print('i can call')
class Dog(Animal):
# 重写父类方法
def call(self):
print('i can wang wang wang')
wangcai = Dog()
wangcai.eat()
wangcai.call()
注意:
子类方法重写后,会优先使用子类的方法
子类继承父类后,某个方法被重写,原父类的方法还在,只不过在子类中找不到
7.8面向对象三大特征--多态
7.8.1概念:多态是指一类事物有多重形态,是一种使用对象的方式,子类重写父类方法后,调用不同的子类对象的相同父类方法,可以产生不同的结果
7.8.2特点
多态依赖于继承
子类方法必须重写父类方法
过程:首先定义一个父类,其可能拥有多个子类对象,当调用一个公共方法时,传递的对象不同,返回结果不同
原理图:
例:
class Fruit(object):
# 公共方法
def makejuice(self):
print('i can make juice')
class Apple(Fruit):
def makejuice(self):
print('i can make apple juice')
class Banana(Fruit):
def makejuice(self):
print('i can make banana juice')
class Orange(Fruit):
def makejuice(self):
print('i can make orange juice')
def service(obj):
obj.makejuice()
apple1=Apple()
banana1=Banana()
orange1=Orange()
for i in (apple1 ,banana1 , orange1):
service(i)
7.9综合案例:
7.9.1需求分析
设计一个game类
属性
类属性top_score记录游戏最高分数
实例属性player_name 记录当前玩家的姓名
方法
静态方法show_help 显示游戏帮助信息
类方法show_top_score 显示历史最高分
实例方法start_game开始当前玩家的游戏
class Game(object):
# 1.定义类属性top_score
top_score=100
# 2.定义初始化方法
def __init__(self,player_name):
self.player_name=player_name
# 3.静态方法
@staticmethod
def show_help():
print('游戏帮助信息')
# 4.定义类方法
def show_top_score(self):
print('游戏最高分:')
# 5. 定义实例方法
def start_game(self):
print('游戏开始,你准备好了吗')
8.第八章 异常处理
8.1 异常概述
8.1.1 异常:报错,程序运行时检测出错误,解释器无法继续执行,既而程序中断
print(10/0)
ZeroDivisionError: divisionbyzero
8.1.2 异常分类
显式异常:明确的语法错误,有提示
隐式异常:不容易发现,与操作有关
8.1.3 异常信息分析
异常追踪信息(Traceback):异常出现在那个文件,哪一行
异常类型:内置在python,根据类型给出提示
异常内容:异常的简单解释
8.1.4 常见异常类型
NameError:变量没有声明
IndexError:索引超出序列范围
ValueError:处入数据错误
ZeroDivisionError:除数为0
MemoryError:内存不足
ImportError:模块加载错误
IOError:输入输出错误(文件不存在)
FileNotFoundError:文件不存在
8.2 捕获异常
8.2.1 格式:
try:
可能发生错误的代码
except:
异常出现后的执行代码
8.2.2 过程:当执行try后的代码块出错后,就会执行except之后的代码块,若无错则except后的代码块不执行
8.2.3 例:
try:
f = open('c:\\python.txt', 'r')
c = f.readline()
print(c, end=' ')
except:
f = open('c:\\python.txt', 'w')
f.write('发生异常!!!')
f.close()
8.2.4 捕获指定异常
作用:针对性的捕获异常去执行对应代码
格式:
try:
可能发生错误的代码
except(需要捕获的异常名称 [as新名称]):
异常出现后的执行代码
as 新名称:表示异常名称过长可以使用短名称,也可以省略
注意:一但捕获的的异常类型与需要捕获的异常类型不同,则无法捕获异常
try:
f = open('c:\\temp.txt', 'r')
c = f.readline()
print(c, end=' ')
except ZeroDivisionError as e:
print(e)
同时捕获多个指定异常
try:
可能发生错误的代码
except(需要捕获的异常名称1, 需要捕获的异常名称2…… ) [as新名称] :
异常出现后的执行代码
try:
f = open('c:\\temp.txt', 'r')
c = f.readline()
print(c, end=' ')
except (FileNotFoundError ,MemoryError) as e:
print(e)
8.2.5 捕获多个异常
格式:
try:
可能发生错误的代码
except Exception :
异常出现后的执行代码
例:
try:
print(name)
except Exception as e:
print(e) # 输出异常类型的解释
8.2.6 异常捕获的else语句
作用:else语句表示如果没有异常要执行则需要执行的代码
try:
可能出现异常的代码
except :
应对代码
else:
没有异常时执行的代码
例
try:
print(1)
except Exception as e:
print(e)
else:
print('无异常!!!')
8.2.7 异常捕获的finally语句
finally表示无论是否有异常都需执行的代码,如:关闭数据库连接、关闭文件等
格式:
try:
可能出现异常的代码
except :
应对代码
else:
没有异常时执行的代码
finally:
必须要执行的代码块
例:
try:
f = open('c:\\python.txt', 'r')
except:
f = open('c:\\python.txt', 'w')
else:
print('无异常!!!')
finally:
print('关闭文件')
f.close()