仅是个人笔记,图片还是没能上传成功不知道为啥,这个我现在也不太想解决。文章仅作为个人笔记哈。大家加油!!!

第一章 Python基础语法 3.8

1-1Python概述

python基础部分:

●Python基础语法: 标识符,关键字,变量,判断循环。。。。
●容器类型(数据类型中的高级类型)
●函数
●文件处理
●面向对象
●包和模块
●异常处理

知道自己能够解决什么问题
能够解决自己没有遇到过的问题
坚信自己能够解决自己没有遇到的这个问题

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Y0gfVp6a-1670931802452)(img/image-20221108211931165-1668172829069.png)]

1、为啥学Python?

1.技术趋势,要用。
2.简单易学。
3.应用广泛。Python语言涉及IT行业70%以上的技术领域。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B5tplCVU-1670931802453)(img/image-20221111180533540.png)]

Python语言的创始人 吉多·范罗苏姆 龟叔

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aVdLFNXZ-1670931802454)(img/20171018174524234-1668172818085)]

2、Python 2.x与Python 3.x版本对比

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hIqvkrW2-1670931802454)(img/image-20221110154034531.png)]

3、本次学习3.8版本

Python是一种跨平台的计算机程序设计语言。是一个高层次的结合了解释性、编译性、互动性和面向对象的语言。最初被设计用于编写自动化脚本Shell (适用于Linux操作系统),随着版本的不断更新和语言新功能的添加,逐渐被用于独立的,大型项目的开发。

其实目前很多知名的机器学习,人工智能以及深度学习框架也都是基于Python语言进行开发的:
●Google开源机器学习框架: TensorFlow
●开源社区主推学习框架: Scikit-learn
●百度开源深度学习框架: Paddle

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qwpYJ8E1-1670931802454)(img/image-20221108212948034.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5T7AEGqr-1670931802455)(img/image-20221108213144902.png)]

1-2Python环境搭建

1、Python解释器的作用

Python解释器的作用:将python语言编程的代码解释为机器语言(二进制文件)的一种工具。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-U40BD1zb-1670931802455)(img/image-20221109135011212.png)]

2、Python解释器种类

①CPython, C语言开发的解释器[官方],应用广泛的解释器。官方版本,稳定,持续更新
②lPython,基于CPython的一种交互式解释器。可交互,在CPython基础上进行了升级
③其他解释器
PyPy,基于Python语言言开发的解释器。
JPython,运行在Java平台的解释器,直接把Python代码编译成Java字节码文件。
lronPython,运行在微软.Net平台上的Python解释器,可直接把Python代码编译成.Net的字节码。

3、下载Python解释器 python-3.10.0-amd64.exe

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JN7ubAB4-1670931802455)(img/image-20221110162203469.png)]

4、Pycharm

4.1 PyCharm是-种Python IDE (集成开发环境) ,带有一整套可以帮助用户在使用Python语言开发时提高其效率的工具,内部集成的功能如下:
Project管理
智能提示
语法高亮
代码跳转
调试代码

4.2Pycharm分为专业版和社区版。我们下载安装社区版本就够用了。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s3UpwU52-1670931802455)(img/image-20221110162619264.png)]

4.3 去官网下载安装pycharm社区版。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-k430BG7m-1670931802456)(img/image-20221110162751744.png)]

4.4新建新项目

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l5XL2SZZ-1670931802456)(img/image-20221110162917022.png)]

4.5创建新python文件

test01.py

4.6 HelloWorld

print('Hello World!')

4.7 pycharm配置
主题配置(不配置也不影响)、
字体配置(不配置也不影响)、
项目解释器配置、

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8Mxqd83O-1670931802456)(img/image-20221110164226430.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZnqibmZQ-1670931802456)(img/image-20221110163937799.png)]

4.8 项目管理

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Z1asZUkU-1670931802457)(img/image-20221110164122977.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UybL36fE-1670931802457)(img/image-20221110164153272.png)]

1-3变量与注释

1.注释

单行注释:# 注释内容(单行注释在一行的开头要留一个空格。单行注释在行末要留两个空格。)

多行注释:三对单引号或三对双引号。

# 这个就是单行注释(注意要有空格)
"""
这是个多行注释
"""
'''
这也是个多行注释
'''
ctrl+/ 单行注释快捷键
多行注释不能放在一行的。末尾都用单行注释,这种了解就行。
单行注释和多行注释颜色不一样,其他都一样。

2.变量

变量,就是存放数据的,一个有名字的盒子。
变量名就是盒子的名字,数据装在盒子中。

变量定义的基本语法:

变量名 = 变量值

=两边都要保留一个空格,变量名可以自定义,但是要满足标识符命名规则。

在python中变量必须赋值否则报错。

3.标识符的命名规则

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eHepi7cR-1670931802457)(img/image-20221108220858464.png)]

标识符和关键字:

标识符是自己定义的名字。关键字是提前定义好的名字,我们新起的名字不能与其重名。

在windows中文件名定义时不严格区分大小写。

1-4变量与debug工具

1、标识符命名规范

1。变量命名,一定要做到见名知义
2。大驼峰:即每个单词首字母都大写,例如: MyName (类名)
3。小驼峰:第二个(含)以后的单词首字母大写,例如: myName
4。划线:例如: my_name (变量名、函数名、包名、模块名使用下划线命名法)

name = '小明'
num = 10

2、变量的使用

所有的变量要先定义再调用。

3、变量的数据类型

注意:
布尔类型的值只能是True或False,其他的都不行,大小写不一致也不行。

●int 整型
●float 浮点型
●bool 布尔型
●str 字符型字符串
●list 列表
●tuple 元组
●set 集合
●dict 字典

# 数据类型查看的函数 
type(数据/变量名)
# 例如:
int1 = 12
print(type(int1))   # <calss 'float'>

pycharm 格式化快捷键( ctrl + alt + L)

4、Bug 和 Debug

1、bug:程序中的错误

2、Debug:Debug工具是PyCharm IDE中集成的专门用来调试程序的工具,在这里程序员可以查看程序的执行细节和流程,以方便我们快速找出程序的Bug!
Debug工具使用二步走:①打断点②Debug调试

2.1、打断点
断点位置:断点要定位在Python代码段的第一行即可
打断点的方法:在需要调试代码行的行号位置右侧的空白处单击即可

2.2、Debug调试

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-61KIClqI-1670931802458)(img/image-20221109144047980.png)]

Debug输出面板分类

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PZlgj4b3-1670931802458)(img/image-20221109144121516.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pz8aa4Tw-1670931802458)(img/image-20221109145358184.png)]

●bug调试工具的使用
。打断点:在行号后边点击出现小红点
。右键debug进 入调试模式,代码执行暂停到断点位置代码执行之前
■debugger: 查看参数及变量在执行过程中的变化情况
■console: 查看控制台输出内容
■stepover: 单步执行代码
■resume:执行到下一次断点位置或程序结束
■stop:让程序终止

易错点

进入Debug模式之前一定要先打断点。否则程序直接全部执行。

1-5格式化输出

1、输出

程序输出给用户

2、格式化输出

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WcVRqOmy-1670931802458)(img/image-20221109151431456.png)]

字符串格式化:格式化是字符串所具有的功能
print输出:print函数只能将传入的内容显示到控制台中,与格式化没有任何关系。

age = 16
str1 = '小明 %d 岁'% age
print(str1)
# 输出
# 小明 16 岁
# 格式:"字符串,占位符"%变量
# 在上述格式中,格式化完成后,会将占位符位置上填充上对应的变量。
# 不同数据类型的变量,要使用不同的占位符

# 字符串数据使用 %s
# 浮点型数据使用 %f
# 浮点型数据使用 %.2f,浮点数精确到小数点后两位。
# 整形数据使用   %d
# 整形数据使用   %6d,控制int型数值为6为,不足补0。
name = "xiaoming"
age = 18
height = 1.85
weight = 61.5
marrage = False
print("小明的姓名是%s,今年%d岁,身高为%f,体重为%f,婚姻状态为%s" %(name,age,height,weight,marrage))

注意

自动换行效果:点击View -> Active Editor -> 点击soft-wrap

一个输出中引用多个变量,%后面的所有变量名要放在小括号中。否则报错。
TypeError: not enough arguments for format string
占位符的数量和变量的数量和顺序都要保持一致。否则报错。

f-格式化字符串是Python3.6中新增的格式化⽅法,该方法更简单易读。

1-6输入与类型转化

1、转义字符

\n :换行符
\t :制表符,一个tab键(4个空格)的距离
%% :输出%
为什么print的输出自带换行效果?
按住 Ctrl键 鼠标点击 print,进入print的源码界面。
	def print( self , *args , sep=' ' , end='\n' , file=none ):
通过源码可以看出,print在结尾自动加入了\n。
end='$$$'
# 此操作可以使此print的无法自动换行。而是直接输出$$$
print(123,'sf',end='$$$') 
"""
实现原理:
        end='$$$'
        此操作将print运行中的end的值由"/n"换成了"$$$"
"""

2、f-string (Python3.6以后推出的格式化方式)

f-string是Python3.6以后推出的格式化方式。

格式:f'要输出的内容{变量}'

print("小明的姓名是%s,今年%d岁,身高为%f,体重为%f,婚姻状态为%s" %(name,age,height,weight,marrage))
上式,用f-string表示,等价于
print(f"小明的姓名是{name},今年{age}岁,身高为{height},体重为{weight},婚姻状态为{marrage}" )
如果需要调整精度:
print(f"小明的姓名是{name},今年{age:03d}岁,身高为{height:.2f},体重为{weight:.2f},婚姻状态为{marrage}" )

3、input输入

# 输入使用的是input函数
# 格式:input(提示字符)
# 使用功input函数会造成程序阻塞,等待输入信息。按enter键输入
input('请输入一个字母:')
num = input('请输入一个数字')
print(num)

练习:按要求输入账号和密码,并将账号和密码打印

account = input('请输入您的账号:')
password = input('请输入您的密码:')
print('您的账号是%s,您的密码是%d' %account,password)

4、数据类型转换

函数

说明

int(x [,base ])

将x转换为一个整数

float(x)

将x转换为一个浮点数

complex(real [,imag ])

创建一个复数,real为实部,imag为虚部

str(x)

将对象 x 转换为字符串

repr(x)

将对象 x 转换为表达式字符串

eval(str)

用来计算在字符串中的有效Python表达式,并返回一个对象

tuple(s)

将序列 s 转换为一个元组

list(s)

将序列 s 转换为一个列表

chr(x)

将一个整数转换为一个Unicode字符

ord(x)

将一个字符转换为它的ASCII整数值

hex(x)

将一个整数转换为一个十六进制字符串

oct(x)

将一个整数转换为一个八进制字符串

bin(x)

将一个整数转换为一个二进制字符串

int类型的数据转换成float类型的数据,在整数末尾加.0。
int类型的数据转换成字符串类型的数据,可以随意转换。

float类型的数据转换成int类型的数据,只保留整数部分。
float类型的数据转换成字符串类型的数据,可以随意转换。

字符串型数据想要转化成int类型,字符串中的数据必须是int类型。其他类型都不行。
字符串型数据想要转化成float类型数据,字符串中的数据必须是数值类型数据。

1-7Python运算符

在除法运算中结果必定是浮点数。
浮点型参与运算后结果一定是浮点型。

算术运算符
赋值运算符
复合赋值运算符
比较运算符
逻辑运算符

1、算数运算符

运算符

描述

实例

+

1 + 1 输出结果为 2

-

1 - 1 输出结果为 0

*

2 * 2 输出结果为 4

/

10 / 2 输出结果为 5

//

整除

9 // 4 输出结果为2

%

取余(取模)

9 % 4 输出结果为 1

**

幂指数

2 ** 4 输出结果为 16,即 2 * 2 * 2 * 2

()

小括号

小括号用来提高运算优先级,即 (1 + 2) * 3 输出结果为 9

2、算数运算符优先级

混合运算优先级顺序:( ) 高于 ** 高于 *  /  //  %  高于 +  -

3、赋值运算符

给变量赋值

a = 10

给多个变量赋值

a,b,c = 10,"计算机",12.8

给多个变量赋相同值

a = b = c = 10

4、符合赋值运算符

+=	a += b 相当于  a = a+b
-=	a -= b 相当于  a = a-b
*=	a *= b 相当于  a = a*b
/=	a /= b 相当于  a = a/b
//=	a //= b 相当于  a = a//b
%=	a %= b 相当于  a = a%b
**=	a **= b 相当于  a = a**b

5、比较运算符

<
>
==
!=
>=
<=
<>不可以使用

6、逻辑运算符

and
or
not

7、短路运算

python 把 0、none、空字符串,看成False,其他数值和非空字符串都看成True:

a and b :如果a是False那结果必为False,因此返回 a;如果 a 是 True,则整个计算结果必定取决与 b,因此返回 b。
在计算 a or b 时,如果 a 是 True,则根据或运算法则,整个计算结果必定为 True,因此返回 a;如果 a 是 False,则整个计算结果必定取决于 b,因此返回 b。

8、运算符的优先级

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zwIBcRNl-1670931802459)(img/image-20221111182902768.png)]

不用太过纠结,自己编程时不太确定的可以直接打括号提升优先级

1-8Python分支语句

1、if

if基本语法

if 条件:
    条件成立执行的代码1
    条件成立执行的代码2
    ......

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fy9Mfysa-1670931802459)(img/image-20221111183251696.png)]

2、if…else…

if 条件:
    条件成立,执行的代码1
else:
    条件不成立,执行的代码2
age = int(input('请输入您的年龄:'))
if age >= 18:
    print(f'您的年龄是{age},已经成年,可以上网')
else:
    print(f'您的年龄是{age},未成年,请自行回家写作业')
print('系统关闭')

3、if…elif…else多重判断语句

if 条件1:
    条件1成立执行的代码1
    条件1成立执行的代码2
    ......
elif 条件2:
    条件2成立执行的代码1
    条件2成立执行的代码2
    ......
......
else:
    以上条件都不成立执行的代码

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oTkXk3dk-1670931802459)(img/image-20221111183551550.png)]

4、if嵌套结构

if 条件1:
    条件1成立执行的代码
    条件1成立执行的代码
    
    if 条件2:
        条件2成立执行的代码
        条件2成立执行的代码
"""
1. 如果有钱,则可以上车
    2. 上车后,如果有空座,可以坐下
    上车后,如果没有空座,则站着等空座位
如果没钱,不能上车
"""
# 假设用 money = 1 表示有钱, money = 0表示没有钱
money = 1
if money == 1:
    print('土豪,不差钱,顺利上车')
else:
    print('没钱,不能上车,追着公交车跑')
"""
1. 如果有钱,则可以上车
    2. 上车后,如果有空座,可以坐下
    上车后,如果没有空座,则站着等空座位
如果没钱,不能上车
"""
# 假设用 money = 1 表示有钱, money = 0表示没有钱; seat = 1 表示有空座,seat = 0 表示没有空座
money = 1
seat = 0
if money == 1:
    print('土豪,不差钱,顺利上车')
    if seat == 1:
        print('有空座,可以坐下')
    else:
        print('没有空座,站等')
else:
    print('没钱,不能上车,追着公交车跑')

5、三目运算符

三目运算符也叫三元运算符。

语法如下:

值1 if 条件 else 值2
# 求两个数的最大值:
a = 1
b = 2
c = a if a > b else b
print(c)
今日作业:
1.从键盘中输入三个任意数值,求最大值
2.期末考试结束了,根据学员成绩求学员等级:90分及以上则为A,60分及60分到90之间则为B,小于60分则为C。
3.红绿灯案例:手动输入红绿灯状态如state="红灯",根据红绿灯状态,输出小汽车的运行状态。正常通行、停车等待、观察并慢行。
4.有一物,不知其数,三三数之余二,五五数之余三,七七数之余二,问物几何?(100以内数值)
for i in range(1,100):
    if(i % 3 == 2 and i % 5 == 3 and i % 7 == 2):
        print(i)
        break
else:
    print("没有符合要求的数")
# 23

1-9分支总结与复习

1-10while循环

程序是为了解决实际问题的,实际问题中存在着重复动作,那么程序中也应该有相应的描述,这就是循环。
在Python中,循环结构分为while和for两种。

1、while循环基本语法

while 条件:
    条件成立重复执行的代码1
    条件成立重复执行的代码2
    ......
# print任务循环执行5次,因为此5次循环print的内容都没有变化,所以现实的效果为print重复执行5次。
i = 0
while i < 5:
    print('老婆大人,我错了')
    i += 1
print('任务结束')

2、循环成立条件

看不明白,就多写几次循环的程序。找到感觉就OK了。

(1)初始状态(可选)
(2)循环条件
(3)循环体(要重复做的事情)
(4)为下次循环作准备()

# 求 1~100的总和5050
i = 1
result = 0
while i <= 100:
    result += i
    i += 1
print(result)
# 方法二
sum1= 0
for i in range(1,101):
    sum1 += i
print (sum1)

1-11while循环嵌套

1、死循环

死循环就是循环条件永远成立。不是bug。

2、循环嵌套

循环体中包含其他循环叫做循环嵌套

外层循环执行一次,内层循环,循环执行一遍。

# 三组训练,一组训练要跑4圈+做10分钟深蹲
i = 0
while(i < 3):
    print(f"第{i+1}组训练开始:")
    j = 0
    while(j < 4):
        print("跑" + str(j+1) + "圈")
        j += 1
    print("深蹲十分钟")
    i += 1

3、break 和 continue

break结束整个循环
continue结束此次循环

练习

# 有3只兔子,第二年的数量为第一年的两倍,以此类推。求,输入n年后,输出兔子数量
one_year_sum = 3
year = 0
while (year != -1):
    print("请输入第几年:")
    year = int(input())
    if( year <= 0):
        break
    print(f"您输入的是第 {year} 年")
    print(f"今年兔子的数量为 {one_year_sum * 2 ** (year - 1)}")
# 需求:猜你相亲对象的年龄,3次机会。猜对输出成功,猜错say byebye
# 先输入一个20到35之间的整数。3次猜的机会。猜对输出成功,猜错say byebye
run = 1
j = 0
while (run == 1):
    print("girl please input your age:")
    gril_age = int(input())
    if(gril_age < 20 or gril_age > 35):
        print("Oh,Come on ! Are you kidding me?")
    else:
        run = 2
print("Boy,try it,i believe with you:")
while (j < 3):
    number = int(input())
    if(number == gril_age):
        print("You are right.")
        break
    else:
        if(j == 2):
            print("Bye bye")
            break
        print(f"你还有{4-j-2}次机会")
        j +=1
# 打印九九乘法表
i = 1
while (i < 10):
    j = 1
    while (j < 10):
        print(f"{i} x {j} = {i*j:02}",end = "  ")
        j +=1
    print()
    i += 1
    
# 打印九九乘法表
i = 1
while (i < 10):
    j = 1
    while (j < i+1):
        print(f"{j} x {i} = {i*j:02}",end = "  ")
        j +=1
    print()
    i += 1
# 倒直角三角(5行5列)
raw = 0
while(raw < 5):
    line = 0
    while( line < 5 - raw ):
        print("*",end=" ")
        line += 1
    print()
    raw += 1
# 倒等腰三角(六行六列)
i = 0
num = 6
while(i < num):
    j = 0
    while(j < num):
        if(j < i or j >= num - i):
            print(" ", end=" ")
        else:
            print("*", end=" ")
        j += 1
    print()
    i += 1

1-12for循环

1、基本语法

for循环时遍历数据序列,每次获取-个元素,直到元素全部被获取,结束循环。

for临时变量in序列: :
重复执行的代码1
重复执行的代码2

案例演示:
str1 = 'itcast'
for i in str1:
	print(i)
"""
i
t
c
a
s
t
"""

for循环和while循环的区别:
1、for循环数据序列,元素提取完成自动停止,不需要使用循环变量
2、for循环不需要循环条件,所以也不会有循环条件成立喝不成立的说法
3、在开发中我们使用for循环的比例居多, while循环主要是构造死循环结构
4、for循环需要配合容器类型(数据序列)进行使用

2 、range

Python2 range()函数返回的是列表,而在Python3中 range()函数返回的是一个可迭代对象(类型是对象) ,而不是列表类型,所以打印的时候不会打印列表。( 由于我们还未学习面向对象,为了方便大家理解,你可以简单的将其理解为一个序列结构)

基本语法:

range(stop)
range(start,stop[,step]) # 包含起始位置不包含结束位置

start:计数从start开始。默认是从0开始。例如range (5 )等价于range (0,5) ;
stop:计数到stop结束,但不包括stop.例如: range (0,5)是[0,1,2,3, 4]没有5
step:步长,默认为1。例如:range(0,5)等价于range(0,5,1)

案例演示:

for i in range(5):
    print(i)

怎样打印range中的所有元素呢?list(range类型)

print(list(range(0,5,1)))
# [0,1,2,3,4]

步长为1可以省略
起始位置为0时可以省略,但起始位置省略时,步长也必须省略。

小案例

# sum(1~100)
sum = 0;
for i in range(1,101):
    sum += i
print(sum)

# 1~100偶数和
sum = 0;
for i in range(2,101,2):
    sum += i
print(sum)

#

3、break 和 continue

break和continue是循环中满足一定条件退出循环的两种不同方式
和while中的一样

4、for循环嵌套

所谓for循环嵌套,就是一个for循环里面嵌套另外一个for循环的写法。当循环结构相互嵌套时,位于外层的循环结构常简称为外层循环或外循环,位于内层的循环结构常简称为内层循环或内循环。

# for 九九乘法表
for i in range(1,10):
    for j in range (1,i+1):
        print(f" {j} x {i} = {i*j:02}",end="  ")
    print()
# 过7游戏
# 在1~100中 ,7和7的倍数、所有带有7的数字。换成输出“哈”
#
for i in range(1,101):
    if(i % 20 == 0):
        print()
    if(i//10 == 7):
        print("ha", end=" ")
        continue
    if(i % 10 == 7):
        print("ha", end=" ")
        continue
    if(i % 7 == 0):
        print("ha",end=" ")
        continue
    else:
        print(f"{i:02}",end=" ")
 -----------------------------------
01 02 03 04 05 06 ha 08 09 10 11 12 13 ha 15 16 ha 18 19 
20 ha 22 23 24 25 26 ha ha 29 30 31 32 33 34 ha 36 ha 38 39 
40 41 ha 43 44 45 46 ha 48 ha 50 51 52 53 54 55 ha ha 58 59 
60 61 62 ha 64 65 66 ha 68 69 ha ha ha ha ha ha ha ha ha ha 
80 81 82 83 ha 85 86 ha 88 89 90 ha 92 93 94 95 96 ha ha 99 
100 

# 过7游戏
# 在1~100中 ,7和7的倍数、所有带有7的数字。换成输出“哈”
#
for i in range(1,101):
    if(i % 20 == 0):
        print()
    if(i//10 == 7 or i % 10 == 7 or i % 7 == 0):
        print("ha",end=" ")
        continue
    else:
        print(f"{i:02}",end=" ")

1-13else

wile循环else结构

else在过7游戏中已经有使用了。

循环可以和else配合使用,else下方缩进的代码指的是当循环正常结束之后要执行的代码。

for…else…

while…else…

1-14字符串定义、切片

1、字符串的定义

字符串是 Python 中最常用的数据类型。我们一般使用引号来创建字符串。创建字符串很简单,只要为变量分配一个值即可。

a = 'hello world'
b = "abcdefg"

print(type(a))
print(type(b))
注意:控制台显示结果为`<class 'str'>`, 即数据类型为str(字符串)。
  • 一对引号字符串
str= 'Tom'
name2 = "Rose"
  • 三引号字符串
name3 = ''' Tom '''
name4 = """ Rose """
a = '''I am Tom, 
        nice to meet you! '''
b = """ I am Rose, 
        nice to meet you! """
注意:三引号形式的字符串支持换行。
如果字符串外层被双引号包裹,字符串内部可以使用单引号。
s = """他说:"hello,i'am lihua"."""
print(s)
# 他说:"hello,i'am lihua".

2、字符串的输入

在Python中,使用input()接收用户输入。

username = input('请输入您的名字:')
print(f'您输入的名字是{username}')
print(type(username))

password = input('请输入您的密码:')
print(f'您输入的密码是{password}')
print(type(password))

3、字符串的输出

在Python中,我们可以使用print()函数进行输出。

print('hello world')
name = 'heima'
print('我的名字是%s' % name)
print(f'我的名字是{name}')

4、字符串的底层存储结构

在计算机底层,Python中的字符串是一段连续的内存地址。

str1 = 'itheima'

底层存储结构:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9apWrdmG-1670931802460)(img/image-20221111192508494.png)]

注意:索引下标从0开始。

5、聊聊索引下标

索引下标,就是编号。比如火车座位号,座位号的作用:按照编号快速找到对应的座位。同理,下标的作用即是通过下标快速找到对应的数据。

案例:字符串name = "abcdef",取到不同下标对应的数据。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iqV2KfjW-1670931802460)(img/image-20221111192629009.png)]

name = "abcdef"
print(name[1])  # 'b'
print(name[0])  # 'a'
print(name[2])  # 'c'
print(name[-1])  # 'f'
print(name[-3])  # 'd'

4、字符串切片

1、基本语法

什么是切片?
切片是指对操作的对象截取其中一部分的操作。字符串、列表、元组都支持切片操作

字符串切片以及其他容器类型的切片操作,都会重新生成一个新的数据序列,不会对原有数据序列产生影响。

序列[开始位置下标:结束位置下标:步长]

① 不包含结束位置下标对应的数据, 正负整数均可;
② 步长是选取间隔,正负整数均可,默认步长为1。

name1 = "abcdef"
st = name1[1:4:1]
print(st)
# bcd

2、切片的使用

记口诀:切片其实很简单,只顾头来尾不管,步长为正正向移,步长为负则逆向移

注意:
切片中的操作用`:`分隔。
起始位置可以省略:
步长为正数,起始位置默认为0
步长为负数,起始位置默认为-1。起始位置为负数时,数据倒序输出(按照下标的执行顺序输出)。

结束位置也可以省略。
str2 = str1[::-1] str1 和 str2互为倒序
str2 = str1[2:5] 步长为1可以省略

1-15字符串查找、替换、合并

1、字符串查找

所谓字符串查找方法即是查找子串在字符串中的位置或出现的次数。

find():检测某个子串是否包含在这个字符串中,如果在返回这个子串开始的位置下标,否则则返回-1。

字符串序列.find(子串, 开始位置下标, 结束位置下标)

注意:开始和结束位置下标可以省略,表示在整个字符串序列中查找。

案例演示:

mystr = "hello world and hello python"
print(mystr.find('hello'))
print(mystr.find('hello', 10))
print(mystr.find('heima'))
"""
0
16
-1
"""

index():检测某个子串是否包含在这个字符串中,如果在返回这个子串开始的位置下标,否则则报异常。

基本语法:

字符串序列.index(子串, 开始位置下标, 结束位置下标)

注意:开始和结束位置下标可以省略,表示在整个字符串序列中查找。

案例演示:

mystr = "hello world and hello python"
print(mystr.index('hello'))
print(mystr.index('hello', 10, 27))
print(mystr.index('heima'))

rfind(): 和find()功能相同,但查找方向为右侧开始。

rindex():和index()功能相同,但查找方向为右侧开始。

字符串序列.rfind(子串, 开始位置下标, 结束位置下标)
字符串序列.rindex(子串, 开始位置下标, 结束位置下标)

注意:开始和结束位置下标可以省略,表示在整个字符串序列中查找。

案例演示:

mystr = "python.png"
print(mystr.rfind('.png'))
print(mystr.rindex('.png'))

count():返回某个子串在字符串中出现的次数

基本语法:

字符串序列.count(子串, 开始位置下标, 结束位置下标)

注意:开始和结束位置下标可以省略,表示在整个字符串序列中查找。

案例演示:

mystr = "hello world and hello python and hello itheima"

print(mystr.count('and'))  # 2
print(mystr.count('ands'))  # 0
print(mystr.count('and', 0, 20))  # 1

编号

函数

作用

1

find()

检测某个子串是否包含在这个字符串中,如果在返回这个子串开始的位置下标,否则则返回-1。

2

index()

检测某个子串是否包含在这个字符串中,如果在返回这个子串开始的位置下标,否则则报异常。

3

rfind()

和find()功能相同,但查找方向为右侧开始。

4

rindex()

和index()功能相同,但查找方向为右侧开始。

5

count()

返回某个子串在字符串中出现的次数

2、字符串修改

所谓修改字符串,指的就是通过函数的形式修改字符串中的数据。

replace():返回替换后的字符串

基本语法

字符串序列.replace(旧子串, 新子串, 替换次数)

注意:替换次数如果查出子串出现次数,则替换次数为该子串出现次数。

案例演示:

mystr = "hello world and hello python"

# 结果:hello world & hello python
print(mystr.replace('and', '&'))

# 结果:hi world and hi python
print(mystr.replace('hello', 'hi', 2))

# 结果:hello world and hello python
print(mystr)

注意:数据按照是否能直接修改分为可变类型和不可变类型两种。由于字符串属于不可变类型,所以修改的时候不能改变原有字符串。

split():按照指定字符分割字符串。

基本语法:

字符串序列.split(分割字符, num)

注意:num表示的是分割字符出现的次数,即将来返回数据个数为num+1个。

案例演示:

mystr = 'apple,orange,banana'
# 结果:['apple', 'orange', 'banana']
print(mystr.split(','))
# 结果:['apple', 'orange,banana']
print(mystr.split(',', 1))
# 结果:['apple,orange,banana']
print(mystr.split('*'))

join():用一个字符或子串合并字符串,即是将多个字符串合并为一个新的字符串。
基本语法:

list1 = ['it', 'heima']
tuple1 = ('hello', 'python')
# 结果:itheima
print(''.join(list1))
# 结果:hello-python
print('-'.join(tuple1))

capitalize():将字符串第一个字符转换成大写
基本语法:

mystr = 'student'
mystr2 = 'stuDENT'
# 结果:Student
print(mystr.capitalize())
# 结果:Student
print(mystr2.capitalize())
注意:capitalize()函数转换后,只字符串第一个字符大写,其他的字符全都小写

title():将字符串每个单词首字母转换成大写
基本语法:

mystr = 'i love python'
# 结果:I Love Python
print(mystr.title())

upper():将字符串中小写转大写
lower():将字符串中大写转小写

基本语法:

mystr = 'i love python'
print(mystr.upper())
print('-' * 10)
mystr = 'I LOVE PYTHON'
print(mystr.lower())

1-16字符串删除、判断

1、字符串删除

lstrip():删除字符串左侧空白字符
rstrip():删除字符串右侧空白字符
strip():删除字符串两侧空白字符

strip("$"):删除字符串两侧所有的美元符号
strip("1234"):删除字符串两侧所有的1或2或3或4

username = '   admin'
password = 'admin888  '
print(len(username))
# lstrip去除左侧空格print(username.lstrip())
print(len(username.lstrip()))
print(len(password))
# rstrip去除左侧空格print(password.rstrip())
print(len(password.rstrip()))
print(username.strip())
print(password.strip())
注:len()方法主要用于获取字符串的长度

ljust():返回一个原字符串左对齐,并使用指定字符(默认空格)填充至对应长度 的新字符串。
rjust():返回一个原字符串右对齐,并使用指定字符(默认空格)填充至对应长度 的新字符串,语法和ljust()相同。
center():返回一个原字符串居中对齐,并使用指定字符(默认空格)填充至对应长度的新字符串,语法和ljust()相同。
基本语法:

字符串序列.ljust(长度, 填充字符)

案例演示:

mystr = "python"
print(mystr.ljust(10, '.'))
print('-' * 10)
print(mystr.rjust(10, '.'))
print('-' * 10)
print(mystr.center(10, '.'))
"""
python....
----------
....python
----------
..python..
"""

编号

函数

作用

1

replace()

返回替换后的字符串

2

split()

返回切割后的列表序列

3

capitalize()

首字母大写

4

title()

所有单词首字母大写

5

upper()与lower()

返回全部大写或小写的字符串

6

lstrip()、rstrip()与strip()

去除左边、右边以及两边的空白字符

7

ljust()、rjust()与center()

返回原字符串左对齐、右对齐以及居中对齐

# 计算1~1000中7出现的次数
# m = 0
# for i in range(1,10000,1):
#    m += str(i).count("7")
# print(m)
print(str(list(range(1, 10000))).count("7"))

2、字符串判断

所谓判断即是判断真假,返回的结果是布尔型数据类型:True 或 False。

startswith():检查字符串是否是以指定子串开头,是则返回 True,否则返回 False。如果设置开始和结束位置下标,则在指定范围内检查。

endswith():检查字符串是否是以指定子串结尾,是则返回 True,否则返回 False。如果设置开始和结束位置下标,则在指定范围内检查。

基本语法:

mystr1 = 'python program'
print(mystr1.startswith('python'))
print('-' * 10)
mystr2 = 'avater.png'
print(mystr2.endswith('.png'))

isalpha():测字符串是否只由字母组成,如果字符串(至少有一个字符)所有字符都是字母则返回 True, 否则返回 False。

mystr1 = 'hello'
mystr2 = 'hello12345'
# 结果:True
print(mystr1.isalpha())
# 结果:False
print(mystr2.isalpha())

isdigit():如果字符串只包含数字则返回 True 否则返回 False。
基本语法:

mystr1 = 'aaa12345'
mystr2 = '12345'
# 结果: False
print(mystr1.isdigit())
# 结果:False
print(mystr2.isdigit())

isalnum():检测字符串是否由字母和数字组成,如果字符串(至少有一个字符)所有字符都是字母或数字则返 回 True,否则返回 False。

mystr1 = 'aaa12345'
mystr2 = '12345-'
# 结果:True
print(mystr1.isalnum())
# 结果:False
print(mystr2.isalnum())

isspace():如果字符串中只包含空白,则返回 True,否则返回 False。
基本语法:

mystr1 = '1 2 3 4 5'
mystr2 = '     '
# 结果:False
print(mystr1.isspace())
# 结果:True
print(mystr2.isspace())

编号

函数

作用

1

startswith()

检查字符串是否是以指定子串开头,是则返回 True,否则返回 False。如果设置开始和结束位置下标,则在指定范围内检查。

2

endswith()

检查字符串是否是以指定子串结尾,是则返回 True,否则返回 False。如果设置开始和结束位置下标,则在指定范围内检查。

3

isalpha()

如果字符串所有字符(至少有一个字符)都是字母则返回 True, 否则返回 False。

4

isdigit()

如果字符串只包含数字则返回 True 否则返回 False。

5

isalnum()

Python isalnum() 方法检测字符串是否由字母和数字组成。如果字符串所有字符(至少有一个字符)都是字母或数字则返 回 True,否则返回 False。

6

isspace()

如果字符串中只包含空白,则返回 True,否则返回 False

1-17列表定义

1、为什么需要列表

一次操作中需要定义同类型的多个变量。一个一个定义变量太麻烦。

例如:

统计全班50位同学的姓名,普通操作则需要手动分别定义50个变量。要是将人数上升到全校、全市。。。

2、列表的定义

基本语法:

列表名称 = [数据1, 数据2, 数据3, 数据4, ...]

案例演示:

name_list = ['Tom', 'Lily', 'Rose’]
print(name_list)   # ['Tom', 'Lily', 'Rose']
print(type(name_list))   # <class 'list'>
注意:列表可以一次存储多个数据且可以为不同的数据类型
但是在开发中,一般列表中都存储同种类型的数据。

1-18列表的操作运用

1、列表的常用操作

列表的作用是一次性存储多个数据,程序员可以对这些数据进行的操作有:增、删、改、查。

查询

索引下标

name_list = ['Tom', 'Lily', 'Rose']

print(name_list[0])  # Tom
print(name_list[1])  # Lily
print(name_list[2])  # Rose

列表的底层存储形式和字符串都是一样的,其也是通过索引下标来对其进行引用的。

index()方法:指定数据所在位置的下标

列表序列.index(数据, 开始位置下标, 结束位置下标)

案例演示:

name_list = ['Tom', 'Lily', 'Rose']
print(name_list.index('Lily', 0, 2))  # 1

count()方法:统计指定数据在当前列表中出现的次数

列表序列.count(数据)

案例演示:

name_list = ['Tom', 'Lily', 'Rose']
print(name_list.count('Lily'))  # 1

in:判断指定数据在某个列表序列,如果在返回True,否则返回False

name_list = ['Tom', 'Lily', 'Rose']

# 结果:True
print('Lily' in name_list)

# 结果:False
print('Lilys' in name_list)

not in:判断指定数据不在某个列表序列,如果不在返回True,否则返回False

name_list = ['Tom', 'Lily', 'Rose']

# 结果:False
print('Lily' not in name_list)

# 结果:True
print('Lilys' not in name_list)

编号

函数

作用

1

index()

从左至右,返回第一次找到的指定数据所在位置的下标,如果不存在则报错。

2

count()

统计指定数据在当前列表中出现的次数

3

in

判断指定数据在某个列表序列,如果在返回True,否则返回False

4

not in

判断指定数据不在某个列表序列,如果不在返回True,否则返回False

增加

append()方法:增加指定数据到列表末尾

name_list = ['Tom', 'Lily', 'Rose']
name_list.append('Jennifer')
print(name_list)
# ['Tom', 'Lily', 'Rose', 'Jennifer']

如果直接打印调用append方法的函数,不会返回任何内容。

注意:列表追加数据的时候,直接在原列表里面追加了指定数据,即修改了原列表,故列表为可变类型数据。

extend()方法:列表结尾追加数据序列,如果数据是一个序列,则将这个序列的数据逐一添加到列表

追加字符串序列时,会将字母依次拆分并放入列表中。
字符串类型哪怕只有一个值,或者只有一个空字符串,都是可迭代类型,同理可知,列表,元组等,哪怕只有一个数据或者空类型也是可迭代类型。

列表序列.extend(数据)

括号内的数据必须是可迭代对象(可以用for循环)。字符串类型哪怕是一个空字符串也是可迭代类型。列表、元组同理。

单个数据演示:

name_list = ['Tom', 'Lily', 'Rose']
name_list.extend('Smith')

# 结果:['Tom', 'Lily', 'Rose', 'S', 'm', 'i', 't', 'h']
print(name_list)

序列数据演示:

name_list = ['Tom', 'Lily', 'Rose']
name_list.extend(['Smith', 'Jennifer'])

# 结果:['Tom', 'Lily', 'Rose', 'Smith', 'Jennifer']
print(name_list)

insert()方法:指定位置新增数据//开发中不经常用

列表序列.insert(位置下标, 数据)

案例演示:

name_list = ['Tom', 'Lily', 'Rose']
name_list.insert(1, 'Smith')

# 结果:['Tom', 'Smith', 'Lily', 'Rose']
print(name_list)

编号

函数

作用

1

append()

将append中的数据作为一个整体追加到该列表的末尾

2

extend()

列表结尾追加数据,如果数据是一个序列,则将这个序列的数据逐一添加到列表,如果是字典,则只将键传入。

3

insert()

指定位置新增数据(开发中少用)

删除

del:不仅可以删除元素,也可以删除任何变量。非常强大但是有些不安全。

del 目标

删除列表,案例演示:

name_list = ['Tom', 'Lily', 'Rose']
del name_list[0]
print(name_list)

pop()方法:删除指定下标的数据(括号内不传值,则默认为最后一个),并返回该数据。

pop传入的元素下标不存在,则报错。

列表序列.pop(下标)

案例演示:

name_list = ['Tom', 'Lily', 'Rose']
del_name = name_list.pop(1)
# 结果:Lily
print(del_name)
# 结果:['Tom', 'Rose']
print(name_list)

remove()方法:移除列表中某个数据的第一个匹配项,不能删除列表中的全部匹配项。

列表序列.remove(数据)

案例演示:

name_list = ['Tom', 'Lily', 'Rose']
name_list.remove('Rose')
# 结果:['Tom', 'Lily']
print(name_list)

clear()方法:清空列表, 删除列表中的所有元素,返回空列表。

列表序列.clear()

案例演示

name_list = ['Tom', 'Lily', 'Rose']
name_list.clear()
print(name_list) # 结果: []

编号

函数

作用

1

del 列表[索引]

先用下标在列表中查找元素,找到后删之

2

pop()

删除指定下标的数据(默认为最后一个),并返回该数据

3

remove()

移除列表中某个数据的从左到右的第一个匹配项。

4

clear()

清空列表,删除列表中的所有元素,返回空列表。

修改

修改指定的元素值

列表[索引] = 修改后的值

案例演示:

name_list = ['Tom', 'Lily', 'Rose']
name_list[0] = 'Smith'
# 结果:['Smith', 'Lily', 'Rose']
print(name_list)

reverse():将数据序列进行倒叙排列

列表序列.reverse()

案例演示:

num_list = [1, 5, 2, 3, 6, 8]
num_list.reverse()
# 结果:[8, 6, 3, 2, 5, 1]
print(num_list)

sort()方法:对列原表序列进行排序,没有产生新列表。默认为升序。

列表序列.sort( key=None, reverse=False)

注意:reverse表示排序规则,reverse = True降序, reverse = False升序(默认)

案例演示:

num_list = [1, 5, 2, 3, 6, 8]
num_list.sort()
# 结果:[1, 2, 3, 5, 6, 8]
print(num_list)

copy()方法:对列表序列进行拷贝

列表序列.copy()

案例演示:

name_list = ['Tom', 'Lily', 'Rose']

name_li2 = name_list.copy()

# 结果:['Tom', 'Lily', 'Rose']
print(name_li2)

编号

函数

作用

1

列表[索引] = 修改后的值

修改列表中的某个元素

2

reverse()

将数据序列进行倒叙排列

3

sort()

对列表序列进行排序

4

copy()

对列表序列进行拷贝

2、列表的循环遍历

1、while循环遍历

name_list = ['Tom', 'Lily', 'Rose']
i = 0
while i < len(name_list):
    print(name_list[i])
    i += 1

2、for循环遍历

name_list = ['Tom', 'Lily', 'Rose']
for i in name_list:
    print(i)

3、列表的嵌套

所谓列表嵌套指的就是一个列表里面包含了其他的子列表。

应用场景:要存储班级一、二、三三个班级学生姓名,且每个班级的学生姓名在一个列表。
name_list = [[‘小明’, ‘小红’, ‘小绿’], [‘Tom’, ‘Lily’, ‘Rose’], [‘张三’, ‘李四’, ‘王五’]]

思考: 如何查找到数据"李四"?

# 第一步:按下标查找到李四所在的列表
print(name_list[2])

# 第二步:从李四所在的列表里面,再按下标找到数据李四
print(name_list[2][1])

1-19元组定义使用

1、为什么需要元组

如果想要存储多个数据,但是这些数据是不能修改的数据,怎么做?

答:列表?列表可以一次性存储多个数据,但是列表中的数据允许更改。

num_list = [10, 20, 30]
num_list[0] = 100

那这种情况下,我们想要存储多个数据且数据不允许更改,应该怎么办呢?
答:使用元组,元组可以存储多个数据且元组内的数据是不能修改的。

2、定义元组

元组特点:定义元组使用小括号,且使用逗号隔开各个数据,数据可以是不同的数据类型。

# 多个数据元组
t1 = (10, 20, 30)

# 单个数据元组
t2 = (10,)

i1 = (1)
i2 = ('1')
i3 = (1,)

print(type(i1))# int
print(type(i2))# str
print(type(i3))# tuple
# 因为小括号还有提升算数优先级的作用。若不加逗号,程序会小括号理解为提升算数优先级,此时((1))与(1)完全相等,所以为int类型。

注意:如果定义的元组只有一个数据,那么这个数据后面也要添加逗号,否则数据类型为唯一的这个数据的数据类型。

元组的括号可以被省略

t2 = 10,
print(type(t2))  # tuple

t3 = (20)
print(type(t3))  # int

t4 = ('hello')
print(type(t4))  # str

3、元组的相关操作

编号

函数

作用

1

元组[索引]

根据索引下标查找元素

2

index()

查找某个数据,如果数据存在返回第一个对应的下标,否则报错,语法和列表、字符串的index方法相同

3

count()

统计某个数据在当前元组出现的次数

4

len()

统计元组中数据的个数。len()其实就是调用了_ _ len _ _()方法

元组内的数据不能直接修改,也不能直接删除。

元组内的数据如果直接修改则立即报错,但是如果元组里面有列表,修改列表里面的数据则是支持的,故这个特点非常重要。

tuple2 = (10, 20, ['aa', 'bb', 'cc'], 50, 30)
print(tuple2[2])  # 访问到列表

# 结果:(10, 20, ['aaaaa', 'bb', 'cc'], 50, 30)
tuple2[2][0] = 'aaaaa'
print(tuple2)

4、元组的相关操作演示

由于元组的数据不能修改,所以元组中的数据不能进行增删改操作。

tuple1 = ('aa', 'bb', 'cc', 'bb')
print(tuple1[0])  # aa
tuple2 = ('aa', 'bb', 'cc', 'bb')
print(tuple2.index('aa'))  # 0
tuple3 = ('aa', 'bb', 'cc', 'bb')
print(tuple3.count('bb'))  # 2
tuple4 = ('aa', 'bb', 'cc', 'bb')
print(len(tuple4))  # 4

1-20字典定义使用

1、为什么需要字典

字典中的键是不能被重复的。
字典:存储多个数据,以健值对的形式存储,方便快速存取。
字典的键要见名知意

思考1: 如果有多个数据,例如:‘Tom’, ‘男’, 20,如何快速存储?
答:列表

list1 = ['Tom', '男', 20]

思考2:如何查找到数据’Tom’?
答:查找到下标为0的数据即可。

list1[0]

思考3:如果将来数据顺序发生变化,如下所示,还能用list1[0]访问到数据’Tom’吗?

list1 = ['男', 20, 'Tom']

答:不能,数据’Tom’此时下标为2。
思考4:数据顺序发生变化,每个数据的下标也会随之变化,如何保证数据顺序变化前后能使用同一的标准查找数据呢?
答:字典,字典里面的数据是以键值对形式出现,字典数据和数据顺序没有关系,即字典不支持下标,后期无论数据如何变化,只需要按照对应的键的名字查找数据即可。

2、字典的定义

字典特点:
符号为大括号(花括号)
数据为键值对形式出现
各个键值对之间用逗号隔开
基本语法:

# 有数据字典
dict1 = {'name': 'Tom', 'age': 20, 'gender': 'male'}

# 空字典
dict2 = {}

dict3 = dict()
注意:一般称冒号前面的为键(key),简称k;冒号后面的为值(value),简称v;key:value就是我们通常说的键值对。

3、字典的"增"操作

基本语法:

字典序列[key] = value

注:如果key存在则修改这个key对应的值;如果key不存在则新增此键值对。

dict1 = {'name': 'Tom', 'age': 20, 'gender': 'male'}

dict1['name'] = 'Rose'
# 结果:{'name': 'Rose', 'age': 20, 'gender': 'male'}
print(dict1)

dict1['id'] = 110

# {'name': 'Rose', 'age': 20, 'gender': 'male', 'id': 110}
print(dict1)
注意:字典为可变类型
# update
# 一般用于两个字典间的拼接
dict1.update({"学号":'194010'})

4、字典的"删"操作

del() / del:删除字典或删除字典中指定键值对

dict1 = {'name': 'Tom', 'age': 20, 'gender': 'male'}
del dict1['gender']
# 结果:{'name': 'Tom', 'age': 20}
print(dict1)

clear():清空字典

dict1 = {'name': 'Tom', 'age': 20, 'gender': 'male'}
dict1.clear()
print(dict1)  # {}

\1. clear()方法(删除字典内所有元素)

dict = {'name': '我的博客地址', 'alexa': 10000, 'url': 'http://blog'}
dict.clear();  # 清空词典所有条目

\2. pop()方法(删除字典给定键 key 所对应的值,返回值为被删除的值)

site= {'name': '我的博客地址', 'alexa': 10000, 'url':'http://blog'}
pop_obj=site.pop('name') # 删除指定的键值对,如{'name':'我的博客地址'}这个键值对
print pop_obj   # 输出 :我的博客地址

\3. popitem()方法(从字典中删除最后一个项目)

site= {'name': '我的博客地址', 'alexa': 10000, 'url':'http://blog'}
site.popitem() # 删除最后一个键值对
print site   # 输出结果是{'name': '我的博客地址', 'alexa': 10000}

\4. del 全局方法(能删单一的元素也能清空字典,清空只需一项操作)

site= {'name': '我的博客地址', 'alexa': 10000, 'url':'http://blog'}
del site['name'] # 删除键是'name'的条目 
del site  # 删除该字典

5、字典的"改"操作

基本语法:

字典序列[key] = value
注意:如果key存在则修改这个key对应的值 ;如果key不存在则新增此键值对。

update(键=值)
update({键:值})

dict1.update( name ='小红')
dict1.update({'age':18})

6、字典的"查"操作

key值查找

dict1 = {'name': 'Tom', 'age': 20, 'gender': 'male'}
print(dict1['id'])   # 不存在则报错
print(dict1['name'])  # Tom
说明:如果当前查找的key存在,则返回对应的值;否则则报错。

编号

函数

作用

1

get(key, 默认值)

根据字典的key获取对应的value值,如果当前查找的key不存在则返回第二个参数(默认值),如果省略第二个参数,则返回None

2

keys()

获取所有的键,返回列表

3

values()

获取所有的值,返回列表

4

items()

获取所有键值对,返回元祖组成的列表

get方法演示

说明:如果当前查找的key不存在则返回第二个参数(默认值),如果省略第二个参数,则返回None。

dict1 = {'name': 'Tom', 'age': 20, 'gender': 'male'}

print(dict1.get('name'))    # Tom
print(dict1.get('id', 110))  # 110
print(dict1.get('id'))  	# None

keys()values()items()案例演示

dict1 = {'name': 'Tom', 'age': 20, 'gender': 'male'}
print(dict1.keys())  
# 结果:dict_keys(['name', 'age', 'gender'])
dict1 = {'name': 'Tom', 'age': 20, 'gender': 'male'}
print(dict1.values())  
# 结果:dict_keys(['Tom', 20, 'male'])
dict1 = {'name': 'Tom', 'age': 20, 'gender': 'male'}
print(dict1.items())  
# 结果:dict_items([('name', 'Tom'), ('age', 20), ('gender', 'male')])

7、字典的循环遍历

遍历字典的key

dict1 = {'name': 'Tom', 'age': 20, 'gender': 'male'}
for key in dict1.keys():
    print(key)

遍历字典的value

dict1 = {'name': 'Tom', 'age': 20, 'gender': 'male'}
for value in dict1.values():
    print(value)

遍历字典的元素

dict1 = {'name': 'Tom', 'age': 20, 'gender': 'male'}
for item in dict1.items():
    print(item)

遍历字典的键值对

dict1 = {'name': 'Tom', 'age': 20, 'gender': 'male'}
for key, value in dict1.items():
    print(f'{key} = {value}')

1-21集合定义使用

1、什么是集合

集合(set)是一个无序的不重复元素序列。
也就是说,集合可以像元组一样,设置不可改变的类型。也可以默认像字典,列表一样,可以迭代改变。同时集合里的元素可以是列表,元组,字典。

2、集合的定义

基本语法:
创建集合使用{}set(), 但是如果要创建空集合只能使用set(),因为{}用来创建空字典。

集合的特点:无序、不重复
了解:在集合中会使用数据的值来计算哈希值,根据哈希值顺序进行排序。

s1 = {10, 20, 30, 40, 50}
print(s1)

s2 = {10, 30, 20, 10, 30, 40, 30, 50}
print(s2)

s3 = set('abcdefg')
print(s3)

s4 = set()
print(type(s4))  # set()

s5 = {}
print(type(s5))  # dict

# boolean在计算时,True == 1,False == 0。
dit1 = {0,1,2,3,True,False,'计算机'}
print(dit1)
# {False, 1, 2, 3, '计算机'}

# 列表数据无法用集合储存
dit1 = {1,2,3,True,False,'计算机',[1,23,2,3,]}
print(dit1)
# TypeError: unhashable type: 'list'

# 元组类型可以放在集合内储存
dit1 = {1,2,3,True,False,'计算机',(1,23,2,3)}
print(dit1)
# {False, 1, 2, 3, (1, 23, 2, 3), '计算机'}

# 字典类型无法用集合储存。
dit1 = {1,2,3,True,False,'计算机',{'name':'zhangsan','age':8}}
print(dit1)
# TypeError: unhashable type: 'dict'

# 集合类型无法用集合储存。
dit1 = {1,2,3,True,False,'计算机', {1,223,2}}
print(dit1)
# TypeError: unhashable type: 'set'
结论:
列表、字典、集合不能放入集合中作为元素出现。
列表、字典、集合,也不能作为字典的键

3、集合的基本操作

增加

① add()方法 :增加单一元素

s1 = {10, 20}
s1.add(100)
s1.add(10)
print(s1)   # 结果: {100, 10, 20}

因为集合有去重功能,所以,当向集合内追加的数据是当前集合已有数据的话,则不进行任何操作。

② update()方法 :增加序列数据
update内部只能填写容器类型(数据序列)

s1 = {10, 20}
# 结果:s1.update(100)  # 报错
s1.update([100, 200])
s1.update('abc')
print(s1)
# {'c', 100, 200, 10, 20, 'a', 'b'}

注:字符串也是一个数据序列

删除

① remove()方法:删除集合中的指定数据,如果数据不存在,报错。
② discard()方法:删除集合中的指定数据,如果数据不存在,不会报错,默认返回None。

s1 = {10, 20}
s1.remove(10)
print(s1)
s1.remove(10)  # 报错
s1.discard(10)  # 不报错
print(s1)

③ pop()方法:随机删除集合中的某个数据,并返回这个数据。

s1 = {10, 20, 30, 40, 50}
del_num = s1.pop()
print(del_num)
print(s1)
# 50
# {20, 40, 10, 30}

查询

① in:判断数据在集合序列
② not in:判断数据不在集合序列

s1 = {10, 20, 30, 40, 50}
print(10 in s1)
print(10 not in s1)

遍历

for i in (s1)
print(s1)

题目

题目1
# 给定一个列表,首先删除以s开头的元素,删除后,修改第一个元素为'joke',并把最后一个元素复制一份,放在'joke'的后面。
# my_list = ["spring", "look", "strange", "curious", "black", "hope"]
# 方法一 (自改法)
my_list = ["spring", "look", "strange", "curious", "black", "hope"]
my_len = len(my_list)
i = 0
while i < my_len:
    if my_list[i].startswith('s'):
        del my_list[i]
        my_len -= 1
    i += 1
print(my_list)
my_list[0] = 'joke'
my_list.insert(1,my_list[len(my_list)-1])
print(my_list)

# ['look', 'curious', 'black', 'hope']
# ['joke', 'hope', 'curious', 'black', 'hope']
# 方法二 (赋值法)
my_list = ["spring", "look", "strange", "curious", "black", "hope"]
new_list = []
for i in my_list:
    if not i.startswith('s'):
        new_list.append(i)
my_list = new_list
print(my_list)
# ['look', 'curious', 'black', 'hope']
# 方法三 (筛选目标法)
my_list = ["spring", "look", "strange", "curious", "black", "hope"]
des_list = []
for i in my_list :
    if i.startswith('s'):
        des_list.append(i)
print(des_list)
for i in my_list:
    if i in des_list:
        my_list.remove(i)
print(my_list)

# ['spring', 'strange']
# ['look', 'curious', 'black', 'hope']
题目2

(9条消息) Python如何对列表进行排序_@阿证1024的博客-_对列表进行排序

将下面两个列表合并,将合并后的列表去重,之后降序并输出
list1 = [11,45,34,51,90,22]
list2 = [4,16,23,0,22]
# 方法一
list1 = [11,45,34,51,90,22]
list2 = [4,16,23,0,22]
list1.extend(list2)
print(list1)
list1 = set(list1)
print(list1)
list1 = list(list1)
list1.sort(reverse=True)
print(list1)
# [11, 45, 34, 51, 90, 22, 4, 16, 23, 0, 22]
# {0, 34, 4, 11, 45, 16, 51, 22, 23, 90}
# [90, 51, 45, 34, 23, 22, 16, 11, 4, 0]
# 方法二
list1 = [11,45,34,51,90,22]
list2 = [4,16,23,0,22]
list3 = list1 + list2
list4 = set(list3)
list5 = list(list4)
list5.sort(reverse = True)
print(list5)
题目3
现有:tuple1=("tom","kaisa","alisi","xiaoming","songshu")
想获得"alisi"这个内容,用三种方法。
tuple1=("tom","kaisa","alisi","xiaoming","songshu")
print(tuple1[2])
print(tuple1[2:3][0])
for i in tuple1 :
    if i == 'alisi':
        print(i)
题目4
# 有如下元组:
# typle1 = ( "tom" , " kaisa" , "alisi" , "xiaoming" , " songshu")
# 求出他的长度
typle1 = ( "tom" , " kaisa" , "alisi" , "xiaoming" , " songshu")
print(len(typle1))
# 5
题目5
# 现有字典dict1 = { 'name ' : ' python'},将键为name的值更改为xiaozhi
dict1 = {'name': 'python'}
# dict1['name'] = 'xiaozhi'
# print(dict1)

# dict1.update(name='xiaozhi')
# print(dict1)

dict1.update({'name':'xiaozhi'})
print(dict1)
题目6
# 现有字典dict1 = { 'name' : 'chuanzhi ' , 'age' : 18}要求:
# 1.删除age: 18这个键值对
# ⒉将整个字典里面的所有键值对,清空
dict1 = { 'name' : 'xiaozhi ' , 'age' : 18}
# del dict1['age']
# print(dict1)
dict1.clear()
print(dict1)
题目7
# 现有字典dict1={'name':'cuanzhi','age':18}要求:
# 1.使用循环将字典中所有的键输出到屏幕上
# ⒉.使用循环将字典中所有的值输出到屏幕上
# 3.使用循环将字典中所有的键值对输出到屏幕上输出方式:
# name: chuanzhiage:18
dict1={'name':'cuanzhi','age':18}
# print(dict1.keys())
# print(dict1.values())
# print(dict1.items())
for key in dict1.keys():
    print(key)
print()
for value in dict1.values():
    print(value)
print()
for key2,value2 in dict1.items():
    print(key2,":",value2)
题目8
# 有这样的一个列表
# product = [
#     { "name" :"电脑","price" : 7000},
#     { "name" :"鼠标","price" : 30},
#     { "name" :"usb电动小风扇","price" : 20},
#     { "name" :"遮阳伞","price" : 50}
# ]
# 小明一共有8000块钱,那么他能不能买下这所有商品?如果能,请输出“能”,否则输出“不能”
# 方法1
money = 8000
product = [
    { "name" :"电脑","price" : 7000},
    { "name" :"鼠标","price" : 30},
    { "name" :"usb电动小风扇","price" : 20},
    { "name" :"遮阳伞","price" : 50}
]
sum = 0
for dict1 in product:
    sum += dict1["price"]
if sum <= money:
    print('能')
else:
    print('不能')
    
# 能
money = 8000
product = [
    { "name" :"电脑","price" : 7000},
    { "name" :"鼠标","price" : 30},
    { "name" :"usb电动小风扇","price" : 20},
    { "name" :"遮阳伞","price" : 50}
]
sum = 0
for dict1 in product:
    for i in dict1.items():
        if i[0] == 'price':
            sum += i[1]
        # sum += int(i)
    # sum += dict1["price"]
if sum <= money:
    print('能')
else:
    print('不能')
    
# 能

1-22公共方法与推导式

1、方法介绍

运算符

描述

支持的容器类型

+

合并

字符串、列表、元组

*

复制

字符串、列表、元组

in

元素是否存在

字符串、列表、元组、字典

not in

元素是否不存在

字符串、列表、元组、字典

2、+ 合并操作

# 1. 字符串 
str1 = 'aa'
str2 = 'bb'
str3 = str1 + str2
print(str3)  # aabb

# 2. 列表 
list1 = [1, 2]
list2 = [10, 20]
list3 = list1 + list2
print(list3)  # [1, 2, 10, 20]

# 3. 元组 
t1 = (1, 2)
t2 = (10, 20)
t3 = t1 + t2
print(t3)  # (10, 20, 100, 200)

3、* 复制操作

# 1. 字符串
print('-' * 10)

# 2. 列表
list1 = ['hello']
print(list1 * 4)

# 3. 元组
t1 = ('world',)
print(t1 * 4)

4、in与not in

# 1. 字符串
print('a' in 'abcd')  # True
print('a' not in 'abcd')  # False
print('-' * 10)
# 2. 列表
list1 = ['a', 'b', 'c', 'd']
print('a' in list1)  # True
print('a' not in list1)  # False
print('-' * 10)
# 3. 元组
t1 = ('a', 'b', 'c', 'd')
print('aa' in t1)  # False
print('aa' not in t1)  # True
print('-' * 10)
# 4. 字典
dict1 = {'name': 'heima', 'age':18}
print('name' in dict1)  # True
print('age' not in dict1)  # False

5、切片

# str切片
str1 = 'abcde'
print(str1[2:])
print(str1)

# cde
# abcde

#list可以切片么?
list1 = [1,2,3,4]
# list切片方式方法和str完全相同
# list切片后不会在原有数据上进行修改,而是产生了一个新的列表
print(list1[1:3:1])#[2,3]
print(list1)

# [2, 3]
# [1, 2, 3, 4]

#tuple可以切片么?
tuple1 = (1,2,3,4)
# tuple1切片方式方法和str完全相同
#切片后不会在原有数据上进行修改,而是产生了一个新的列表
print(tuple1[1:3:1])#(2,3)
print(tuple1)

# (2, 3)
# (1, 2, 3, 4)

# dict、set可以切片吗?
#	不行,因为不能使用索引获取数据
#结论:
1.list str tuple 可以使用切片,格式是:[起始位置:终止位置:步长],三者使用方式完全一致
2.所有的切片都不会在原有的数据上进行修改,而是产生一个新的数据序列
3.集合和字典无法切片,因为不能使用索引获取数据元素

数据序列的公共方法

1、公共方法

编号

函数

描述

1

len()

计算容器中元素个数

2

del 或 del()

删除

3

max()

返回容器中元素最大值

4

min()

返回容器中元素最小值

5

range(start, end, step)

生成从start到end的数字,步长为 step,供for循环使用

6

enumerate()

函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。

结论
1.列表,字典可以使用del删除内部元素,但是,列表中是删除元素,字典中是删除键值对。
2.使用del没法循环遍历删除set中的元素,因为引用机制问题。
3.str tuple内部的元素都不可更改所以不能使用del删除元素。
list tuple set str可以使用max min获取容器内的最大最小值
dict是使用max和min获取键的最大最小值

2、enumerate()

`# 枚举函数:获取容器内数据时添加序号(默认序号从0开始可以作为索引使用)

enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。

Python 2.3. 以上版本可用,2.6 添加 start 参数。

基本语法:

enumerate(可遍历对象, start=0)

注意:start参数用来设置遍历数据的下标的起始值,默认为0。

list1 = ['a', 'b', 'c', 'd', 'e']

for i in enumerate(list1):
    print(i)

for key, value in enumerate(list1, start=1):
    print(f'下标是{key}, 对应的字符是{value}')

3、容器类型转换

tuple()方法:将某个序列转换成元组

list1 = [10, 20, 30, 40, 50, 20]
s1 = {100, 200, 300, 400, 500}

print(tuple(list1))
print(tuple(s1))
"""
(10, 20, 30, 40, 50, 20)
(400, 100, 500, 200, 300)
"""

list()方法:将某个序列转换成列表

t1 = ('a', 'b', 'c', 'd', 'e')
s1 = {100, 200, 300, 400, 500}

print(list(t1))
print(list(s1))
"""
['a', 'b', 'c', 'd', 'e']
[400, 100, 500, 200, 300]
"""

set()方法:将某个序列转换成集合(但是要注意两件事 => ① 集合可以快速完成列表去重 ② 集合不支持下标)

list1 = [10, 20, 30, 40, 50, 20]
t1 = ('a', 'b', 'c', 'd', 'e')

print(set(list1))
print(set(t1))
"""
{40, 10, 50, 20, 30}
{'d', 'e', 'b', 'a', 'c'}
"""

列表集合字典推导式

1、什么是推导式

推导式comprehensions(又称解析式),是Python的一种独有特性。推导式是可以从一个数据序列构建另一个新的数据序列(一个有规律的列表或控制一个有规律列表)的结构体。 共有三种推导:列表推导式集合推导式字典推导式

2、为什么需要列表推导式

列表推导式
集合推导式
字典推导式
没有元组推导式和字符串推导式,因为其内部元素无法被修改。

案例:创建一个0-9的列表
while

# 1. 准备一个空列表
list1 = []

# 2. 书写循环,依次追加数字到空列表list1中
i = 0
while i < 10:
    list1.append(i)
    i += 1

print(list1)

for

list1 = []
for i in range(10):
    list1.append(i)

print(list1)

3、列表推导式

基本语法:

变量名 = [表达式 for 变量 in 列表 for 变量 in  列表]
变量名 = [表达式 for 变量 in 列表 if 条件]

案例:创建一个0-9的列表

list1 = [i for i in range(10)]
print(list1)

4、带if的列表推导式

案例:创建一个0-9的偶数列表
方法一:range()步长实现

list1 = [i for i in range(0, 10, 2)]
print(list1)

方法二:if实现

list1 = [i for i in range(10) if i % 2 == 0]
print(list1)

5、多个for循环实现列表推导式

案例:创建列表 => [(1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]

list1 = [(i, j) for i in range(1, 3) for j in range(3)]
print(list1)
用推导式进行九九乘法表的生成,将所有的算式放入列表中。
# list6 = []
# for i in range (1,10):
#     for j in range(1,i+1):
#         list6.append(f"{j:2}x{i:2}={i*j:2} ")
# print(list6)

list7 = []
[list7.append(f"{j:2}x{i:2}={i*j:2} ") for i in range (1,10) for j in range(1,i+1)]
print(list7)

6、字典推导式

思考:有如下两个列表,如何快速合并为一个字典?
list1 = [‘name’, ‘age’, ‘gender’]
list2 = [‘Tom’, 20, ‘man’]

答:使用字典推导式
基本语法:
字典推导式是列表推导式思想的延续,语法差不多,只不过产生的是字典而已。
字典推导式格式:
变量名 = {…}
字典推导式作用:快速合并列表为字典或提取字典中目标数据。

案例1:创建一个字典:字典key是1-5数字,value是这个数字的2次方。

dict1 = {i: i**2 for i in range(1, 5)}
print(dict1)  # {1: 1, 2: 4, 3: 9, 4: 16}

案例2:将两个列表合并为一个字典。

list1 = ['name', 'age', 'gender']
list2 = ['Tom', 20, 'man']
dict1 = {list1[i]: list2[i] for i in range(len(list1))}
print(dict1)

案例3:提取字典中目标数据。

counts = {'MBP': 268, 'HP': 125, 'DELL': 201, 'Lenovo': 199, 'acer': 99}

# 需求:提取上述电脑数量大于等于200的字典数据
count1 = {key: value for key, value in counts.items() if value >= 200}
print(count1)  # {'MBP': 268, 'DELL': 201}

7、集合推导式

集合推导式跟列表推导式非常相似,唯一区别在于用 { } 代替 [ ]
需求:创建一个集合,数据为下方列表的2次方。

list1 = [1, 1, 2]

代码:

list1 = [1, 1, 2]
set1 = {i ** 2 for i in list1}
print(set1)  # {1, 4}

注意:集合有数据去重功能。

字典不支持加法和乘法运算
字典支持max函数
元祖类型可以被遍历

1-23函数基本使用

1、函数的作用及使用步骤

1、函数的作用

来看一个典型的应用场景,用户到ATM机取钱:
输入密码后显示"选择功能"界面
查询余额后显示"选择功能"界面
取2000钱后显示"选择功能"界面
思考一个问题:显示“选择功能”界面需要重复输出给用户,要怎么实现呢?答:使用函数

2、什么是函数

函数是一个被命名的、独立的、完成特定功能的代码段,其可能给调用它的程序一个返回值。

被命名的:在Python中,大部分函数都是有名函数
完成特定功能的代码段:函数的功能要专一,专门为了完成某个功能而定义
返回值:当函数执行完毕后,其可能会返回一个值给函数的调用处

函数的主要作用:
① 模块化编程
② 代码重用

3、函数的定义

函数的定义:

def 函数名(参数1,参数2...):
    函数体
    ...
    return 返回值

函数的调用:

函数名(参数)
注意:
① 不同的需求,参数可有可无。
② 在Python中,函数必须先定义后使用。
4、引入函数

案例一:定义一个打招呼程序,用于实现向同事打招呼的功能

# 见到同事老张
print('您好')

# 见到同事老李
print('您好')

# 见到同事老王
print('您好')

以上代码虽然可以完成打招呼程序,但是重复性代码太多。能不能想个办法,将重复性代码分离出来呢?
答:可以,使用函数

# 定义函数,用于实现打招呼程序
def greet():
    print('您好')

# 见到同事老张
greet()

# 见到同事老李
greet()

# 见到同事老王
greet()
4.1函数的定义

案例二:定义一个打招呼函数,专门用于实现向同事打招呼的功能

# 定义函数,用于实现打招呼程序
def greet():
    print('您好')

# 见到同事老张
greet()

# 见到同事老李
greet()

# 见到同事老王
greet()
4.2函数的参数

案例三:升级案例二函数,可以实现向不同的人打不同的招呼

# 定义函数,添加参数,用于实现向不同的人打不同的招呼
def greet(name):
    print(f'您好,{name}')

# 见到同事老张
greet('老张')

# 见到同事老李
greet('老李')

# 见到同事老王
greet('老王')
5、函数的返回值

案例四:函数的设计原则“高内聚、低耦合”,函数执行完毕后,应该主动把数返回给调用处,而不应该都交由print()等函数直接输出。

# 定义函数,添加参数,用于实现向不同的人打不同的招呼
def greet(name):
    return '您好,' + name

# 见到同事老张
print(greet('老张'))

# 见到同事老李
print(greet('老李'))

# 见到同事老王
print(greet('老王'))
6、聊聊return

思考:如果一个函数如些两个return (如下所示),程序如何执行?

def return_num():
    return 1
    return 2

result = return_num()
print(result)  # 1

答:只执行了第一个return,原因是因为return可以退出当前函数,导致return下方的代码不执行。
思考:如果一个函数要有多个返回值,该如何书写代码?

案例:一个函数同时返回多个值

def return_num():
    return 1, 2

result = return_num()
print(result)  # (1, 2)
注意:
① `return a, b`写法,返回多个数据的时候,默认是元组类型。
② return后面可以连接列表、元组或字典,以返回多个值。

案例:制作一个计算器,计算任意两数字之和,并保存结果。

def sum_num(a, b):
    return a + b

result = sum_num(10, 20)
print(result)
# 30

2、函数的说明文档

1、什么是函数的说明文档

思考:定义一个函数后,程序员如何书写程序能够快速提示这个函数的作用?
答:注释

思考:如果代码多,我们是不是需要在很多代码中找到这个函数定义的位置才能看到注释?如果想更方便的查看函数的作用怎么办?
答:函数的说明文档(函数的说明文档也叫函数的文档说明)。

2、函数的说明文档的定义

☆ 定义函数的说明文档

def 函数名(参数):
    """ 说明文档的位置 """
    代码
    ......

☆ 查看函数的说明文档

help(函数名)

案例演示:

def sum_num(a, b):
    """ 求和函数 """
    return a + b

help(sum_num)

3、函数的嵌套

1、什么是函数的嵌套

所谓函数嵌套调用指的是一个函数里面又调用了另外一个函数。

def testB():
    print('---- testB start----')
    print('这里是testB函数执行的代码...(省略)...')
    print('---- testB end----')

def testA():
    print('---- testA start----')
    testB()
    print('---- testA end----')

testA()
"""
---- testA start----
---- testB start----
这里是testB函数执行的代码...(省略)...
---- testB end----
---- testA end----
"""
2、执行过程
如果函数A中,调用了另外一个函数B,那么先把函数B中的任务都执行完毕之后才会回到上次 函数A执行的位置。

4、函数应用案例

1、打印图形

☆ 打印一条虚线

def print_line():
    print('-' * 20)
print_line()

☆ 打印多条横线

def print_lines(num):
    i = 0
    while i < num:
        print_line()
        i += 1
print_lines(5)
2、函数计算

☆ 求三个数的和

def sum_num(a, b, c):
    return a + b + c

result = sum_num(1, 2, 3)
print(result)  # 6

☆ 求三个数的平均值

def average_num(a, b, c):
    sumResult = sum_num(a, b, c)
    return sumResult / 3

result = average_num(1, 2, 3)
print(result)  # 2.0

1-24函数作用域

1、局部变量和全局变量

1、局部变量

变量作用域指的是变量的作用范围(变量在哪里可用,在哪里不可用),主要分为两类:局部变量和全局变量。

所谓局部变量是定义在函数体内部的变量,即只在函数体内部生效。

def testA():
    a = 100
    print(a)

testA()   # 100
print(a)  # 报错:name 'a' is not defined

变量a是定义在testA函数内部的变量,在函数外部访问则立即报错。局部变量的作用:在函数体内部,临时保存数据,即当函数调用完成后,则销毁局部变量。

2、全局变量

所谓全局变量,指的是在函数体内、外都能生效的变量。
思考:如果有一个数据,在函数A和函数B中都要使用,该怎么办?
答:将这个数据存储在一个全局变量里面。

# 定义全局变量a
a = 100

def testA():
    print(a)  # 访问全局变量a,并打印变量a存储的数据

def testB():
    print(a)  # 访问全局变量a,并打印变量a存储的数据

testA()  # 100
testB()  # 100
3、global关键字

思考:testB函数需求修改变量a的值为200,如何修改程序?

a = 100

def testA():
    print(a)

def testB():
    # global 关键字声明a是全局变量
    global a
    a = 200
    print(a)

testA()  # 100
testB()  # 200
print(f'全局变量a = {a}')  # 全局变量a = 200
#扩展:在Python中所有的变量查询遵循legb原则
L:local 在函数体内部查询
E:edge 在外部函数中查询
g:global 在全局变量中查询
b:built-in 在系统内置变量中查询
4、多函数程序执行流程

☆ 共享全局变量一般在实际开发过程中,一个程序往往由多个函数(后面知识中会讲解类)组成,并且多个函数共享某些数据,如下所示:

# 1. 定义全局变量
num = 0

def test1():
    global num
    # 修改全局变量
    num = 100

def test2():
    # 调用test1函数中修改后的全局变量
    print(num)

# 2. 调用test1函数,执行函数内部代码:声明和修改全局变量
test1()
# 3. 调用test2函数,执行函数内部代码:打印
test2()  # 100

☆ 把函数返回值作为参数传递:

def test1():
    return 50

def test2(num):
    print(num)

# 1. 保存函数test1的返回值
result = test1()

# 2.将函数返回值所在变量作为参数传递到test2函数
test2(result)  # 50

2、函数参数进阶

1、位置参数

位置参数:调用函数时根据函数定义的参数位置来传递参数。

def user_info(name, age, gender):
    print(f'您的名字是{name}, 年龄是{age}, 性别是{gender}')

user_info('TOM', 20, '男')
注意:递和定义参数的顺序及个数必须一致。
2、关键字参数

函数调用,通过“键=值”形式加以指定。可以让函数更加清晰、容易使用,同时也清除了参数的顺序需求。

def user_info(name, age, gender):
    print(f'您的名字是{name}, 年龄是{age}, 性别是{gender}')

user_info('Rose', age=20, gender='女')
user_info('小明', gender='男', age=16)
函数调用时,如果有位置参数时,位置参数必须在关键字参数的前面,但关键字参数之间不存在先后顺序。
3、缺省参数(默认值)

缺省参数也叫默认参数,用于定义函数,为参数提供默认值,调用函数时可不传该默认参数的值(注意:所有位置参数必须出现在默认参数前,包括函数定义和调用)。

def user_info(name, age, gender='男'):
    print(f'您的名字是{name}, 年龄是{age}, 性别是{gender}')

user_info('TOM', 20)
user_info('Rose', 18, '女')
函数调用时,如果为缺省参数传值则修改默认参数值;否则使用这个默认值。

1-25总结 每日练习

练习题:

1、

使用列表推导式生成一个[0,5,10,15,...,50]的列表。
list1 = [i for i in range (51) if i % 5 == 0]
print(list1)
# [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50]

2、

使用列表推导式生成一个['page1', 'page2', 'page3'... 'page10']的列表
list1 = [f'page{i}' for i in range (1,11)]
print(list1)
# ['page1', 'page2', 'page3', 'page4', 'page5', 'page6', 'page7', 'page8', 'page9', 'page10']

3、

定义一个返回两个数值中的最大值的函数
def max_num(i,j):
    return i if i >= j else j

1-26不定长参数与组包解包

不定长参数也叫可变参数。用于不确定调用的时候会传递多少个参数(不传参也可以)的场景。此时,可用包裹(packing)位置参数,或者包裹关键字参数,来进行参数传递,会显得非常方便。

1、位置不定长参数

基本语法:

def user_info(*args):
    print(args)

# ('TOM',)
user_info('TOM')
# ('TOM', 18)
user_info('TOM', 18)

注意:传进的所有参数都会被args变量收集,它会根据传进参数的位置合并为一个元组(tuple),args是元组类型,这就是包裹位置传递。

2、关键字不定长参数(不定长参数字典)

基本语法:

def user_info(**kwargs):
# kwargs在从传参之后,会将实参位置的所有未定义参数的关键字参数转换为字典的键值对,保存在kwargs当中。
    print(kwargs)

# {'name': 'TOM', 'age': 18, 'id': 110}
user_info(name='TOM', age=18, id=110)
#kwargs 内部到底是什么存储结构呢?
def func(**kwargs):
# kwargs在从传参之后,会将实参位置的所有未定义参数的关键字参数转换为字典的键值对,,保存在kwargs当中
    print(kwargs) # {'a ' : 1,'b ': 2,'c ' : 3}
func(a=1,b=2,c=3)

综上:无论是包裹位置传递还是包裹关键字传递,都是一个组包的过程。

案例:输入多个数,输出最大值。
def max_num(*numbers):
    max = numbers[0]
    for i in numbers:
        if i > max:
            max = i
    print(max)
案例:使用创建一个函数可以保存学员的全部信息,并将其存储到字典中
def student_info(**kwargs):
    print(f"学生信息为:{kwargs}")
student_info(name = '张三',age = '118',gender = '男')

3、参数的排布顺序

1.位置参数和缺省参数之间的关系。
先关键字参数赋值,再缺省参数赋值
有默认值的参数只能放到没有默认值的参数的后面,否则报错。

2.位置参数、缺省参数,位置不定长参数之间的关系。
先位置参数、再缺省参数、后位置不定长参数。但是这种情况会使得每次的缺省参数都要赋值,很麻烦。所以有以下方案:
先位置参数、再位置不定长参数,后缺省参数(缺省参数需要赋值时用关键字参数赋值)

3.位置参数、缺省参数、位置不定长参数,关键字不定长参数之间的关系。
关键字不定长参数只能放到最后
顺序赋值不能在关键字赋值之后,调用顺序时先使用顺序赋值再使用关键字赋值。

def fun2(a,b,*args,c=10,**kwargs):
    print(a)
    print(b)
    print(c)
    print(args)
    print(kwargs)
fun2(1,2,3,4,5,6,c = 1,name = "张三",age = '18')

1
2
1
(3, 4, 5, 6)
{'name': '张三', 'age': '18'}

形参:位置参数》》位置不定长参数》》缺省参数》》关键字不定长参数

实参:顺序赋值》》关键字参数赋值

4、组包和拆包

组包:将多个值进行组合,打包为一个容器类型的过程
拆包:就是将一个容器类型,拆分成多个数据,分别赋值给多个变量的过程。

# 组包
def func1():
    return 1,2,3,4
#func1返回了多个数据,Python自动将其打包为一个元组,这个过程就是组包
print(func1())#(1,2,3,4)
#将多个数据打包整合为一个容器,赋值给变量,这个就是组包过程
a = 1,2,3,4
print(a)
# 拆包(解包)
a,b,c,d=[1,2,3,4]
print(a,b,c,d)
# 1 2 3 4

list1 = [1,2,3,4]
for index,value in enumerate(list1):
    print(index,value)
0 1
1 2
2 3
3 4
# 同时进行组包和拆包
# 将a,b的值互换
a,b=3,4
a,b=b,a
print(a,b) # 4 3
# 这个互换过程,是先将a,b的值提取出来,组包为一个元组,然后进行拆包,将元素内的两个数据分别赋值给a,b变量。
Python拆包

1、什么是拆包

拆包: 对于函数中的多个返回数据, 去掉元组, 列表 或者字典直接获取里面数据的过程。
☆ 拆包tuple元组:

def return_num():
    return 100, 200

num1, num2 = return_num()
print(num1)  # 100
print(num2)  # 200

☆ 拆包dict字典

dict1 = {'name': 'TOM', 'age': 18}
a, b = dict1

# 对字典进行拆包,取出来的是字典的key
print(a)  # name
print(b)  # age

print(dict1[a])  # TOM
print(dict1[b])  # 18

1-27 引用类型

1、值传递与引用传递

在python中,值是靠引用来传递来的。我们可以用id() 来判断两个变量是否为同一个值的引用。我们可以将id值理解为那块内存的地址标识。

#在python中所有的数据分为3个维度:值(判断 ==),数据类型(int ... float ...),唯一标识(id)

# 1.值相等的数据,唯一标识和数据类型不一定相等
a = 0
b = False
print(a == False) # True
print(type(a) == type(b)) # False
print(id(a) == id(b)) # False

# 2.值和数据类型相等的,唯一标识不一定相等
list1 = [1,2,3]
list2 = [1,2,3]
print(list1 == list2)  # True
print(type(list1) == type(list2)) # True 
print(id(list1) == id(list2)) # list1和list2的唯一标识不等,也就是说,其所在的内存空间不一致。

# 3.唯一标识相等的,值和数据类型必然相等

怎样判断唯一标识是否相等呢?
使用is关键字可以判断是否为同一个内存空间的数据。

2、可变与不可变类型

所谓可变类型与不可变类型是指:数据能够直接进行修改,如果能直接修改那么就是可变,否则是不可变。

可变类型

不可变类型

列表、字典、集合

整型、浮点型、字符串、元组、Boolean

3、引用类型当做参数传递

1-28案例-学员管理系统

1、学员管理系统功能概述

1、最终效果图
--------------------
  学生管理系统  v1.0
1.添加学生的信息
2.删除学生的信息
3.修改学生的信息
4.查询学生的信息
5.遍历所有学生的信息
6.退出系统
--------------------
2、功能概述

需求:进入系统显示系统功能界面,功能如下:
1、添加学员信息
2、删除学员信息
3、修改学员信息
4、查询学员信息
5、遍历所有学员信息
6、退出系统
系统共6个功能,用户根据自己需求选取

2、学员管理系统步骤分析

学员管理系统实现步骤

① 显示功能界面
② 用户输入功能序号
③ 根据用户输入的功能序号,执行不同的功能(函数)
定义函数
调用函数

3、学员管理系统代码实现

☆ 显示功能界面

定义函数print_info,负责显示系统功能。

def print_info():
    print('-' * 20)
    print('欢迎登录学员管理系统')
    print('1: 添加学员信息')
    print('2: 删除学员信息')
    print('3: 修改学员信息')
    print('4: 查询学员信息')
    print('5: 遍历输出所有学员信息')
    print('6: 退出系统')
    print('-' * 20)
print_info()
☆用户输入序号,选择功能

使用input获取用户输入序号:

user_num = input('请选择您需要的功能序号:')
☆根据用户选择,执行不同的功能

使用 if 判断用户要实现的功能

user_num = int(input("请输入编号(输入-1退出系统):"))
if user_num == 1:
    print('添加学员信息')
elif user_num == 2:
    print('删除学员信息')
elif user_num == 3:
    print('修改学员信息')
elif user_num == 4:
    print('查询学员信息')
elif user_num == 5:
    print('查询学员信息')
elif user_num == 6:
    print('退出系统')
else:
    print('信息输入错误')
☆循环输出功能菜单,直至用户手工退出

① 用户选择系统功能的代码需要循环使用,直到用户主动退出系统。
② 如果用户输入1-6以外的数字,需要提示用户。

user_num = 0
while (user_num != -1):
    user_num = int(input("请输入编号(输入-1退出系统):"))
    if user_num == 1:
        print('添加学员信息')
    elif user_num == 2:
        print('删除学员信息')
    elif user_num == 3:
        print('修改学员信息')
    elif user_num == 4:
        print('查询学员信息')
    elif user_num == 5:
        print('查询学员信息')
    elif user_num == 6:
        user_num = -1
        print('退出系统')
    else:
        print('信息输入错误')
☆ 定义全局列表,保存学员信息

所有功能函数都是操作学员信息,所有存储所有学员信息应该是一个全局变量,数据类型为列表。

后续列表结构如下:

info = [{'name':'Tom', 'age':18, 'mobile':'13578664321'}, {'name':'Mary', 'age':18, 'mobile':'19920187732'}, {'name':'Jennifier', 'age':18, 'mobile':'18862357791'}]
学员管理系统
stu_info = [{'id':'001','name':'张三','age':18,'phone':'183'}]


def exit_program():
    '''终止系统函数'''
    import sys
    sys.exit()

# def exit_program():
#     '''终止系统函数'''
#     exit()


def show_stu_info():
    '''展示所有学员信息函数'''
    for student_info in stu_info:
        print(f'学号:{student_info["id"]}  姓名:{student_info["name"]}  年龄:{student_info["age"]}  手机号码:{student_info["phone"]}')


def search_stu_info():
    '''查询学员信息函数'''
    id = input("请输入你要查询学员的id:")
    for student_info in stu_info:
        if student_info['id'] == id:
            print(f'学号:{student_info["id"]}  姓名:{student_info["name"]}  年龄:{student_info["age"]}  手机号码:{student_info["phone"]}')
            return
    else:
        print(f"没有{id}学员的信息")


def modify_stu_info():
    '''修改学员信息函数'''
    id = input("请输入你要修改学员的id:")
    for student_info in stu_info:
        if student_info['id'] == id:
            name = input("请输入修改后的学员名称:")
            age = int(input("请输入修改后的学员年龄:"))
            phone = input("请输入修改后的学员手机号:")
            student_info['name'] = name
            student_info['age'] = age
            student_info['phone'] = phone
            return
    else :
        print(f"不存在{id}学员的学生信息")


def del_stu_info():
    '''删除学员信息函数'''
    id = input("请输入要删除学员的id:")
    for student_info in stu_info:
        if student_info['id'] == id:
            stu_info.remove(student_info)
            print(f'id为{ id }的学员,信息删除成功')
            return
    print('不存在与该id对应的学生信息。')


def add_info():
    '''添加学员信息函数'''
    stu_id = [i['id'] for i in stu_info]
    id=input("请输入学员id:")
    if id in stu_id:
        print('此id已经存在,换一个吧。')
        print()
    else:
        name=input("请输入学员姓名:")
        age=input("请输入学员年龄:")
        phone=input("请输入学员手机号:")
        stu_info.append({'id':id,'name':name,'age':int(age),'phone':phone})


def print_option():
    '''界面显示函数'''
    print('-' * 20)
    print('  欢迎登录学员管理系统')
    print('1: 添加学员信息')
    print('2: 删除学员信息')
    print('3: 修改学员信息')
    print('4: 查询学员信息')
    print('5: 输出所有学员信息')
    print('6: 退出系统')
    print('-' * 20)


def chose(num):
    '''接受用户输入的命令,并调用对应的函数'''
    if num =='1':
        # print('添加学员信息')
        add_info()
    elif num == '2':
        # print('删除学员信息')
        del_stu_info()
    elif num == '3':
        # print('修改学员信息')
        modify_stu_info()
    elif num == '4':
        # print('查询学员信息')
        search_stu_info()
    elif num == '5':
        # print('输出所有学员信息')
        show_stu_info()
    elif num == '6':
        # print('退出系统')
        exit_program()
    else:
        print('信息输入错误')


while True:
    print_option()
    num = input("请输入编号:")
    chose(num)
    print(stu_info)
    print()

1-29递归与lambda

递归函数

# 函数递归的三个必备条件
'''
1.函数体内部,调用函数本身
2.递归有明确的跳出条件
3.不能超出最大调用深度
'''
# 计算100以内整数累加和
def func(n):
    if(n == 1):
     return 1;
    return func(n - 1) + n
print(func(100))# 5050
def fun1(n):
    '''递归求1~n的和'''
    if n != 1:
        return fun1(n-1)+n
    else:
        return 1

n = int(input('请输入正数:'))
print(fun1(n))

python中函数的最大的调用深度是1000

lambda函数

(10条消息) python的lambda表达式详细讲解_神的孩子都在歌唱的博客-博客_pythonlambda详解

lambda表达式, 也叫匿名函数
格式:lambda 参数:返回值

# 需求:根据传入的参数返回最大值,使用lambda函数书写
# 三目运算符:条件成立时返回的代码 if 条件 else 条件不成立时返回的代码
max_num = lambda a, b: a if a > b else b
# 使用变量可以存储lambda函数
print(max_num(1,2))

lambda应用场景
可以用于一次性函数使用
可以作为函数的参数进行传递

小练习

def find_all_pos(i,list1):
    '''查找到一个数字,在一组数字序列中,所对应的所有位置'''
    list_step = []
    step = 0
    for num in list1:
        step += 1
        if num == i:
            list_step.append(step)
    return tuple(list_step)

list1 = [1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,1,1,1]
i = int(input('请输入你要查找到数字:'))
a = find_all_pos(i,list1)
print(a)
def fibonacci_numbers(site):
    '''输出斐波那契数列的前n位数字'''
    list1 = [1,1]
    for i in range (site-1):
        if i == 0 or i == 1:
            print(1,end=' ')
        else :
            list1.append(list1[i - 2] + list1[i - 1])
            print(list1[i],end=' ')


site = int(input('输出斐波那契数列的前n位数字:'))
# site = 20
fibonacci_numbers(site)

1-30文件基本操作

学习目标:

了解文件操作的作用,
掌握文件的基本操作如打开、读写、关闭、备份等等。
掌握python操作文件和文件夹的方法
能独立完成文件操作应用案例的编写

文件读写,在使用的时候和我们正常使用文件一样。

1、文件的操作步骤

  1. 打开文件
  2. 读写文件
  3. 关闭文件

1、文件
文件可以分为文本文件、视频文件、音频文件、图像文件、可执行文件等等。

2、文件操作包含哪些内容?
打开、关闭、读、写、备份等操作

3、文件操作的作用
把一些内容(数据)存储存放起来,可以让程序下一次执行的时候直接使用,而不必重新制作一份,省时省力。

2、open()打开函数

在python,使用open函数可以打开一个已经存在的文件或创建一个新文件。

open(name,mode)

name:是要打开的目录文件名的字符串(可以包含文件所在的具体路径)
mode:设置打开文件的模式(访问模式):r 只读、w 写入、a 追加等。

# 用open函数打开文件。使用 open 函数会返回一个文件对象。
# 文件路径可以是相对路径也可以是绝对路径
# 读写模式r(只读)、w(写入)、a(追加)
file = open('python01.txt','r')
print(file) # <_io.TextIOWrapper name='python01.txt' mode='r' encoding='cp936'> CP936其实就是GBK
print(file.read()) # 将该文件中的内容读取并打印到屏幕上
file.close() # 关闭文件
print(file) # <_io.TextIOWrapper name='python01.txt' mode='r' encoding='cp936'>
print(file.read()) # ValueError: I/O operation on closed file.
# 为什么要关闭文件
# 在文件打开状态会保持连接,这种状态下会持续消耗内存,不利于服务器性能优化(内存泄漏)

# 关闭文件后,文件对象有没有被释放?
# 没有释放
# 文件关闭后,相当于与文件的连接状态消失了,但是文件对象没有发生变化。
# 在文件关闭后,file对象不能进行任何读写操作,因为已经无法连接文件。

1、写操作

案例演示:

# 1. 打开文件
f = open('python.txt', 'w')

# 2.文件写入
f.write('hello world')

# 3. 关闭文件
f.close()

注意:
w模式和a模式:如果文件不存在则创建该文件;如果文件存在,w模式先清空再写入,a模式直接末尾追加。
r模式:如果文件不存在则报错。

2.1、读操作

文件在'r'模式下可进行读取。
读取的文件不存在则会直接报错。

read()方法:

文件对象.read(num)

num表示单次读取的最大字符数,如果没有传入num,那么就表示读取文件中所有的数据。实际开发一般每次读取的字符数为(1024x1024)

2.2其他读取方式

readline # 每次读取1行的数据,

readlines # readlines可以按照行的方式把整个文件中的内容进行一次性读取,以\n为该行的终止,并且返回的是一个列表,其中每一行的数据为一个元素。
file = open("python.txt",'r',encoding='utf-8')
content = 1
while (content != ''):
    content = file.readline()
    print(content,end="")
file.close()
----------------------------------------------------------
file = open("python.txt",'r',encoding='utf-8')
while True:
    content = file.readline()
    if(content == ''):
        break
    print(content,end="")
file.close()

4 文件写入

write()

当文件的读写模式是'w',可以使用文件的写入操作。
若打开的该文件的读写模式是'w',并且该文件不存在,则会新建该文件,不会报错。
若打开的该文件的读写模式是'w',并且该文件存在,则会清空该文件中的原数据。
当完成文件的读写操作时,我们写入文件和读取文件所使用的编码格式必须一致。
用windows电脑开发,在写入文件时,需要指定编码格式为utf-8
用Linux 或 mac 会默认是utf-8

file = open('python01.txt','w',encoding='utf-8')
file.write("一去二三里,烟村四五家")
content = file.readline()
print(content)
file.close()
--------------------报错---------------------
io.UnsupportedOperation: not readable
是因为这个代码中有两处错误:
1、你是用open打开一个文件,此时调用的是w写入模式,下面使用read是没有权限的。 
2、使用write写入一个字符s,但是此时并没有真正的写入,而是还存在与内存中。 此时执行read读取的为空字符。
解决方法:去掉读文件的部分就好

5 文件追加

'a'模式写入:追加模式。
在追加模式下可以进行文件字符的追加,在原有数据的末尾添加新字符。
如果打开的文件是以追加方式,并且该文件不存在,则会新建该文件。

file1 = open('python.txt','a',encoding = 'utf-8')
file1.write("""天上的星星亮晶晶\n""")
file1.close()

6.mode访问模式详解(了解)

模式

描述

r

以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。

rb

以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。

r+

打开一个文件用于读写。文件指针将会放在文件的开头。

rb+

以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。

w

打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。

wb

以二进制格式打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。

w+

打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。

wb+

以二进制格式打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。

a

打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。

ab

以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。

a+

打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。

ab+

以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。

1-31文件操作案例

1.文件备份案例

# 用户输入当前目录下任意文件名,完成对文件的备份功能(备份文件名为xx[备份]后缀,例如:test[备份].txt

file_name = input("请输入文件名:")
file = open(file_name,'r',encoding='utf-8')
copy_file_name = file_name.replace('.','[备份].')
copy_file = open(copy_file_name,'a',encoding="utf-8")
content = file.read()
copy_file.write(content)
file.close()
copy_file.close()

# 一般情况下,文件都是指定单次读取的最大字符的
file_name = input("请输入文件名:")
file = open(file_name,'r',encoding='utf-8')
copy_file_name = file_name.replace('.','[备份].')
copy_file = open(copy_file_name,'a',encoding="utf-8")
while True:
    content = file.read(3)
    if(content == ''):
        break
    copy_file.write(content)
file.close()
copy_file.close()
# 用户输入当前目录下任意文件名,完成对文件的备份功能(备份文件名为xx[备份]后缀,例如:test[备份].txt
file_name = input('请输入需要备份的文件名:')
file1 = open(file_name,'r',encoding='utf-8')
new_file_name = file_name.replace('.','[备份].')
new_file = open(new_file_name,'w+',encoding='utf-8')
new_file.writelines(file1.readlines())
print(new_file.readlines())
file1.close()
new_file.close()
# python01.txt

# 运行结果为
请输入需要备份的文件名:python01.txt
[]
分析:程序运行没问题,但备份后的文件内容显示未空非None,而我们在pycharm中手动点击可以发现python01.txt的备份文件已经产生,并且备份文件中的内容也是完整的。

(10条消息) python写文件光标的用法_云丶图的博客-博客_python光标you

2.文件操作

1、os模块

在Python中文件和文件夹的操作要借助os模块里面的相关功能,具体步骤如下:
① 导入os模块 import os
② 还用os模块的相关功能 os.函数()

2、文件操作

编号

函数

功能

1

os.rename(目标文件名称,新文件名称)

对一个文件进行重命名操作

2

os.remove(要删除文件名称)

对一个文件进行删除操作

import os
os.rename('python.txt','/draft/python01.txt')
os.remove('draft.txt') # 可以删除文件不会提示任何信息,并且不会到回收站
# 使用 remove 不能删除文件夹

3.文件夹的操作

函数

功能

os.mkdir(新文件夹名称)

创建一个指定名称的文件夹

os.getcwd()

current work directory,获取当前目录名称

os.chdir(切换后目录名称)

change directory,切换目录

os.listdir(目标目录)

获取指定目录下的文件信息,返回列表

os.rmdir(目标目录)

用于删除一个指定名称的"空"文件夹

os.mkdir(新文件夹名称)
创建一个空文件夹,不能创建多级文件夹。
如果创建的文件夹已经存在,则报错。
如果上级目录不存在,则不能创建该文件夹。

os.rmdir(目标目录)
如果删除的文件夹已经不存在,则会报错。
文件非空不能删除,需要递归删除。

os.getcwd()
默认工作目录就是工程所在的根目录。

4.批量修改文件名案例

# 需求:批量修改文件名,既可添加指定字符串,又可以删除指定字符串
# 步骤:
# ① 设置添加删除字符串的的标识
# ② 获取指定目录的所有文件
# ③ 将原有文件名添加/删除指定字符串,构造新名字
# ④ os.rename()重命名

第二章 Python面向对象编程

2-1类定义与初始化

1、什么是编程思想

所谓的编程思想,就是人们利用计算机来解决实际问题的一种思维方式,常见的编程思想有面向过程和面向对象,很多计算机语言的语法各不相同,但是它们基本的编程思想却是差不多的,而Python是同时支持面向对象和面向过程的编程语言!

面向对象,面向过程。

2、类和对象

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-woxzTb0f-1670931802462)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\image-20221208212830537.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-H45DPuNk-1670931802463)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\image-20221208213035232.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EY3JXTlU-1670931802463)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\image-20221208213108120.png)]

类就是一系列拥有相同或相似功能的对象的集合,或者说就是一系列事物的统称。

对象就是类的具体表现形式

3、类的定义和实例化

python中类分为:经典类和实例类
经典类:不由任意内置类型派生出的类,称之为经典类。

class 类名:
    pass # python代码占位也可用...来占位

新式类:这就是一个类,只不过里面什么都没有!其中,类名不区分大小写,遵守一般的标识符的命名规则(以字母、数字和下划线构成,并且不能以数字开头),一般为了和方法名相区分,类名的首字母一般大写!(大驼峰法))

class 类名(父类名):
    ...
类名的定义要使用大驼峰命名法。
python严格区分大小写,class Student 和class student是两个不同的类。
我们可以直接打印对象,得到的是其所对应的类和所在的内存地址。
也可以答应对象的类型,输出的就是其类名。
理论上,类可以创建无数个实例对象。
class Student():
    def studey(self):
        print("我在上网课啊...")
    def run(self):
        print("run...")

s1 = Student()
s1.run()
s1.studey()

# run...
# 我在上网课啊...

4、self

在类的内部定义方法的时候,自动传入一个self,在调用实例方法时,不需要对self进行传值。

self就是将调用方法的实例传入方法内部,在方法内部可以调用那个实例的属性和方法

2-2总结与复习

2-3示例属性操作

1、在类的外部添加和获取实例属性

属性即是特征,比如:人的姓名、年龄、身高、体重…都是对象的属性。对象属性既可以在类外面添加和获取,也能在类里面添加和获取。

扩展:__dict__ 可以通过__dict__去查询该实例的所有属性

class student():
    def hi(self):
        print("good morning!")

s1 = student()
s1.name = 'xiaoming'
s1.age = 18
print(s1)
print(s1.__dict__)

# <__main__.student object at 0x000001C7656B02E0>
# {'name': 'xiaoming', 'age': 18}

2、在类的内部添加和获取实例属性

在类的外部添加和获取实例属性
。添加:对象名.属性名=值。获取︰对象名.属性名
。创建对象后,我们对其中一个对象添加实例属性,其他对象不发生变化

在类的内部添加和获取实例属性
。添加:self.属性名=值
。获取:self.属性名
。一般实例属性写在实例方法中,调用该方法才能获取实例属性,对象创建后,其中一个实例调用该方法,获取实例属性,其余对象不发生变化

2-4魔法方法

1、魔术方法介绍

在Python中,__xxx__()的函数叫做魔法方法,指的是具有特殊功能的函数。

魔术方法的定义一般使用__func__()格式定义函数名,所以我们再定义函数名或方法名时,禁用这种方式进行定
以下内容是系统内置变量,不是函数也不是方法,
print( __ name __ )
print( __ file__ )

2、__init__()方法

__init__()方法在对象创建完成后,初始化对象时,自动调用在init方法中添加的属性,由于每个对象都会执行该方法,所以都包含该属性,被称之为公有属性。
在init方法之外添加的属性,由于不是每个对象都拥有,所以被称之为独有属性。

class Person():
    
    # 定义初始化功能的函数
    def __init__(self):
        # 添加实例属性
        self.name = '老王'
        self.age = 18
        self.address = '北京'
	
    def print_info(self):
        # 类里面调用实例属性
        print(f'姓名:{self.name}, 年龄:{self.age},地址:{self.address}')
        
p1 = Person()
p1.print_info()
① __init__()方法,在创建一个对象时默认被调用,不需要手动调用
② __init__(self)中的self参数,不需要开发者传递,python解释器会自动把当前的对象引用传递过去。

3、带参数的__init__()方法

虽然我们已经可以通过__init__实现类属性的初始化操作,但是以上案例还存在一个问题,所有实例属性都拥有相同的name、age以及address,这显然是不对的。应该如何解决呢?答:使用带参数的__init__()

class Person():
    
    # 定义初始化功能的函数
    def __init__(self, name, age, address):
        # 添加实例属性
        self.name = name
        self.age = age
        self.address = address
	
    def print_info(self):
        # 类里面调用实例属性
        print(f'姓名:{self.name}, 年龄:{self.age},地址:{self.address}')
        
p1 = Person('老王', 18, '北京')
p1.print_info()

p2 = Person('老李', 20, '深圳')
p2.print_info()

4、__str__方法

当使用print输出对象的时候,默认打印对象的内存地址。如果类定义了__str__方法,那么就会打印从在这个方法中 return 的数据。

class Person():
    
    # 定义初始化功能的函数
    def __init__(self, name, age, address):
        # 添加实例属性
        self.name = name
        self.age = age
        self.address = address
	
    def __str__(self):
        """ 返回一个对象的描述信息 """
        return f'姓名:{self.name},年龄:{self.age},地址:{self.address}'
    	
       
p1 = Person('老王', 18, '北京')
print(p1)

5、__del__()方法

当删除对象时,python解释器也会默认调用__del__()方法。

class Person():
    
    # 定义初始化功能的函数
    def __init__(self, name, age, address):
        # 添加实例属性
        self.name = name
        self.age = age
        self.address = address
    
    def __del__(self):
        print(f'{self}对象已经被删除')
        
p1 = Person('老王', 18, '北京')

# <__main__.Person object at 0x101af8f90>对象已经被删除
del p1

2-5面向对象案例

1、学员成绩案例

需求:定义学员信息类,包含姓名、成绩属性,定义成绩打印方法(90分及以上显示优秀,80分及以上显示良好,70分及以上显示中等,60分及以上显示合格,60分以下显示不及格)

class Student():
    def __init__(self, name, score):
        self.name = name
        self.score = score
        
    def print_grade(self):
        if self.score >= 90:
            print(f'{self.name},{self.score}分,成绩优秀')
        elif self.score >= 80:
            print(f'{self.name},{self.score}分,成绩良好')
        elif self.score >= 70:
            print(f'{self.name},{self.score}分,成绩中等')
        elif self.score >= 60:
            print(f'{self.name},{self.score}分,成绩及格')
            
p1 = Student('Tom', 80)
p1.print_grade()

p2 = Student('Rose', 99)
p2.print_grade()

2-6面向对象封装与继承

封装、继承、多态

面向对象的三大特性:封装、继承、多态
① 封装
将属性和方法书写到类的里面的操作即为封装,封装可以为属性和方法添加私有权限。
② 继承
子类默认继承父类的所有属性和方法,与此同时子类也可以重写父类属性和方法。
③ 多态
多态是同一类事物具有的多种形态。不同的对象调用同一个接口(方法),表现出不同的状态,称为多态。

1、私有属性和私有方法

在Python中,可以为实例属性和方法设置私有权限,即设置某个实例属性或实例方法不继承给子类。
设置私有属性和私有方法的方式非常简单:在属性名和方法名 前面 加上两个下划线 “__” 即可。

案例1:私有属性和私有方法设置方式

class Girl():
    def __init__(self):
        self.name = '小美'
        self.__age = 18

    def __showinfo(self):
        print('姓名:%s,年龄:%d' % (self.name, self.__age))

girl = Girl()
print(girl.name)
# 外界不能直接访问私有属性和私有方法
print(girl.__age)
girl.__showinfo()

2、获取与设置私有属性值

在Python中,一般定义函数名’ get_xx ‘用来获取私有属性,定义’ set_xx '用来修改私有属性值。

class Girl():
    def __init__(self):
        self.name = '小美'
        self.__age = 18
        
    def get_age(self):
        return self.__age
    
    def set_age(self, age):
        self.__age = age


girl = Girl()
girl.set_age(19)
print(girl.get_age())

3、封装的意义在哪里?

封装数据属性:明确的区分内外,控制外部对对隐藏的属性的操作行为

class People(object):
    def __init__(self, name, age):
        self.__name = name
        self.__age = age

    def tell_info(self):
        print('Name:<%s> Age:<%s>' % (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

封装方法:隔离复杂度

class ATM:
    def  __card(self):
         print('插卡')
    def  __auth(self):
         print('用户认证')
    def __input(self):
          print('输入取款金额')
    def __print_bill(self):
          print('打印账单')
    def __take_money(self):
          print('取款')

    def withdraw(self):
          self.__card()
          self.__auth()
          self.__input()
          self.__print_bill()
          self.__take_money()

atm = ATM()
atm.withdraw()

1、什么是继承

我们接下来来聊聊Python代码中的“继承”:类是用来描述现实世界中同一组事务的共有特性的抽象模型,但是类也有上下级和范围之分,比如:生物 => 动物 => 哺乳动物 => 灵长型动物 => 人类 => 黄种人

2、继承的基本语法

基本语法:

# 父类B
class B(object):
	pass

# 子类A
class A(B):
    pass

在Python中,所有类默认继承object类,object类是顶级类或基类;其他子类叫做派生类。

3、与继承相关的几个概念

继承:一个类从另一个已有的类获得其成员的相关特性,就叫作继承!
派生:从一个已有的类产生一个新的类,称为派生!
很显然,继承和派生其实就是从不同的方向来描述的相同的概念而已,本质上是一样的!

父类:也叫作基类,就是指已有被继承的类!
子类:也叫作派生类或扩展类

扩展:在子类中增加一些自己特有的特性,就叫作扩展,没有扩展,继承也就没有意义了!
单继承:一个类只能继承自一个其他的类,不能继承多个类,单继承也是大多数面向对象语言的特性!
多继承:一个类同时继承了多个父类, (C++、Python等语言都支持多继承)

4、Python中的单继承

单继承:一个类只能继承自一个其他的类,不能继承多个类。这个类会有具有父类的属性和方法。
基本语法:

# 父类B
class B(object):
	pass

# 子类A
class A(B):
    pass

5、重写父类属性和方法

重写也叫作覆盖,就是当子类成员与父类成员名字相同的时候,从父类继承下来的成员会重新定义!

此时,通过子类实例化出来的对象访问相关成员的时候,真正其作用的是子类中定义的成员!

6、调用父类属性和方法

super():调用父类属性或方法,完整写法:super(当前类名, self).属性或方法()

class Animal():
    def __init__(self, name, age):
        self.name = name
        self.age = age


    def eat(self):
        print('吃...')


    def sleep(self):
        print('睡...')


    def call(self):
        print('叫...')
        ...
class Dog(Animal):
    def __init__(self, name, age, sex):
        super().__init__(name, age)
        self.sex = sex


    def __str__(self):
        return f'{self.name},今年{self.age}岁了,我会汪汪叫...'


class Cat(Animal):
    def __init__(self, name, age, sex):
        super().__init__(name, age)
        self.sex = sex

    def __str__(self):
        return f'{self.name},今年{self.age}岁了,我会喵喵叫...'
    ...

7、Python中的多继承实现

多继承:一个类同时继承了多个父类,并且同时具有所有父类的属性和方法例如:孩子会继承父亲 和 母亲的方法。

class Father(object):
    pass

class Mother(object):
    pass

class Child(Father, Mother):
    pass

注:MRO(Method Resolution Order):方法解析顺序,我们可以通过类名.__mro__或类名.mro()获得“类的层次结构”,方法解析顺序也是按照这个“类的层次结构”寻找到。

2-7面向对象多态

1、什么是多态

多态指的是一类事物有多种形态。

定义:多态是一种使用对象的方式,子类重写父类方法,调用不同子类对象的相同父类方法,可以产生不同的执行结果
① 多态依赖继承
② 子类方法必须要重写父类方法

好处:调用灵活,有了多态,更容易编写出通用的代码,做出通用的编程,以适应需求的不断变化!

2、多态的实现步骤

定义父类,并提供公共方法
定义子类,并重写父类方法
传递子类对象给调用者,可以看到不同子类执行效果不同

3、多态实现

类具有继承关系,并且子类类型可以向上转型看做父类类型,如果我们从 Animal 派生出 Cat和 Dog,并都写了一个 call() 方法,如下示例:

class Animal(object):  
   def __init__(self, name, age):
       self.name = name
       self.age = age
   def call(self):
       print(self.name, '会叫')
class Cat(Animal):
   def __init__(self, name, age, sex):
       super(Cat, self).__init__(name, age)
       self.sex = sex

   def call(self):
       print(self.name, '会“喵喵”叫')

class Dog(Animal):
   def __init__(self, name, age, sex):
       super(Dog, self).__init__(name, age)
       self.sex = sex
   def call(self):
       print(self.name, '会“汪汪”叫')
def do(all):
   all.call()

A = Animal('小黑',4)
C = Cat('喵喵', 2, '男')
D = Dog('旺财', 5, '女')

for x in (A,C,D):
   do(x)
小黑 会叫
喵喵 会“喵喵”叫
旺财 会“汪汪”叫

2-8类属性方法

1、类属性和实例属性

类属性就是 类对象中定义的属性,它被该类的所有实例对象所共有。通常用来记录 与这类相关 的特征,类属性 不会用于记录 具体对象的特征。
案例:定义一个工具类, 每件工具都有自己的名称,需求:知道使用这个类,创建了多少个工具对象?

class Tool(object):
    # 定义类属性,用于记录创建了多少个工具对象
    count = 0
    
    def __init__(self, name):
        self.name = name
        # 针对类属性做一个计数+1操作
        Tool.count += 1

        
tool1 = Tool('斧头')
tool2 = Tool('榔头')
tool3 = Tool('铁锹')

# 输出工具对象的总数
print(Tool.count)

2、类方法

类方法就是针对类对象定义的方法,在类方法中可以直接访问类属性或者调用其他类方法。
基本语法:

@classmethod
def 类名称(cls):
    pass

类方法需要用修饰器" @classmethod “来标识,告诉解释器这是一个类方法类方法的第一个参数应该是” cls "
① 有哪一个类调用的方法,方法内的" cls “就是哪一个类的引用
② 这个参数和示例方法的第一个参数是"self"类似
③ 提示使用其他名称也可以,不过习惯使用” cls " 通过类名.调用类方法,调用方法时,不需要传递" cls "参数

在方法内部
① 可以通过"cls."访问类的属性 ② 也可以通过 “cls.” 调用其他的类方法

3、静态方法

在开发时,如果需要在类中封装一个方法,这个方法:
① 既 不需要访问实例属性或者调用实例方法
② 也 不需要访问类属性或者调用类方法
这个时候,可以把这个方法封装成一个静态方法

基本语法:

@staticmethod
def 静态方法名():    
    pass

2-9python异常处理

1、什么是异常

当检测到一个错误时,解释器就无法继续执行了,反而出现了一些错误的提示,这就是所谓的"异常"。

2、异常演示

例如:以r方式打开一个不存在的文件。

f = open('linux.txt', 'r')

执行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RXvcgiZA-1670931802463)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\image-20221213191634059.png)]

3、捕获常规异常

基本语法:

try:
    可能发生错误的代码
except:
    如果出现异常执行的代码

快速入门
需求:尝试以r模式打开文件,如果文件不存在,则以w方式打开。

try:
    f = open('linux.txt', 'r')
except:
    f = open('linux.txt', 'w')

4、捕获指定异常

基本语法:

try:
    print(name)
except NameError:
    print('name变量名称未定义错误')

① 如果尝试执行的代码的异常类型和要捕获的异常类型不一致,则无法捕获异常。
② 一般try下方只放一行尝试执行的代码。

5、捕获多个异常

当捕获多个异常时,可以把要捕获的异常类型的名字,放到except 后,并使用元组的方式进行书写。

try:
    print(1/0)
except (NameError, ZeroDivisionError):
    print('ZeroDivision错误...')

执行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rrihfltj-1670931802464)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\image-20221213191858427.png)]

6、捕获异常并输出描述信息

基本语法:

try:
    print(num)
except (NameError, ZeroDivisionError) as e:
    print(e)

执行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8fEwNuQG-1670931802464)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\image-20221213191959676.png)]

7、捕获所有异常

基本语法:

try:
    print(name)
except Exception as e:
    print(e)

执行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BtZi0Nq8-1670931802464)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\image-20221213192045482.png)]

8、异常else

else表示的是如果没有异常要执行的代码。

try:
    print(1)
except Exception as e:
    print(e)
else:
    print('我是else,是没有异常的时候执行的代码')

执行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gtU4SZPv-1670931802465)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\image-20221213192218246.png)]

9、异常的finally

finally表示的是无论是否异常都要执行的代码,例如关闭文件。

try:
    f = open('test.txt', 'r')
except Exception as e:
    f = open('test.txt', 'w')
else:
    print('没有异常,真开心')
finally:
    f.close()

10、抛出自定义异常

在Python中,抛出自定义异常的语法为raise 异常类对象

2-10python模块与包

1、什么是模块

Python 模块(Module),是一个 Python 文件,以 .py 结尾,包含了 Python 对象定义和Python语句。模块能定义函数,类和变量,模块里也能包含可执行的代码。

2、模块的导入方式

import 模块名
from 模块名 import 功能名
from 模块名 import *
import 模块名 as 别名
from 模块名 import 功能名 as 别名

3、制作自定义模块

在Python中,每个Python文件都可以作为一个模块,模块的名字就是文件的名字。也就是说自定义模块名必须要符合标识符命名规则。

4、测试模块

在实际开中,当一个开发人员编写完一个模块后,为了让模块能够在项目中达到想要的效果,这个开发人员会自行在py文件中添加一些测试信息,例如,在my_module1.py文件中添加测试代码。

def test(a, b):
    print(a + b)
test(1, 1)

此时,无论是当前文件,还是其他已经导入了该模块的文件,在运行的时候都会自动执行test函数的调用。
解决方案:

def test(a, b):
    print(a + b)

# 只在当前文件中调用该函数,其他导入的文件内不符合该条件,则不执行testA函数调用
if __name__ == '__main__':
    test (1, 1)

调用方式:

import my_module1
my_module1.test (1, 1)

注意事项:如果使用from … import …或from … import *导入多个模块的时候,且模块内有同名功能。当调用这个同名功能的时候,调用到的是后面导入的模块的功能。

# 模块1代码
def my_test(a, b):
    print(a + b)

# 模块2代码
def my_test(a, b):
    print(a - b)
   
# 导入模块和调用功能代码
from my_module1 import my_test
from my_module2 import my_test

# my_test函数是模块2中的函数
my_test(1, 1)

5、模块的定位顺序

当导入一个模块,Python解析器对模块位置的搜索顺序是:
当前目录
如果不在当前目录,Python则搜索在shell变量PYTHONPATH下的每个目录。
如果都找不到,Python会查看默认路径。UNIX下,默认路径一般为/usr/local/lib/python/

模块搜索路径存储在system模块的sys.path变量中。变量里包含当前目录,PYTHONPATH和由安装过程决定的默认目录。

注意:
自己的文件名不要和已有模块名重复,否则导致模块功能无法使用
"使用from 模块名 import 功能"的时候,如果功能名字重复,调用到的是最后定义或导入的功能。

6、__all__

如果一个模块文件中有__all__变量,当使用from xxx import *导入时,只能导入这个列表中的元素。

my_module1模块代码

__all__ = ['testa']

def testa():
    print('testA')

def testb():
    print('testB')

导入模块的文件代码

from my_module1 import *
testa()
testb()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RpFVttIT-1670931802465)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\image-20221213193324703.png)]

1、什么是Python包

包将有联系的模块组织在一起,即放到同一个文件夹下,并且在这个文件夹创建一个名字为__init__.py 文件,那么这个文件夹就称之为包。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-641FezOp-1670931802465)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\image-20221213193415797.png)]

2、制作包

[New] — [Python Package] — 输入包名 — [OK] — 新建功能模块(有联系的模块)。注意:新建包后,包内部会自动创建__init__.py文件,这个文件控制着包的导入行为。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YMrbPYCr-1670931802465)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\image-20221213193455098.png)]

3、快速入门

① 新建包mypackage ② 新建包内模块:my_module1my_module2 ③ 模块内代码如下

# my_module1
print(1)
def info_print1():
    print('my_module1')
# my_module2
print(2)
def info_print2():
    print('my_module2')

4、导入包

方法一:

import 包名.模块名

包名.模块名.目标

快速入门:

import my_package.my_module1

my_package.my_module1.info_print1()

方法二:
注意:必须在__init__.py文件中添加__all__ = [],控制允许导入的模块列表。

from 包名 import *
模块名.目标

快速入门:

from my_package import *

my_module1.info_print1()

试卷分析

# 分析下面的代码是否可以达到预期结果,如果不能把分析的原因说明,然后修改代码【要求2种方式实现 一种是在现在代码基础上,一个是使用for in】
# #要求: 现有一个列表 li = [1,2,3,4,6,7,8,10,12],删除列表中的偶数数据
# li = [1,2,3,4,6,7,8,10,12]
# index = 0
# lg = len(li)
# while index < lg:
#     if li[index]%2==0:
#         del li[index]
#     index+=1
# print(li)


# 不能达到预期结果
# 循环进行一次删除操作后,删除后的列表长度应当进行-1操作,并且下一次循环的索引下标应该还是这个值。
li = [1,2,3,4,6,7,8,10,12]
index = 0
lg = len(li)
while index < lg:
    if li[index]%2==0:
        del li[index]
        lg -= 1
        index -=1
    index+=1
print(li)

# li = [1,2,3,4,6,7,8,10,12]
# box = []
# for i in li:
#     if i % 2 == 0:
#         box.append(i)
# for j in box:
#     li.remove(j)
# print(li)
# 假如现有一组爬虫爬取的数据,每个元素包含了一个IP地址域端口号,
# [("192.168.1.109",6000),("192.168.1.109",None),("192.168.2.255",8000),("192.168.100.200",8080),
# ("192.168.1.8600",6000),("192.168.1.199",8000),("192.168.1.500",6000),("192.168.1.50",80000),
# ("192.168.1.50",'80000')],里面的部分数据有错误,
#
# 请去去除错误数据,保留正确的数据!编写代码中请使用列表推导式
list1 = [("192.168.1.109",6000),("192.168.1.109",None),("192.168.2.255",8000),("192.168.100.200",8080),("192.168.1.8600",6000),("192.168.1.199",8000),("192.168.1.500",6000),("192.168.1.50",80000),("192.168.1.50",'80000')]
list2 = []
for i in list1:
    Error_data = False
    ip_num = i[0]
    ip_verify = ip_num.split('.')
    for num in ip_verify:
        if int(num) > 255 or int(num) < 0:
            Error_data = True
            break
    if Error_data == True:
        continue
    port_verify = i[1]
    if isinstance(port_verify,str) == True:
        continue
    if str(port_verify).isdigit() == False:
        continue
    if port_verify < 1 or port_verify > 65535:
        continue
    list2.append(i)
print(list2)
# 请同学实现一个可以递归删除指定目录下面的固定格式的文件的程序()
# 示例: remove(myproject,'pyc') , 表示删除myproject目录中的所有以pyc文件结尾的文件
# 提示:
#     可以使用help方法查看os.path下面的方法分别是什么作用
import os
def remove(project_name, file_type):
    os.chdir(project_name)
    file_list = os.listdir()
    for i in file_list:
        if i.find('.'+file_type) != -1:
            os.remove(i)
remove('D:/aSpaceForLearning/pythonCode/class2/Draft','txt')
# 题目:现在有2个类,一个是博主类一个是粉丝类,要求博主可以发表博客,博主提供查看博客的内容,博主可以提供粉丝关注功能,博主
# 提供粉丝取消关注的功能,当博主更新状态的时候,粉丝可以得知博主的状态更新了!提供博客的评论功能,便于当新博客更新后,粉丝评论
# 要求:
# 同学们百度关键词 python 观察者模式,查阅观察者模式相关的资料
# 同学们请使用观察者模式实现此案例
# 里面提供了2个类,其他的类需要同学自己抽取,方法也需要同学分析!
# 请同学们灵活使用基础所学内容
# 把关注博主的粉丝信息保存到文件中fans.info,以及博主发表的博客内容,博客对应的评论内容保存到 blogs.info
# fans.info 格式 : ['粉丝: 粉丝1', '粉丝: 粉丝2']
# blogs.info 格式:
# [{id:1,content:xxx,comments:[conment1,comment2]},xxx]  # 可以考虑使用推导式
#  运行图示
# 提醒: 实际开发也是这样的一个状态,可能是边查看资料边写代码,提前感受下!

from 模块名 import 功能名 as 别名

3、制作自定义模块

在Python中,每个Python文件都可以作为一个模块,模块的名字就是文件的名字。也就是说自定义模块名必须要符合标识符命名规则。

4、测试模块

在实际开中,当一个开发人员编写完一个模块后,为了让模块能够在项目中达到想要的效果,这个开发人员会自行在py文件中添加一些测试信息,例如,在my_module1.py文件中添加测试代码。

def test(a, b):
    print(a + b)
test(1, 1)

此时,无论是当前文件,还是其他已经导入了该模块的文件,在运行的时候都会自动执行test函数的调用。
解决方案:

def test(a, b):
    print(a + b)

# 只在当前文件中调用该函数,其他导入的文件内不符合该条件,则不执行testA函数调用
if __name__ == '__main__':
    test (1, 1)

调用方式:

import my_module1
my_module1.test (1, 1)

注意事项:如果使用from … import …或from … import *导入多个模块的时候,且模块内有同名功能。当调用这个同名功能的时候,调用到的是后面导入的模块的功能。

# 模块1代码
def my_test(a, b):
    print(a + b)

# 模块2代码
def my_test(a, b):
    print(a - b)
   
# 导入模块和调用功能代码
from my_module1 import my_test
from my_module2 import my_test

# my_test函数是模块2中的函数
my_test(1, 1)

5、模块的定位顺序

当导入一个模块,Python解析器对模块位置的搜索顺序是:
当前目录
如果不在当前目录,Python则搜索在shell变量PYTHONPATH下的每个目录。
如果都找不到,Python会查看默认路径。UNIX下,默认路径一般为/usr/local/lib/python/

模块搜索路径存储在system模块的sys.path变量中。变量里包含当前目录,PYTHONPATH和由安装过程决定的默认目录。

注意:
自己的文件名不要和已有模块名重复,否则导致模块功能无法使用
"使用from 模块名 import 功能"的时候,如果功能名字重复,调用到的是最后定义或导入的功能。

6、__all__

如果一个模块文件中有__all__变量,当使用from xxx import *导入时,只能导入这个列表中的元素。

my_module1模块代码

__all__ = ['testa']

def testa():
    print('testA')

def testb():
    print('testB')

导入模块的文件代码

from my_module1 import *
testa()
testb()

[外链图片转存中…(img-RpFVttIT-1670931802465)]

1、什么是Python包

包将有联系的模块组织在一起,即放到同一个文件夹下,并且在这个文件夹创建一个名字为__init__.py 文件,那么这个文件夹就称之为包。

[外链图片转存中…(img-641FezOp-1670931802465)]

2、制作包

[New] — [Python Package] — 输入包名 — [OK] — 新建功能模块(有联系的模块)。注意:新建包后,包内部会自动创建__init__.py文件,这个文件控制着包的导入行为。

[外链图片转存中…(img-YMrbPYCr-1670931802465)]

3、快速入门

① 新建包mypackage ② 新建包内模块:my_module1my_module2 ③ 模块内代码如下

# my_module1
print(1)
def info_print1():
    print('my_module1')
# my_module2
print(2)
def info_print2():
    print('my_module2')

4、导入包

方法一:

import 包名.模块名

包名.模块名.目标

快速入门:

import my_package.my_module1

my_package.my_module1.info_print1()

方法二:
注意:必须在__init__.py文件中添加__all__ = [],控制允许导入的模块列表。

from 包名 import *
模块名.目标

快速入门:

from my_package import *

my_module1.info_print1()

试卷分析

# 分析下面的代码是否可以达到预期结果,如果不能把分析的原因说明,然后修改代码【要求2种方式实现 一种是在现在代码基础上,一个是使用for in】
# #要求: 现有一个列表 li = [1,2,3,4,6,7,8,10,12],删除列表中的偶数数据
# li = [1,2,3,4,6,7,8,10,12]
# index = 0
# lg = len(li)
# while index < lg:
#     if li[index]%2==0:
#         del li[index]
#     index+=1
# print(li)


# 不能达到预期结果
# 循环进行一次删除操作后,删除后的列表长度应当进行-1操作,并且下一次循环的索引下标应该还是这个值。
li = [1,2,3,4,6,7,8,10,12]
index = 0
lg = len(li)
while index < lg:
    if li[index]%2==0:
        del li[index]
        lg -= 1
        index -=1
    index+=1
print(li)

# li = [1,2,3,4,6,7,8,10,12]
# box = []
# for i in li:
#     if i % 2 == 0:
#         box.append(i)
# for j in box:
#     li.remove(j)
# print(li)
# 假如现有一组爬虫爬取的数据,每个元素包含了一个IP地址域端口号,
# [("192.168.1.109",6000),("192.168.1.109",None),("192.168.2.255",8000),("192.168.100.200",8080),
# ("192.168.1.8600",6000),("192.168.1.199",8000),("192.168.1.500",6000),("192.168.1.50",80000),
# ("192.168.1.50",'80000')],里面的部分数据有错误,
#
# 请去去除错误数据,保留正确的数据!编写代码中请使用列表推导式
list1 = [("192.168.1.109",6000),("192.168.1.109",None),("192.168.2.255",8000),("192.168.100.200",8080),("192.168.1.8600",6000),("192.168.1.199",8000),("192.168.1.500",6000),("192.168.1.50",80000),("192.168.1.50",'80000')]
list2 = []
for i in list1:
    Error_data = False
    ip_num = i[0]
    ip_verify = ip_num.split('.')
    for num in ip_verify:
        if int(num) > 255 or int(num) < 0:
            Error_data = True
            break
    if Error_data == True:
        continue
    port_verify = i[1]
    if isinstance(port_verify,str) == True:
        continue
    if str(port_verify).isdigit() == False:
        continue
    if port_verify < 1 or port_verify > 65535:
        continue
    list2.append(i)
print(list2)
# 请同学实现一个可以递归删除指定目录下面的固定格式的文件的程序()
# 示例: remove(myproject,'pyc') , 表示删除myproject目录中的所有以pyc文件结尾的文件
# 提示:
#     可以使用help方法查看os.path下面的方法分别是什么作用
import os
def remove(project_name, file_type):
    os.chdir(project_name)
    file_list = os.listdir()
    for i in file_list:
        if i.find('.'+file_type) != -1:
            os.remove(i)
remove('D:/aSpaceForLearning/pythonCode/class2/Draft','txt')
# 题目:现在有2个类,一个是博主类一个是粉丝类,要求博主可以发表博客,博主提供查看博客的内容,博主可以提供粉丝关注功能,博主
# 提供粉丝取消关注的功能,当博主更新状态的时候,粉丝可以得知博主的状态更新了!提供博客的评论功能,便于当新博客更新后,粉丝评论
# 要求:
# 同学们百度关键词 python 观察者模式,查阅观察者模式相关的资料
# 同学们请使用观察者模式实现此案例
# 里面提供了2个类,其他的类需要同学自己抽取,方法也需要同学分析!
# 请同学们灵活使用基础所学内容
# 把关注博主的粉丝信息保存到文件中fans.info,以及博主发表的博客内容,博客对应的评论内容保存到 blogs.info
# fans.info 格式 : ['粉丝: 粉丝1', '粉丝: 粉丝2']
# blogs.info 格式:
# [{id:1,content:xxx,comments:[conment1,comment2]},xxx]  # 可以考虑使用推导式
#  运行图示
# 提醒: 实际开发也是这样的一个状态,可能是边查看资料边写代码,提前感受下!