视频资源来自:b站杨淑娟老师——《Python教程全套》完全入门版
文章仅为个人观看视频后的学习心得笔记,用于个人查看和记录保存。文中定有疏漏错误之处,恳请指正。
目录
一、python入门
二、字符编码
三、运算符
四、程序的组织结构
五、循环
六、列表
七、字典
八-1、元组
八-2、集合
九、字符串
十、函数
十一、异常处理
十二、类与对象
十三、对象
十四、模块化
十五、文件
十六、学生信息管理系统
十七、实操案例
一、python入门
python简介
解释型语言,没有编译环节
交互型语言
面向对象
下载安装python、pycharm
配置解释器
python中的输出函数
print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
print函数默认换行,是end='\n'在起作用。
print(i,end='\t')
不换行,输出完之后,结尾用制表符代替
print可以输出数字、字符串(加引号)、含有运算符的表达式
输出到文件
fp=open('D:/text.txt','a+')
print('hello world',file=fp)
fp.close()
'a+'如果文件不存在就直接创建,存在就在文件内容的后面继续追加
1.指定的盘符存在,
2.使用file= fp
不进行换行输出(输出内容在一行当中)
print('hello','world','Python')
转义字符
\ \ 用两个反斜杠来表示一个反斜杠
\n -> newline换行
\t,每次占一个制表位,一个制表位占4格()
print('a\tbcdefghi')
print('ab\tcdefghi')
print('abc\tdefghi')
print('abcd\tefghi')
\r 覆盖
print('hello\rworld')
\b 退格
print('hello\bworld')
单双引号混用
原字符,不希望字符串中的转义字符起作用,就使用原字符,就是在字符串之前加上r,或R。==注意==:最后一个字符不能是\。想写\可以用\\代替。因为字符的优先级不同
print(r'hello\bworld')
二、字符编码
二进制与字符编码
ASCII
graph TD
A(二进制0\,1) -->B(ASCII)
B --> C(GB2312)
B --> D(其他国家的字符编码)
C --> E(GBK)
D --> F(Unicode几乎包含了全世界的字符)
E --> G(GB18030)
F --> H(UTF-8)
G --> F
print(chr(0b100111001011000))
print(chr(20056))
print(ord('乘'))
Python中的标识符与保留字
import keyword
print(keyword.kwlist)
['False', 'None', 'True', '_peg_parser_', '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中的变量与数据类型
标识:标识对象所存储的内存地址,使用内置函数id(obj)
来获取
类型:标识的是对象的数据类型,使用内置函数type(obj)
来获取
name = '玛丽亚'
print('值',name)
print('标识',id(name))
print('类型',type(name))
多次赋值后,变量名会指向新的空间
数据类型:int float bool str
整数可以表示为二进制0b、八进制0o、十进制、十六进制0x。
浮点数,计算可能不精确。
解决方法:导入模块
print(1.1+2.2)
from decimal import Decimal
print(Decimal('1.1')+Decimal('2.2'))
布尔类型,可以转成证数进行计算。True
和False
首字母都必须大写
f1=True
f2=False
print(f1+1) #2
print(f2+1) #1
字符串类型,三引号(3个单引号/3个双引号)定义的字符串可以分布在连续的多行。
str1='''好好学习,
天天向上'''
str2="""好好学习,
天天向上"""
print(str1)
print(str2)
甚至空格也给你记进去
数据类型转换:
str():当str和int型连接时,用+
会报错,可以用,
也可以用str()
int():str->int,字符串必须为整数数字串。float->int,截取整数部分。bool->int,1或0。
float():str->float,字符串必须为数字串。int->float,98->98.0
Python中的注释
单行注释:#
多行注释:'''一对三引号之间的为多行注释'''
中文编码声明注释:python默认存储为UTF-8,在文件开头注释
#coding:gbk
该文件就默认存储为GBK了
三、运算符
Python的输入函数input()
present = input('好好学习')
print(present,type(present))
想要输入整数类型时,别忘了类型转换int()
a=int(input('输入整数'))
Python中的运算符
算数运算符
标准算数运算符:加、减、乘、除(/)、整除(//,一正一负向下取整,9//-4=-3)
取余运算符:%,余数=被除数-除数*商。9%-4=-3,-9%4=3。
幂运算符:**
2**3=8
赋值运算符
支持链式赋值:a=b=c=20
支持参数赋值:+=、-=、/=、//=、%=
支持系列解包赋值:a,b,c=20,30,40
左右变量数和值的个数要相同。
交换a,b=b,a
比较运算符
结果为bool型。
== 比较运算符,比较值
is ,is not,比较标识
a=10
b=10
print(a==b)
print(a is b)
先创建a,在创建b的时候,发现已经有了10,就直接也指向那个对象了。所以 a、b标识一样。
但是数组的id地址不相同
布尔运算符
and 相当于&&
or 相当于||
not 相当于!
in ,not in :
a='hello world'
print('w' in a)
print('s' in a)
print('w'not in a)
位运算符
按位与& 、按位或| 、左移<< 、右移>>
运算符的优先级
算数运算->位运算->比较运算->布尔运算->赋值运算
四、程序的组织结构
顺序结构、选择结构、循环结构
对象的布尔值
python一切皆对象,所有对象都有一个布尔值
False:False、数值0、None、空字符串、空列表([]、list())、空元组(()、tuple())、空字典({}、dict())、空集合(set())
其它对象的布尔值均为True
分支结构
单分支结构
双分支结构
多分支结构
money = int(input())
if 90<=money<=100:
print('优')
elif 80<=money<90:
print('良')
else:
print('及')
嵌套if
print('优' if 90<=money<=100 else ('良',money) )
pass语句
什么都不做,只是一个占位符,用在语法上需要语句的地方
if 80<=money<90:
pass
else:
print('及')
没想好咋写,这样语法也不会报错
五、循环
内置函数range()
内置函数:前面不需要加任何函数,可以直接使用。
range(),用于生成一个整数序列。默认从0开始,步长1
range(stop),创建一个[0,stop)之间的整数序列,步长为1
range(start,stop),
range(start,stop,step),创建一个[start,stop)之间的整数序列,步长为step
优点:占用内存空间固定,值存储3个值
while循环
a=2
sum=0
while a<=100:
sum+=a
a+=2
print('1-100之间的偶数和',sum)
for-in循环
in表达从(字符串、序列等)中依次取值(遍历)
for-in编历的对象必须是可迭代对象
如果不需要使用自定义变量,可将自定义变量改用下划线_表示
for item in 'Python':
print(item)
for i in range(10):
print(i)
for _ in range(5):
print('重复输出5次')
100-999之间的水仙花数
for item in range(100,1000):
a=item//100
b=(item-a*100)//10
c=item%10
if a**3+b**3+c**3==item:
print(item)
break、continue与else语句
输出1-50之间所有5的倍数
for item in range(1,51):
if item%5!=0:
continue
print(item)
else与 while、for搭配使用时,没有碰到break时执行else。循环的正常执行次数执行完,就执行else
for i in range(4):
for j in range(3):
print('*',end='\t')
print()# 加了这个就会换行啦
二重循环中的break和continue用于控制本层循环
嵌套循环
六、列表
列表元素按顺序有序排序
所以映射唯一一个数据
列表可以存储重复数据
任意数据类型混存
根据需要动态分配和回收内存
列表的创建与删除
使用中括号
lst1=['hello','world',98]
使用内置函数list()
lst2=list(['hello','world',98])
lst1、lst2,存储 列表对象的引用
列表生成式
lst=[i*i for i in range(1,10)]#[1, 4, 9, 16, 25, 36, 49, 64, 81]
列表的查询操作
获取列表中指定元素的索引index()
:
如果列表中存在N个相同元素,只返回相同元素中的第一个元素的索引
如果查询的元素在列表中不存在,则会抛出ValueError
还可以在指定start和stop直接进行查找
lst1=['hello','world',98,100]
print(lst1.index('world'))
print(lst1.index('world',1,3))
获取列表中的单个元素:
正向索引从0到N-1
逆向元素从-N到-1
指定索引不存,抛出indexError
lst1 = ['hello', 'world', 98, 100]
print(lst1[2])#98
print(lst1[-4],lst1[-3],lst1[-2],lst1[-1])#hello world 98 100
获取列表中的多个元素(切片操作):
切片结果是元列表片段的拷贝
切片的范围[start,stop),默认为[0,N)
步长默认为1
step为正数:从start开始往后计算切片
lst = [0,1,2,3,4,5,6,7,8,9]
print(lst[2:6:2])#[2, 4]
print(lst[2:6])#[2, 3, 4, 5]
print(lst[2:6:])#[2, 3, 4, 5]
print(lst[:6:])#[0, 1, 2, 3, 4, 5]
print(lst[::])#[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
step为负数:从start开始往前计算切片
lst = [0,1,2,3,4,5,6,7,8,9]
print(lst[6:2:-2])#[6, 4]
print(lst[2::-1])#[2, 1, 0]
print(lst[:6:-1])#[9, 8, 7]
print(lst[::-1])#[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
可以用in、not in来判断指定元素在列表中是否存在
可以用for 迭代变量 in 列表名
来遍历列表
列表元素的增、删、改操作
增加:内存没有更改,就是在元列表中添加
方法 | 描述 |
---|---|
append() | 在列表的末尾添加一个元素 |
extend() | 在列表的末尾至少添加一个元素 |
insert() | 在列表的任意位置添加一个元素 |
切片 | 在列表的任意位置至少添加一个元素 |
以下代码分别执行
lst = [0,1,2,3,4,5,6,7]
lst.append(80)#[0, 1, 2, 3, 4, 5, 6, 7, 80]
lst2 = ['a','b','c']
lst.append(lst2)#[0, 1, 2, 3, 4, 5, 6, 7, ['a', 'b', 'c']]
lst.extend(lst2)#[0, 1, 2, 3, 4, 5, 6, 7, 'a', 'b', 'c']
lst.insert(2,90)#[0, 1, 90, 2, 3, 4, 5, 6, 7]
lst.insert(2,lst2)#[0, 1, ['a', 'b', 'c'], 2, 3, 4, 5, 6, 7]
lst[3::]=lst2#[0, 1, 2, 'a', 'b', 'c']
lst[:4:]=lst2#['a', 'b', 'c', 4, 5, 6, 7]
lst[::3]=lst2#['a', 1, 2, 'b', 4, 5, 'c', 7]
删除
方法 | 描述 |
---|---|
remove() | 一次删除一个元素;重复元素只删除第一个;元素不存在就抛出ValueError |
pop() | 删除一个指定索引位置上的元素;不指定索引,则删除列表中最后一个元素;指定索引不存在就抛出ValueError |
切片 | 一次至少删除一个元素 |
clear() | 清空列表 |
del | 删除列表对象 |
remove写的是元素值,pop写的是索引
切片↓
lst = [0,1,2,3,4,5,6,7]
new_list = lst[1:3]#产生新对象[1, 2]
lst[1:3]=[]#在原列表中删除[0, 3, 4, 5, 6, 7]
修改
以下代码分开执行
lst = [0,1,2,3,4,5]
lst[2]='a' #[0, 1, 'a', 3, 4, 5]
lst[1:3]=['a','b','c','d']#[0, 'a', 'b', 'c', 'd', 3, 4, 5]
列表元素的排序
sort():不指定reverse,就默认False,升序排序
lst=[20,40,30,10,50]
lst.sort()#[10, 20, 30, 40, 50]
lst.sort(reverse=True)#[50, 40, 30, 20, 10]
new_list = sorted(lst)
new_list = sorted(lst,reverse=True)
使用内置函数sorted(),原列表不发生变化
七、字典
什么是字典
python内置的数据结构之一,与列表一样是一个可变序列
以键值对的方式存储数据,字典是一个无序的序列
键必须是一个不可变序列(不可以执行增删改操作),如整数序列、字符串序列
特点:
所有元素都是一个key-value对,key不允许重复,value可以重复
字典中的元素是无序的
字典中的key必须是不可变对象
字典也可以根据需要动态地伸缩
字典会浪费较大的内存,是一种使用空间换时间的数据结构
字典的实现原理
hash
字典的创建与删除
#{'张三': 100, '李四': 90, '王五': 80}
scores1 = {'张三':100, '李四':90, '王五':80}
scores2 = dict(张三 = 100, 李四 = 90, 王五 = 80)
scores3 = {}#创建空字典
字典的常用操作
查询
print(scores1['张三'])
print(scores1.get('张三'))
print(scores1.get('邓布利多',99))#如果查找不存在,返回默认值99
如果找不到,[]会报KeyError。get会报None
key的判断:in、not in
print('张三' in scores1)
增
scores1['赵六']=70
删
del scores1['张三']
scores1.clear()
改
没有就新增,有就修改
scores1['赵六']=70
获取视图
keys=scores1.keys()
print(keys,type(keys))
print(list(keys))#将所有键组成的视图转成列表
values=scores1.values()
print(values,type(values))
print(list(values))
items=scores1.items()
print(items,type(items))
print(list(items))#转换之后的列表元素是由元组组成的
dict_keys(['张三', '李四', '王五'])
['张三', '李四', '王五']
dict_values([100, 90, 80])
[100, 90, 80]
dict_items([('张三', 100), ('李四', 90), ('王五', 80)])
[('张三', 100), ('李四', 90), ('王五', 80)]
字典元素的编历
for item in scores1:
print(item,scores1[item],scores1.get(item))
结果:
张三 100 100
李四 90 90
王五 80 80
字典生成式
内置函数zip()
用于将可迭代的对象作为参数,将对象中对应的元素打包成一个元组,然后返回由这些元组组成的列表
items = ['Fruits','Books','Others']
prices = [10,20,30,40,50]
d={item:price for item,price in zip(items,prices)}
#{'Fruits': 10, 'Books': 20, 'Others': 30}
压缩打包的时候会以元素少的那个列表为基准
八-1、元组
什么是元组
Python内置的数据结构之一,是一个不可变序列。==没有元组生成式==
不可变序列:字符串、元组。没有增删改的操作
可变序列:列表、字典。可以对序列执行增、删、改操作,对象地址不发生改变
列表用[],元组用()
为什么要将元组设计成不可变序列?
设计成不可变序列后,在多任务环境下,同时操作对象时不需要加锁。(可以看数据、取数据,但是不能增删改)因此,在程序中尽量使用不可变序列
注意:元组中存储的对象:
如果元组中的对象本身是不可变对象,则不能再引用其他对象
如果元组中的对象是可变对象,则可变对象的引用不允许改变,但数据可以改变
可以向列表中添加元素,而列表的内容的地址不变
元组的创建方式
()、内置函数tuple()
t1=('hello','world',80)
tw='hello','world',80 #元素有2+个时,小括号可以省略
t3=tuple(('hello','world',80))
t4=('hello',)
t5=()
t6=tuple()
只包含一个元组的元素需要使用逗号和小括号
元组的编历
1、使用索引
2、元组是可迭代对象,所以可以使用for…in进行编历
八-2、集合
什么是集合
集合是没有value的字典(字典中键不能重复,同样 集合中的元素也不能重复)
集合的创建
集合中的元素是无序的,不重复
s1={2,3,4,4,5,6,2,1}#{1, 2, 3, 4, 5, 6}
print(s1)
s=set([3,4,5,10])#列表{10, 3, 4, 5}
s=set((3,4,5,10))#元组{10, 3, 4, 5}
s=set('Hello')#字符串{'o', 'H', 'l', 'e'}
s=set({3,4,5,10})#集合{10, 3, 4, 5}
s=set()#set()
定义空集合时用set,如果直接用{},会被当作为字典类型
集合的增、删、改、查操作
判断:in、not in
新增:
add():一次添加一个元素
update():一次至少添加一个元素(里面可以填集合、列表、元组)
删除:
remove():一次删除一个指定元素,如果指定的元素不存在就抛出KeyError
discard():一次删除一个指定元素,如果指定元素不存在 不抛异常
pop():一次只删除一个任意元素
clear():清空集合
集合间的关系
是否相等==或!=
一个集合是否是另一个集合的子集issubset
一个集合是否是另一个集合的超集issuperset
两个集合是否没有交集isdisjoint
集合的数学操作
s1={2,3,4,6}
s2={3,4,5,6}
#交集{3, 4, 6}
print(s1.intersection(s2))
print(s1 & s2)
#并集{2, 3, 4, 5, 6}
print(s1.union(s2))
print(s1 | s2)
#差集{2}
print(s1.difference(s2))
print(s1-s2)
#对称差集{2, 5}
print(s1.symmetric_difference(s2))
print(s1^s2)
集合生成式
就是把列表生成式的[]改成{}
s1={i*i for i in range(10)}
九、字符串
字符串的驻留机制
字符串是基本数据类型,是一个不可变的字符序列
Python的驻留机制对相同的字符串只保留一份拷贝,后续创建相统字符串时,不会开辟新空间,而是把该字符串的地址赋给新创建的变量
交互模式(cmd)几种情况:
字符串长度为0或1时
符合标识符的字符串:不符合标识符的就不能驻留,比如'abc%'
字符串只在编译时进行驻留,而非运行时:用join连接的和原字符串不能共用
[-5,256]之间的整数数字:驻留
在需要拼接字符串时,建议使用join方法,而不是+。
因为join()方法是先计算出所有字符的长度,然后再拷贝,只new一次对象,效率更高
字符串的常用操作
查询
方法 | 作用 |
---|---|
index() | 查找子串第一次出现的位置,如果查找的子串不存在,则抛出ValueError |
rindex() | 查找子串最后一次出现的位置,如果查找的子串不存在,则抛出ValueError |
find() | 查找子串第一次出现的位置,如果查找的子串不存在,则返回-1 |
rfind() | 查找子串最后一次出现的位置,如果查找的子串不存在,则返回-1 |
大小写转换
转换之后,会产生一个新的字符串对象
方法 | 作用 |
---|---|
upper() | 把字符串中所有字符都转成大写字母 |
lower() | 把字符串中所有字符都转成小写字母 |
swapcase() | 把字符串中所有小写字符都转成大写字母,所有大写字符都转成小写字母 |
capitalize() | 把第一个字符转换为大写,把其余字符转换成小写 |
title() | 把每个单词的第一个字符转换为大写,把每个单词的剩余字符转换为小写 |
字符串内容对齐操作的方法
方法 | 作用 |
---|---|
center() | 居中对齐,第1个参数指定宽度,第2个参数指定填充符。第2个参数是可选的,默认是空格。如果设置宽度小于实际宽度,则返回原字符串 |
ljust() | 左对齐,第1个参数指定宽度,第2个参数指定填充符。第2个参数是可选的,默认是空格。如果设置宽度小于实际宽度,则返回原字符串 |
rjust() | 右对齐,第1个参数指定宽度,第2个参数指定填充符。第2个参数是可选的,默认是空格。如果设置宽度小于实际宽度,则返回原字符串 |
zfill() | 右对齐,左边用0填充。该方法只接收1个参数,用于指定字符串的宽度。如果设置宽度小于实际宽度,则返回原字符串 |
strip() | 移除字符串头尾指定的字符(默认为空格或换行符)或字符序列 |
注意:zfill()中如果有负号在开头,那么零填充在符号后。
print('-aads'.zfill(8))#-000aads
字符串劈分操作的方法
方法 | 作用 |
---|---|
split() | 从字符串的左边开始劈分,默认的劈分字符是空格字符串,返回的值都是一个列表;以通过参数sep指定劈分字符串是的劈分符;通过参数maxsplit指定劈分字符串时的最大劈分次数,在经过最大次劈分之后,剩余的子串会单独作为一部分 |
rsplit() | 从字符串的右边开始劈分,默认的劈分字符是空格字符串,返回的值都是一个列表;以通过参数sep指定劈分字符串是的劈分符;通过参数maxsplit指定劈分字符串时的最大劈分次数,在经过最大次劈分之后,剩余的子串会单独作为一部分 |
s='hello world python'
lst=s.split()
s='hello|world|python'
lst=s.split(sep='|')
s='hello|world|python'
lst=s.split(sep='|',maxsplit=1)#['hello', 'world|python']
字符串判断的相关方法
方法 | 作用 |
---|---|
isidentifier() | 判断指定的字符串是否是合法的标识符 |
isspace() | 判断指定的字符串是否全部由空白字符组成(回车、换行、水平制表符) |
isalpha() | 判断指定的字符串是否全部由字母组成 |
isdecimal() | 判断指定的字符串是否全部由十进制的数字组成 |
isnumeric() | 如果 string 中只包含数字字符,则返回 True,否则返回 False |
isalnum() | 判断指定的字符串是否全部由字母和数字组成 |
isdigit() | 如果 string 只包含数字则返回 True 否则返回 False. |
https://www.runoob.com/python/python-strings.html
注意:
'张三' 是字母
'四'、'Ⅱ' 是数字,但不是十进制数字
字符串替换
replace():第1个参数指定被替换的子串,第2个参数指定替换子串的字符串,该方法返回替换后得到的字符串,替换前的字符串不发生变化,调用该方法时可以通过第3个参数指定最大替换次数
字符串合并
join():将列表或元组中的字符串合并成一个字符串。
print('-'.join(lst))
print('-'.join('abcd'))#a-b-c-d
字符串的比较
运算符:>,>=,<,<=,==,!=
ord(),字符->原始值
print(ord('a'))#97
chr(),原始值->字符
print(chr(97))#a
== 比较的是value是否相等
is 比较的是id是否相等
字符串的切片操作
字符串是不可变类型,不具备增删改等操作,切片操作将产生新的对象
[start : end : step]
格式化字符串
%作占位符
name = '张三'
age = 20
print('我叫%s,今年%d岁' % (name,age))
print('%10d' % 99)
print('%.3f' % 3.1415926)
print('%10.3f' % 3.1415926)#总宽度为10,小数点后三位
{}作占位符。Python format 格式化函数
name = '张三'
age = 20
print('我叫{0},今年{1}岁'.format(name,age))
print('{:.3}'.format(3.1415926))#3.14
print('{0:.3}'.format(3.1415926))#3.14
print('{0:.3f}'.format(3.1415926))#3.142
print('{0:10.3f}'.format(3.1415926))# 3.142
print('{:^10d}'.format(3.1415926))#中间对齐,宽度为10
f-string
name = '张三'
age = 20
print(f'我叫{name},今年{age}岁')
字符串的编码转换
s='我要吃饭'
print(s.encode(encoding='GBK'))
print(s.encode(encoding='UTF-8'))
输出:
b'\xce\xd2\xd2\xaa\xb3\xd4\xb7\xb9'
b'\xe6\x88\x91\xe8\xa6\x81\xe5\x90\x83\xe9\xa5\xad'
在GBK编码格式中,一个中文占2个字节
在UTF-8编码格式中,一个中文占3个字节
byte=s.encode(encoding='GBK')
print(byte.decode(encoding='GBK'))
byte=s.encode(encoding='UTF-8')
print(byte.decode(encoding='UTF-8'))
十、函数
函数的创建和调用
def clac(a,b):#形参
c=a+b
return c
print(clac(2,3))#实参
函数的参数传递
位置实参:根据形参对应的位置进行实参传递。用法如上↑
关键词实参:根据形参名称进行实参传递
def clac(a,b):
print('a='+str(a))
print('b='+str(b))
return
clac(2,3)#a=2 b=3
clac(b=2,a=3)#a=3 b=2
在函数调用过程中,进行参数传递:
如果是不可变对象,在函数体的修改不会影响实参的值。
如果是可变对象,在函数体的修改会影响实参的值。
列表传的是地址,在函数里append追加元素后,调用结束了,在原列表中依旧在
函数的返回值
如果函数没有返回值,return可以省略不写
函数的返回值如果是1个,直接返回类型
函数的返回值如果是多个,返回的结果为元组
def fun(num):
odd=[]
even=[]
for i in num:
if i%2:
odd.append(i)
else:
even.append(i)
return odd,even
print(fun([1,3,5,6,7,8,9,20]))
#([1, 3, 5, 7, 9], [6, 8, 20])
函数的参数定义
函数定义默认值参数
def clac(a=30,b=100):
print('a='+str(a))
print('b='+str(b))
return
clac()#a=30 b=100
clac(2)#a=2 b=100
个数可变的位置参数
定义函数时,可能无法事先确定传递的位置实参的个数时,使用可变的位置参数
使用*定义个数可变的位置形参
结果为一个元组
每个函数只能定义一个
def fun(*a):
print(a)
fun(1,2,3,4)#(1, 2, 3, 4)
def fun(*lst):
在函数调用时,将列表中的每个元素都转换为位置实参传入
个数可变的关键字形参
定义函数时,无法事先确定传递的关键字实参的个数时,使用可变的关键字形参
使用**定义个数可变的关键字形参
结果为一个字典
每个函数只能定义一个
def fun(**arg):
print(arg)
print(arg['a'],arg['c'])
fun(a=1,b=2,c=3)
输出:
{'a': 1, 'b': 2, 'c': 3}
1 3
def fun(**dic):
在函数调用时,将字典中的键值对都转换为关键字实参传入
在一个函数定义过程中,既有个数可变的关键字形参,又有个数可变的位置形参。要求个数可变的位置形参放前面,个数可变的关键字形参放后面
def fun(*a,**arg):
def fun(a,b,*,c,d,**arg):
def fun(a,b=10,*,c,d,**arg):
↓从*之后的参数,在函数调用时,只能采用关键字参数传递
def fun(a,b,*,c,d):
print('a=',a)
print('b=',b)
print('c=',c)
print('d=',d)
fun(10,20,d=30,c=40)
变量的作用域
局部变量、全局变量
递归函数
组成部分:递归调用与递归终止条件
栈
算阶乘:
def fun(num):
if num==1:
return 1
return fun(num-1)*num
print(fun(6))
斐波那契数列:
def fib(num):
if(num==1 or num==2):
return 1
return fib(num-1)+fib(num-2)
for i in range(1,8):
print(fib(i),end=' ')
十一、异常处理
bug的由来及分类
常见错误:
1.末尾冒号
2.缩进错误
3.英文符号
4.字符串+数字拼接
5.没有定义变量
6.==和=
不同异常类型的处理方式
异常处理机制
try:
# res=1/0
# res='a'/1
res = 3/2
except ZeroDivisionError:
print('除数为0')
except BaseException as e:
print('其它异常',e)
else:
print('没有异常',res)
finally:
print('无论是否产生异常,都会被执行的代码')
finally可以用来释放资源
Python常见的异常类型
异常类型 | 描述 |
---|---|
ZeroDivisionError | 除(或取模)零(所有数据类型) |
IndexError | 序列中没有此索引(index) |
KeyError | 映射中没有这个键 |
NameError | 未声明/初始化对象(没有属性) |
SyntaError | Python语法错误 |
ValueError | 传入无效的参数 |
traceback模块:打印异常信息
import traceback
try:
a=1/0
except:
# pass
traceback.print_exc()
异常后续可以存储到文件中
raise 手动抛出异常
语法格式:
raise [Exception [, args [, traceback]]]
如
try:
x = 10
if x > 5:
raise Exception('x 不能大于 5。x 的值为: {}'.format(x)
except Exception as e:
print(e)
PyCham的调试模式
十二、类与对象
两大编程思想
面向过程:事务比较简单,可以用线性的思维去解决
面向对象
类和对象的创建
不同的数据类型属于不同的类。100、99、520都是int类下包含实例/对象
Python中一切皆对象(有id、内存空间、值)
创建类的语法
类的组成:类属性、实例方法、静态方法、类方法
在类之外定义的称为函数,在类之内定义的称为方法
class Student:#取名规范:由一个或多个单词组成,每个单词的首字母大写,其余小写
native='吉林' #类属性
def __init__(self,name,age): #初始化
self.name=name #self.name 称为实例属性,进行了一个赋值操作,将局部变量的name的值赋给实体属性
self.agee=age #self后面的不一定要叫name、age。但是习惯上局部变量和属性名相同
def eat(self): #实例方法
print('实例方法的输出')
@staticmethod #静态方法
def me():
print('我使用了staticmethod进行修饰,所以我是静态方法')
@classmethod #类方法
def cm(cls):
print('我使用了classmethod进行修饰,所以我是类方法')
对象的创建(类的实例化)
stu1=Student('张三',20)
使用
stu1=Student('张三',20)
stu1.eat() #对象名.方法名()
Student.eat(stu1) #类名.方法名(类的对象self)
print(stu1.name)
print(Student.native)
Student.native='天津' #native被共享,一改,其它对象的native也跟着改
print(stu1.native)
Student.cm() #类方法
Student.me() #静态方法
动态绑定
绑定属性
stu1.gender='女'
print(stu1.gender)
对象创建之后,又给stu1增加一个属性。而这个属性只能在stu1用,stu2是不能用的,没有定义。
绑定方法
def show():
print('我是一个函数')
stu1.show=show
stu1.show()#我是一个函数
同样,stu2也不能用show方法
十三、对象
面向对象三大特征:封装(安全性)、继承(复用性)、多态(扩展性、可维护性)
封装
在python中没有专门的修饰符用于属性的私有,如果该属性不希望在类对象外部被访问,前边加2个_下划线
class Student:
def __init__(self,name,age):
self.name=name
self.__age=age #不想被外部访问
def show(self):
print(self.name,self.__age)
stu=Student('张三',20)
print(stu.name)
# print(stu.__age)#会报错
print(stu._Student__age)
继承
python支持多继承。可以有好多个父类。所有类型的共同父类是Object
class Person(object):
def __init__(self,name,age):
self.name=name
self.age=age
def info(self):
print('姓名:{0},年龄:{1}'.format(self.name,self.age))
class Student(Person):
def __init__(self,name,age,score):
super().__init__(name,age)
self.score=score
stu=Student('小红',20,'80')
stu.info()#姓名:小红,年龄:20
方法重写
用super()
表示调用父类
在子类中也可以重写父类,用同一个方法名
def info(self):
super().info()
print(self.score)
Object类
print(dir(对象/类))
可以显示现在有多少方法
object有一个__str__()
方法,用于返回一个对于对象的描述。print(对象)
原本输出对象的内存地址。我们可以把它重写,让它输出属性值。
class Student:
def __init__(self,name,age)
self.score=score
def __str__(self):
return '名字{0},今年{1}岁'.format(self.name,self.age)
stu=Student('小红',20,'80')
print(stu)#名字小红,今年20岁
一般会在写完这个类的时候再去重写__str__
方法,用于返回对象的描述
多态
在运行过程中,根据变量所引用的对象的类型,动态决定调用哪个对象的方法
动态语言(python)(崇尚鸭子类型):不需要关系对象是什么类型,只关心对象的行为
静态语言(java)实现多态的三个必要条件:继承、方法重写、父类引用指向子类对象
特殊方法和特殊属性
特殊属性
名称 | 描述 |
---|---|
__dict__ | 获得类对象所绑定的属性和方法的字典,或实例对象属性的字典 |
__class__ | 输出对象所属的类 |
__bases__ | 父类类型的元素 |
__base__ | 输出一个距离它最近的父类(定义时谁写前边就输出谁) |
__mro__ | 查看类的层次结构 |
__subclasses__() | 子类的列表 |
特殊方法
名称 | 描述 |
---|---|
__len__() | 通过重写_len_()方法,让内置函数len()的参数可以是自定义类型 |
__add__() | 通过重写_add_()方法,可使自定义对象具有“+”功能 |
__new__() | 用于创建对象 |
__init__() | 对创建的对象进行初始化 |
c=a+b
d=a.__add__(b)
class Student:
def __init__(self,name):
self.name=name
def __add__(self, other):
return self.name+other.name
stu1=Student('张三')
stu2=Student('李四')
s=stu1+stu2
print(s)
先new新建,再init初始化
类的浅拷贝与深拷贝
变量的赋值操作
只有一个对象的实例,用了两个变量去指。同一个对象赋给了两个变量
浅拷贝
python拷贝一般都是浅拷贝,拷贝时,对象包含的子对象内容不拷贝。
因此,源对象与拷贝对象会引用同一个子对象。
深拷贝
使用copy的deepcopy函数,递归拷贝对象中包含的子对象,源对象和拷贝对象所有的子对象也不相同
cpu=Cpu()
disk=Disk()
computer=Computer(cpu,disk)
computer1=computer #赋值
import copy
computer2=copy.copy(computer)#浅拷贝。对象地址不同,子对象地址相同
computer3=copy.deepcopy(computer)#深拷贝。对象地址、子对象地址都不相同
十四、模块化
什么叫模块
Modules,一个模块可以包含N多个函数。在Python中一个扩展名为.py的文件就是一个模块。使用模块:方便其它程序/脚本导入并使用;避免函数名和变量冲突;提高代码的可维护性;提高代码的可重用性
自定义模块
创建模块:新建一个.py文件,名称尽量不要与Python自带的标准模块名称相同
导入模块:
import 模块名称 [as 别名]
form 模块名称 import 函数/变量/类
import math
print(pow(2,3))#8
print(math.pow(2,3))#8.0
print(math.ceil(9.001))#10
print(math.floor(9.999))#9
新建一个calc.py
def add(a,b):
return a+b
在要用的地方导入模块使用
方法1
import calc
print(calc.add(1,2))
方法2
from calc import add
print(add(1,2))
老师说要标记一下。。但是我不标记没报错。。
以主程序的形式执行
每个模块都有一个记录模块名称的变量__name__,程序可以检查该变量,以确定他们在哪个模块中执行。顶级模块的__name__变量的值为__main__
#calc.py
def add(a,b):
return a+b
if __name__ == '__main__':
print('只有在运行calc时才输出这句话')
python中的包
包是一个分层次的目录结构,它将一组功能相近的模块组织在一个目录下
作用:
代码规范、避免模块名称冲突
包与目录的区别:
包含__init__.py文件的目录称为包
目录里通常不包含__init__.py文件
使用import方式进行导入时,只能跟包名或模块名
import calc
import pg1
使用from…import 可以导入包、模块、函数、变量
from pg1 import moduleA
from pg1.moduleA import a
Python中常用的内置模块
模块名 | 描述 |
---|---|
sys | 与Python解释器及其环境操作相关的标准库 |
time | 提供与时间相关的各种函数的标准库 |
os | 提供了访问操作系统服务功能的标准库 |
calendar | 提供了与日期相关的各种函数的标准库 |
urllib | 用于读取来自网上(服务器)的数据标准库 |
json | 用于使用json序列化和反序列化对象 |
re | 用于在字符串中执行正则表达式匹配和替换 |
math | 提供标准算术运算函数的标准库 |
decimal | 用于进行精确控制运算精度、有效数位和四舍五入操作的十进制运算 |
logging | 提供了灵活的记录事件、错误、警告和调试信息等日志信息的功能 |
import sys
print(sys.getsizeof(24))
print(sys.getsizeof(True))
print(sys.getsizeof(False))
import time
print(time.time())
print(time.localtime())
import urllib.request
print(urllib.request.urlopen('http://www.baidu.com').read())
import math
print(math.pi)
第三方模块的安装及使用
第三方模块的安装
在cmd中pip install schdule
。(建议直接在pyCharm里import然后按提示安装)
pip不识别的话记得配置环境变量。系统变量path中放入python目录下C的Scripts
import schedule
import time
def job():
print('haha')
schedule.every(3).seconds.do(job)
while True:
schedule.run_pending()
time.sleep(1)
十五、文件
编码格式介绍
Python的解释器使用的是Unicode(内存)
.py文件在磁盘上使用UTF-8存储(外存)
文件的读写原理
文件读写操作
file=open('a.txt','r')
print(file.readlines())
file.close()
输出:
['中国\n', '好吃']
常用的文件打开方式
文本文件:存储的是普通“字符”文本,默认为unicode字符集,可以使用记事本程序打开
二进制文件:把数据内容用“字节”进行存储,无法用记事本打开,必须使用专用的软件打开。如:mp3、jpg、doc
打开方式 | 描述 |
---|---|
r | 以只读模式打开文件,文件的指针将会放在文件的开头 |
w | 以只写模式打开文件,如果文件不在则创建。如果文件存在,则覆盖原有内容,文件指针在文件的开头 |
a | 以追加模式打开文件,如果文件不存在则创建,文件指针在文件开头。如果文件存在,则在文件末尾追加内容,文件指针在原文件末尾 |
b | 以二进制方式打开文件,不能单独使用,需要与其他模式一起使用,rb、或者wb |
+ | 以读写方式打开文件,不能单独使用,需要与其他模式一起使用,a+ |
文件拷贝:
src_file=open('logo.png','rb')
target_file=open('copylogo.png','wb')
target_file.write(src_file.read())
target_file.close()
src_file.close()
文件对象常用的方法
方法 | 说明 |
---|---|
read([size]) | 从文件中读取size个字节或字符内容返回,若省略[size],则读取到文件末尾,即一次读取文件所有内容 |
readlines() | 从文本文件中读取一行内容 |
write(str) | 把文本文件中每一行都作为独立的字符串对象,并将这些对象放入列表中返回 |
writelines(s_list) | 将字符串列表s_list写入文本文件,不添加换行符 |
seek(offset[,whence]) | 把文件指针移动到新的位置,offset表示相对于whence的位置: offset:正,往结束方向移动。负,往开始方向移动 whence:0,从文件头开始计算。1,从当前位置开始计算。2,从文件尾开始计算 |
tell() | 返回文件指针的当前位置。从0开始计算 |
flush() | 把缓冲区的内容写入文件,但不关闭文件 |
close() | 把缓冲区的内容写入文件,同时关闭文件,释放文件对象相关资源 |
with语句(上下文管理器)
with语句可以自动管理上下文资源(不用手动关闭),不论什么原因(是否产生异常)跳出with块,都能确保文件正确的关闭,以此来达到释放资源的目的
自动调用__enter__、__exit__方法
文件赋值↓
with open('logo.png','rb') as src_file:
with open('copy21logo.png','wb') as target_file:
target_file.write(src_file.read())
目录操作
os模块——操作系统相关的一个模块
import os
os.system('notepad.exe')
os.startfile("D:\\Program Files\\Typora\\Typora.exe")
打开记事本。相当于在运行(win+R)中写notepad。
calc计算器
os模块操作目录:
函数 | 说明 |
---|---|
getcwd() | 返回当前的工作目录 |
listdir(path) | 返回指定路径下的文件和目录信息 |
mkdir(path[,mode]) | 创建目录 |
makedirs(path1/path2...[,made]) | 创建多级目录 |
rmdir(path) | 删除目录 |
removedirs(path1/path2...) | 删除多级目录 |
chdir(path) | 将path设置为当前工作目录 |
os.path模块操作目录相关函数:
函数 | 说明 |
---|---|
abspath(path) | 用于获取文件或目录的绝对路径 |
exists(path) | 用于判断文件或目录是否存在,存在返回Ture,否则返回False |
join(path,name) | 将目录与目录或文件名拼接起来 |
split() | 拆分目录和文件 |
splitext() | 分离文件名和扩展名 |
basename(path) | 从一个目录中提取文件名 |
dirname(path) | 从一个路径中提取文件路径,不包括文件名 |
isdir(path) | 用于判断是否为路径 |
列出指定目录下的所有py文件
import os
path=os.getcwd()
lst=os.listdir(path)
for filename in lst:
if filename.endswith('.py'):
print(filename)
endswith()
表示以...结尾
walk可以编历目录下的各种子目录文件
import os
path=os.getcwd()
lst_files=os.walk(path)
for dirpath,dirname,filename in lst_files:
'''print(dirpath)
print(dirname)
print(filename)'''
for dir in dirname:
print(os.path.join(dirpath,dir))
for file in filename:
print(os.path.join(dirpath,file))
十六、学生信息管理系统
需求分析
系统设计
录入学生信息
查找学生信息
删除学生信息
修改学生信息
学生成绩排名
统计学生总人数
显示全部学生信息
系统开发必备
主函数设计
学生信息维护模块设计
录入学生信息功能:从控制台录入学生信息,并且把它们保存(save()
)到磁盘文件中
def save(lst):
try:
stu_txt=open(filename,'a',encoding='UTF-8')
except:
stu_txt=open(filename,'w',encoding='UTF-8')
for item in lst:
stu_txt.write(str(item)+'\n')
stu_txt.close()
删除学生信息
def delete():
while True:
student_id=input('请输入要删除的学生的ID:')
if student_id!='':
if os.path.exists(filename):#如果文件存在在目录下
with open(filename,'r',encoding='UTF-8') as file:
student_old=file.readlines()
else:
student_old=[]
flag=False #标记是否删除
if student_old:
with open(filename,'w',encoding='UTF-8') as wfile:
# d={}
for item in student_old:
d=dict(eval(item)) #将字符串转成字典
if d['id']!=student_id:
wfile.write(str(d)+'\n')
else:
flag=True
if flag:
print(f'id为{student_id}的学生信息已被删除')
else:
print(f'没有找到id为{student_id}的学生')
else:
print('无学生数据')
break
show() #删完之后重新显示所有学生信息
answer=input('是否继续删除?y/n\n')
if answer=='y' or answer=='Y':
continue
else:
break
d=dict(eval(item)) #将字符串转成字典
修改学生信息
查询学生信息:
展示↓
def show_student(lst):
if len(lst)==0:
print('没有查询到学生信息,无数据显示!!')
return
#定义标题显示格式
format_title='{:^6}\t{:^12}\t{:^8}\t{:^10}\t{:^10}\t{:^8}'
print(format_title.format('ID','姓名','英语成绩','python成绩','java成绩','总成绩'))
#定义内容的显示格式
format_data='{:^8}\t{:^8}\t{:^8}\t{:^8}\t{:^8}\t{:^8}'
for item in lst:
print(format_data.format(item.get('id'),item.get('name'),item.get('english'),item.get('python'),item.get('java'),int(item.get('english')+item.get('python')+item.get('java'))))
统计学生总人数
显示所有学生信息
排序模块设计
sort()
函数用于对原列表进行排序,如果指定参数,则使用比较函数指定的比较函数。
list.sort( key=None, reverse=False)
key -- 主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。
reverse -- 排序规则,reverse = True 降序, reverse = False 升序(默认)。
lambda ※
tudent_new.sort(key=lambda x:int(x['english']),reverse=asc_or_desc_bool)
def sort():
show()
if os.path.exists(filename):
with open(filename,'r',encoding='UTF-8') as rfile:
student_lst=rfile.readlines()
student_new=[]
for item in student_lst:
d=dict(eval(item))
student_new.append(d)
else:
return
while True:
asc_or_desc=input('请选择(0.升序 1.降序):')
if asc_or_desc=='0':
asc_or_desc_bool=False
break
elif asc_or_desc=='1':
asc_or_desc_bool = True
break
else:
print('您的输入有误,请重新输入')
while True:
mode=input('请选择排序方式(1.按英语成绩排序 2.按Python成绩排序 3.按java成绩排序 4.按总成绩排序):')
if mode!='1' and mode!='2'and mode!='3'and mode!='4':
print('您的输入有误,请重新输入')
sort()
continue
elif mode=='1':
student_new.sort(key=lambda x:int(x['english']),reverse=asc_or_desc_bool)
elif mode=='2':
student_new.sort(key=lambda x:int(x['python']),reverse=asc_or_desc_bool)
elif mode == '3':
student_new.sort(key=lambda x:int(x['java']),reverse=asc_or_desc_bool)
elif mode=='4':
student_new.sort(key=lambda x:int(x['english'])+int(x['python'])+int(x['java']),reverse=asc_or_desc_bool)
break
show_student(student_new)
项目打包
安装:pip install PyInstaller
打包:pyinstaller -F D:\study\python\16-\stusystem.py
打包完之后倒数第二行:10833 INFO: Appending archive to EXE C:\WINDOWS\system32\dist\stusystem.exe
然而每次要修改文件的时候就会闪退,我也不知道为什么。┑( ̄Д  ̄)┍
十七、实操案例
print输出
输出到文件
fp=open('D:/test.txt','w')
print('输出到文件',file=fp)
fp.close()
文件读写
有赋值的输出
循环list输出、字典输出、字典的内置函数zip()
lst_name=['林黛玉','薛宝钗','贾元春','贾探春','史湘云']
lst_sig=['①','②','③','④','⑤']
for i in range(5):
print(lst_sig[i],lst_name[i])
d={'①':'林黛玉','②':'薛宝钗','③':'贾元春','④':'贾探春','⑤':'史湘云'}
for key in d:
print(key,d[key])
for s,name in zip(lst_sig,lst_name):
print(s,name)
有颜色的输出
\033[显示方式; 前景色; 背景色m****\033[0m
其中******表示被标记的内容。可以缺省书写,使用默认设定。
print('\033[0:35m图书音像勋章\033[m')
进制转换
num=int(input('请输入一个十进制的整数:'))
print(num,'的二进制数为:',bin(num))
print(str(num)+'的二进制数为:'+bin(num))
print('%s的二进制数为:%s' % (num,bin(num)))
print('{0}的二进制数为:{1}'.format(num,bin(num)))
print(f'{num}的二进制数为:{bin(num)}')
print(f'{num}的八进制数为:{oct(num)}')
print(f'{num}的十六进制数为:{hex(num)}')
支付密码格式验证
s='支付密码合法' if pwd.isdigit() else '支付密码只能是数字'
数字竞猜(随机数)
price=random.randint(1000,2000)
车票购买
dict={'aaa':['1','2','3'],
'bbb':['4','5','6']}
for item in dict:
print(item)
for i in dict[item]:
print(i)
对字典dict进行for…in,item表示的是key值
对列表lst进行for…in,item表示的是lst[i],也就是元素值(而不是索引)
咖啡购买(元组编历)
enumerate() 函数:用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。
t1=('hello','world',80)
for index,item in enumerate(t1):
print(f'{index} {item}')
也可以逆向查找
print(t1[2])
高铁售票
下载模块:prettytable
import prettytable as pt
tb=pt.PrettyTable()
tb.field_names=['行号','座位1','座位2','座位3','座位4']
for i in range(4):
lst=[f'第{i}行','有票','有票','有票','有票']
tb.add_row(lst)
print(tb)
可以显示整齐的表格
计算日期
用到模块:datetime
import datetime
sdate=datetime.datetime.strptime('2021-07-29','%Y-%m-%d')
fdate=sdate+datetime.timedelta(days=20)
print(f'20天之后是{fdate}')
print(f'20天之后是{str(fdate).split(" ")[0]}')
输出:
20天之后是2021-08-18 00:00:00
20天之后是2021-08-18
记录查看登陆日志