由于本人因不能手搓脚本而感到自卑
此篇用来记录本人的python学习进度
希望能在寒假结束前把python学完
一起加油吧OWO
持续更新ing
Day1梦的开始
输出hello world
print("hello world!")
入门概念
字面量:代码中,被写下来的固定的值,称为字面量
(字符串,整数,浮点数。。。。)
注释:
单行注释:# (python中#后面加个空格(规范))
多行注释:""" """"(三个双引号中间的都是注释的内容),一般用于
- 整个python代码文件
- 类
- 方法
""""
本代码写着玩的
"""
print("hello world!")
print("111")# 输出
变量:
变量名 = 变量值
money = 100
print("钱包还有",money)
print(money - 10)
money = money - 10
print("还剩",money,"在钱包")
数据类型:(入门)
type()
输出类型信息,可以赋值给一个变量
print(type(money))
name = type(money)
print(name)
查看的是变量存储的数据的类型,因为,变量无类型,但是它存储的数据有
注意:字符串变量:我们会说一个字符串存储在一个变量里面,变量是没有类型的(python中)
数据类型转换:
int()
float()
str()任意都可以转字符串
都是有结果的,因此我们可以用变量来接受/print直接打印
转字符串
num_string = str(1110)
print(num_string,type(num_string))
# 整数转浮点数
num1 = float(int(10))
print(num1,type(num1))
# 浮点数转整数
num2 = int(float(10.43))
print(num2,type(num2))# 输出10
num3 = int(float(10.63))
print(num2,type(num3))# 输出10
由浮点数转换成整数时会丢失精度(小数部分)
标识符:
1.什么是标识符
①变量的名字
②方法的名字
③类的名字
内容限制:
英文(大小写敏感),中文(不推荐),数字(不能用在开头),下划线
不能使用关键字:
if false 。。。。。
命名规范:
变量名:见名知意,下划线命名法(不同单词分割),英文字母全小写
类名:
方法名:
运算符:
算数运算符:
+,-,×,/除,//取整除,%取余,**指数。
print("11 / 5 = ",11 / 5)
print("11 // 5 = ",11 // 5)
print("9 % 2 = ",9 % 2)
print("2 ** 2 = ",2 ** 2)

字符串拓展:
字符串的定义:
1.单引号定义法:
2.双引号
3.三引号(和多行注释一样支持换行,使用变量接收时为字符串,不使用变量接收,多行注释)
name_1 = '张三'
name_2 = "李四"
name_3 = """王五"""
print(name_1,name_2,name_3)
如果定义的字符串本身,是包含单引号,双引号自身呢?
单引号里面可以含有双引号
双引号内可以含有单引号
可以使用转义字符\来将引号解除效果,变成普通字符串
name_1 = '"张三"'
name_2 = "'李四'"
name_3 = """'王五'"""
print(name_1,name_2,name_3)
name_1 = '\"张三'
name_2 = "\'李四\'"
name_3 = "\"'王五'\""
print(name_1,name_2,name_3)
![]()
字符串的拼接:
+(和Java一样)
name = "李太白"
print("人生得意须尽欢" + "莫使金樽空对月")
print("我名字是" + name)
字符串只能和字符串拼接(但是我们强转)
tel = 121321321312
print("我的电话是"+str(tel))
字符串格式化1:
占位
拼接字符串
class_num = 57
avg_salary = 16781
message = "Python大数据,北京%s期,工资:%s" % (class_num,avg_salary)
print(message)
%占位,s是代表以字符串的形式传递进来
数字和字符串:
class_num = 57
avg_salary = 16781
message = "Python大数据,北京%s期,工资:%s" % (class_num,avg_salary)
print(message)
%d:整型
%f:浮点型
name = "传智播客"
setup_year = 2006
stock_price = 19.99
message = "%s,成立于%d年,今天的股价是%.2f" % (name,setup_year,stock_price)
print(message)
格式化的精度控制:
m.n:
m:控制宽度,宽度小于自身不生效,在数字前面加空格
n:控制精度,会进行四舍五入
name = "传智播客"
setup_year = 2006
stock_price = 19.99
message = "%s,成立于%d年,今天的股价是%.1f" % (name,setup_year,stock_price)
print(message)
(四舍五入(大于5))
m:
name = "传智播客"
setup_year = 2006
stock_price = 19.99
message = "%s,成立于%d年,今天的股价是%7.1f" % (name,setup_year,stock_price)
print(message)
![]()
20.0是4位于是前面要加3位(先精度后宽度)
字符串格式化方式2:
快速写法:
f"内容{变量}"
name = "传智播客"
setup_year = 2006
stock_price = 9.99
message = f"{name}在{setup_year}年诞生,股票价格为:{stock_price}"
print(message)
![]()
表达式的格式化:
表达式:一条具有明确执行结果的代码语句
在无需使用变量进行数据存储的时候,可以直接格式化表达式,简化代码
print("1 * 1的结果为:%d" % (1 * 1) )
print(f"1 * 2的结果是:{(1 * 2)}")
print("字符串在python中的类型是: %s" % (type('dadadadad')))
input语句(函数):
键盘录入
print("告诉我你的名字")
name = input()
print(f"我的名字是{name}")
但是在python中这个print是多余的,我们可以直接在input中输入
name = input("Who are you?\n")
print(f"我的名字是{name}")
但是input语句无论你写入的是什么类型的数据,它都会当作是字符串(可以进行强转===)
DAY2
布尔类型:真假(bool)
True:1
False:0
比较运算符:
==
!=
>
<
>=
<=
bool_1 = True
bool_2 = False
print(f"bool_1的变量内容:{bool_1},类型是:{type(bool_2)}")
print(f"bool_2的:{bool_2}")
判断语句:
if基本格式:
if 要判断的条件:
条件成立时,要做的事情
int(age) = input("请输入你的年龄\n")
- 在 Python 中,
int(age)是一个表达式,它的作用是把age变量的值转换为整数。 - 但赋值语句的左边必须是一个变量(比如
age),不能是表达式。
"""age = float(input("请输入你的年龄\n"))
if age >= 18:
print("你已经成年了")
else:
print("你还是未成年")
print("时间有点快")"""
age = input("请输入你的年龄\n")
if float(age) >= 18:
print("你已经成年了")
else:
print("你还是未成年")
print("时间有点快")
多条件的判断:
if 条件1:
应作的事情
elif 条件2:
应作的事情
elif 条件3:
应做的事情
else:
所有条件不符合时做的事情
age = int(input())
if age > 18:
print("你已经成年了")
elif age == 18:
print("你刚刚成年,成年快乐")
else:
print("你还是未成年")
elif语句可以写多个
判断是互斥且有顺序的,只有所有的elif都不满足,才会运行else语句
else可以省略不写(不满足条件就不执行)
嵌套判断语句
空格缩进
python中是通过空格缩进来决定语句之间的关系
num_1 = int(input("请输入一个整数"))
if num_1 > 0:
print("这个数字是正数")
if num_1 > 50:
print("这个数字大于50")
else:
print("这个数字小于50")
else:
print("这个数字是负数")
DAY3循环语句
while
语法:
while 条件: (这个条件可以是比较或者是布尔类型,总之结果要是true)
条件满足时,做的事情1
条件满足时,做的事情2
条件满足时,做的事情3
................
num_1 = int(input("输入一个整数"))
while num_1 < 100:
print("Hello World")
num_1 += 1

注意:
python中没有自增/自减符号
1-100的合
num_1 = 1
num_2 = 0
while num_1 <= 100:
num_2 += num_1
num_1 += 1
print(num_2)
while的嵌套:

主要就是注意缩进
i = 1
while i <= 100:
print(f"今天是我像小美表白的第{i}天。。。")
i += 1
j = 1
while j <= 10:
print(f"这是我送出去的第{j}朵玫瑰花")
j += 1
print("小美我喜欢你")
print(f"到了{i-1}天我们在一起了")
不换行:
print("hello")
print("world")
print("hello " , end = '')
print("world" , end = '')

制表符:\t
打印99乘法表
# 打印99乘法表
i = 1
while i <= 9:
j = 1
while j <= i:
print(f"{j} * {i} = {i * j}\t ", end='')
j += 1
i += 1
print()
for(轮询,遍历循环)
语法:
for 临时变量 in 待处理数据集:
循环满足条件时执行的代码
name = "dwadadadawda"
for x in name:
print(x)
与while循环的区别:
for循环无法定义循环条件(只能从一个数据集中不断取出数据,因此理论上无法无限for循环)
数数一串字符串中有几个a:
word = "day same gogogo aaa abc fi a"
num = 0
for char in word:
if char == "a":
num += 1
print(f"有{num}个a")
变量的作用域:
for i in range(10):
print(i)
print(i)
#可以输出但是规范上不建议
darange 语句:
帮助我们构建一个数字序列
range的用法
for num in range(100): #生成[0-100)含左不含右"""
print(num)
for num in range(50,100):#生成【num1-num2)也是含左不含右
print(num)
for num in range(100,1000,100):#step = 100
print(num)
待处理的数据集严格意义上被称为序列类型
序列类型:其内容可以被一个个依次取出的一种类型,包括:
- 字符串
- 列表
- 元组
- 等等
循环中断:break 和 continue
continue:
跳出本次循环
for i in range(10):
if i ==6:
continue
print(i)
break:
直接跳出循环
for i in range(10):
if i ==6:
break
print(i)
DAY4函数
函数:
是组织好的,可重复使用的,用来实现特定功能的代码段
#输出长度
name = "we are the world"
length = len(name)
print(length)
函数的定义:
def 函数名(传入参数):
函数体
return 返回值
def print1():
print("hello world")
print1()
注意:
①参数如果不需要,可以省略
②返回值不需要,可以省略
③函数必须先定义后使用
函数的参数:
函数的传入参数:在函数进行计算的时候,接受外部(调用时)提供的数据
def add(x,y):
result = x + y
return result
print(add(1,2))
x,y为形参
调用函数的1,2称为实参,为我们使用的参数值
传入参数的数量是不受限制的。
- 可以不使用参数
- 也可以仅使用任意N个参数
函数的返回值:
函数运行后的结果
def 函数(参数......):
函数体
return 返回值
变量 = 函数(参数)
注意:当函数体遇到return时就停止运行,return后面的代码就不执行了
def add(x,y):
result = x + y
return result
num = add(5,67)
print(num)
None类型:
无返回值的函数,实际上就是返回了:None这个字面量
①.我们不写return返回值时,就返回None
②.我们可以主动return None
def print1():
print("hello world")
result = print1()
print(f"无返回值的函数的结果是{result}")
print(f"其数据类型是{result}")
#hello world
#无返回值的函数的结果是None
#其数据类型是None
None作为一个特殊的字面量,用于表示:空、无意义,有很多应用场景。
- 用在函数无返回值上
- 用在if判断上(None等同于False)
- 一般用于函数中主动返回None,配合if判断做相关处理
- 用于声明无内容的变量上
- 定义变量,但暂时不需要变量有具体值,可以用None来代替
- name = None#暂时不赋予变量具体的值
def check_age(age):
if age >= 18:
return "SUCCESS"
else:
return None
result = check_age(16)
if not result:
print("未成年")
注意:在python中
- Python 无单独的
!取反运算符,逻辑布尔取反用 **not关键字 **(最常用); - 整数二进制按位取反用 **
~符号 **(数值操作,新手少用); !在 Python 中仅和=组合为!=,表示不等于判断;
函数的说明文档:
辅助理解函数的作用
用多行注释写在函数体之前
def add(x,y):
"""
add函数可以接受两个参数,进行2数的相加
:param x: 形参x表示相加的其中一个数
:param y: 形参y表示相加的另一个数
:return: 返回值是2数相加的结果
"""
result = x + y
print(f"两数相加的结果是:{result}")
return result
函数的嵌套调用:
在一个函数中又调用了另一个函数
def func_b():
print("func_b")
def func_a():
print("func_a")
func_b()
print("232323232323")
func_a()
a函数里调用b函数
函数中的变量的作用域:
变量的作用域指的是变量的作用范围
局部变量:
定义在函数体内部的变量,即只在函数体内部生效
当函数调用完之后
局部变量会被销毁
全局变量:
在函数体内体外都能够发挥作用的变量
#在函数内修改全局变量
num = 200
def test_a():
print(f"test_a:{num}")
def test_b():
num = 500
print(f"test_b:{num}")
test_a()
test_b()
print(num)

原因是因为,函数内部的num变量我们就将其看作一个新的局部变量了(因此这个函数内部的num与函数外的没有关系)
我们应该如何在函数内去修改函数外的全局变量呢?
global关键字
#在函数内修改全局变量
num = 200
def test_a():
print(f"test_a:{num}")
def test_b():
global num#global关键字声明其为全局变量
num = 500
print(f"test_b:{num}")
test_a()
test_b()
print(num)
、
DAY5数据容器
了解数据容器:
一个变量,能够存储多份数据
一种可以容纳多份数据的数据类型,容纳的每一份数据称之为一个元素,每一个元素,可以是任意类型,如字符串、数字、布尔。
list(列表):
列表一次可以存储多个数据
语法:
字面量[元素1,元素2,元素3,。。。。。]
#定义变量
变量名称 = [元素1,元素2.。。。。]
#定义空列表
变量名称 = []
变量名称 = list()
元素:
列表中的每一个数据,称之为元素,元素类型不受限
- 以【】作为标识
- 列表内每一个元素之间用,分隔开
name_list = ["vbfbfbfdbdf","cast","dadwdadsa"]
print(name_list)
print(type(name_list))

#列表的嵌套
my_list = [[1,2,3],[4,5,6]]
print(my_list)
print(type(my_list))
列表的下标(索引):
按照下表索引,获取对应位置的元素
可以从左向右(0),也可以从右向左(-1)
name_list = ['Tom','dadada','cscs']
print(name_list[2])
print(name_list[-1])
print(name_list[1])
print(name_list[-2])
print(name_list[0])
print(name_list[-3])
列表的嵌套
my_list = [["Tom","Lily","Rose"],["Jack","Donk","danking"]]
print(my_list)
print(my_list[0][2])
print(my_list[1][1])
注意:用索引取数据,不要超过范围
常用操作:
方法介绍:
函数是一个封装的代码单元,可以提供特定的功能
在python中,如果将函数定义为class(类)的成员,那么函数会称之为:方法
方法和函数只是写的位置不一样,使用的格式不一样
函数的使用: num = add(1,2)
方法的使用:student = Student()
num = student.add(1,2)
列表的查询功能:
语法:列表.index(元素)
my_list = [["Tom","Lily","Rose"],["Jack","Donk","danking"]]
print(my_list)
print(my_list.index(["Tom","Lily","Rose"]))
如果查询的元素不存在,会报错
修改特定位置(索引)的元素值:
语法:列表[下标] = 值
my_list = ["Tom","Lily","Rose"]
print(my_list)
my_list[0] = "Jack"
print(my_list)
插入元素:
语法:列表.insert(下标,元素),在指定的下标位置,插入指定的元素
my_list = ["Tom","Lily","Rose"]
print(my_list)
my_list.insert(1,"marry")
print(my_list)
元素的追加(添加)
1.追加一个元素
语法:列表.append(元素),将指定元素,追加到列表的尾部
my_list = ["Tom","Lily","Rose"]
print(my_list)
print(my_list.append("MIKE"))
print(my_list)
2.如果我们追加一批元素
语法:列表.extend(其他数据容器),将其它数据容器的内容取出,一次追加到列表尾部
my_list = ["Tom","Lily","Rose"]
print(my_list)
my_list.extend(["Tom","Lily","Rose"])
print(my_list)

my_list = ["Tom","Lily","Rose"]
print(my_list)
my_list.extend(["Tom","Lily","Rose"])
print(my_list)
my_new_list = ["Tom","Lily","Rose"]
my_list.extend(my_new_list)
print(my_list)

元素删除:(下标)
语法1:del 列表[下标]
语法2:列表.pop(下标)//pop方法可以有返回值,并且可以有一个变量去接收
my_list = [1, 2, 3]
del my_list[2]
print(my_list)
num = my_list.pop(1)
print(my_list)
print(num)
删除第一个匹配项:
语法:列表.remove(元素)
(只能删除一个)
my_list = [1, 2, 3,2,32,4343,2,4]
print(my_list)
my_list.remove(2)
print(my_list)

列表清空:
语法:列表.clear()
my_list = [1, 2, 3,2,32,4343,2,4]
print(my_list)
my_list.remove(2)
print(my_list)
my_list.clear()
print(my_list)

统计某元素在列表内的数量:
语法:列表.count(元素)
my_list = [1, 2, 3,2,32,4343,2,4]
print(my_list.count(2))
统计列表内总共有多少元素:
语法:len(列表)
my_list = [1,23,343,234,12,345]
count = len(my_list)
print(count)
总结:

常用功能的练习:
#有一个列表记录学生的年龄[21,25,21,23,22,20]
#1.定义这个列表并且用变量来接收它
age_list = [21,25,21,23,22,20]
#2.追加一个数字31,到列表尾部
age_list.append(31)
print(age_list)
#3.追加一个新列表[29,33,30],到列表的尾部
new_list = [29,33,30]
age_list.extend(new_list)
print(age_list)
#4.取出第一个元素(21)
print(age_list[0])
#5.取出最后一个元素(30),可以使用负数索引
print(age_list[len(age_list)-1])
print(age_list[-1])
#6.查找元素31,在列表中的下标位置
x = 0
for i in age_list:
if i == 31:
print(f"元素31所在的位置是{x}")
else:
x += 1
index = age_list.index(31)
print(index)
#我忘记index了
DAY6LIST列表的遍历:
将容器中的元素依次取出进行处理的行为,称之为:遍历、迭代
1.while循环的遍历
语法:
index = 0
while index < len(列表):
元素 = 列表[index]
对元素处理
index += 1
#while循环
my_list = [1,2321,54,68,23,65,1,5647]
index = 0
while index < len(my_list):
element = my_list[index]
print(element,end = ' ')
index += 1
print("\n")
#for循环
index = 0
for element in my_list:
print(element,end = ' ')
index += 1
while循环和for循环,都是循环语句,但细节不同:
- 在循环控制上:
- while循环可以自定循环的条件,并且自行控制
- for循环不可以自定循环,但可以一个个从容器内取出数据
- 在无限循环上:
- while循环可以通过条件控制做到无限循环
- for循环理论上不可以,因为被遍历的容器容量不是无限的
- 在使用场景上:
- while循环适用于任何想要循环的场景
- for循环适用于,遍历数据容器的场景或简单的固定次数循环场景
2.元组:
如果想要传递的信息,不想被篡改,列表就不合适了
元组和列表一样,都是可以分装多个、不同类型的元素在内。
但不同点:
元组一旦定义完成,就不可修改
(元组就是一个只读的list)
定义元组:
定义元组使用小括号,且使用都好隔开各个数据,数据可以是不同的数据类型。
#定义元组字面量
(元素1,元素2,元素3.。。。。。)
#定义元组变量
变量名称 = (元素,元素,。。。。。。。,元素)
#定义空元组
变量名称 = () #方式1
变量名称 = tuple() #方式2
my_tuple = ("1","dada","Hello",1,True)
print(my_tuple)
注意:
如果元组里面只有一个字符串内容,在内容后面要加个,
t1 = ("hello")
print(type(t1))
t2 = ("hello",)
print(type(t2))

如果不加逗号就不是元组类型
元组的嵌套:
t5 = ((1,2,3),(3,4,5))
print(type(t5))
用下标去取元素:(和list一样)
t5 = ((1,2,3),(3,4,5))
num = t5[1][2]
print(num)
操作:(元组不可修改)

t6 = (12,32,534534,75647,786,12,32,12,54,12)
print(t6.index(12))
print(t6.count(12))
print(len(t6))
index = 0
while index < len(t6):
print(t6[index],end = ' ')
index += 1
print("\n")
for i in t6:
print(i,end = ' ')
修改元组内容:
t6[0] = 1000
print(t6)
TypeError: 'tuple' object does not support item assignment
元组内容不支持修改
特例:
我们可以修改元组内部的list的内容
因为list没有发生改变,改变的只是list内部的内容
t6 = (232,432,["dada","2354534"])
t6[2][1] = 1
print(t6)
字符串的定义和操作:
字符串也算是容器
每一个字符都是一个容器的元素
并且可以使用下标
my_str = "hello world"
print(my_str[0])
print(my_str[-11])
#都可以取到h
字符串和元组一样都是无法修改的容器
字符串的替换:replace:
功能:替换字符串中的「指定子串」,不是替换整个字符串!
注意:
不是修改字符串本身,而是我们得到了一个新的字符串
(相当于会返回一个字符串(因为字符串不能修改)
my_str = "hello world"
new_str = my_str.replace("hello","你好")
print(my_str)
print(new_str)
只替换我们需要替换的部分
字符串的分割:split
语法:字符串.split(分割符字符串)
功能:按照指定的分割符字符串,将字符串划分为多个字符串,并存入列表对象中
注意:字符串本身不变,而是得到了一个列表对象
my_str = "hello world hi da daw2ef"
my_str_list = my_str.split(" ")
print(my_str_list)

字符串的规整操作strip
去前后空格,以及回车符
语法:字符串.strip()
去除前后指定的字符串
语法:字符串.strip(字符串)
my_str = " hello world hi da daw2ef "
new_str = my_str.strip()
print(new_str)
my_str1 = " hello world hi da daw2ef "
my_str2 = "hello"
new_str = my_str1.strip(my_str2)
print(new_str)
my_str3 = "hello world hi da daw2ef "
new_str = my_str3.strip(my_str2)
print(new_str)

说白了就是从前或者从后开始匹配然后去除,当遇到第一个匹配不到的字符时就停止
因为 my_str2 = "hello",strip() 会把它拆解成字符集合 {'h','e','l','o'}(重复的 l 会自动去重)。
统计字符串中某个字符串出现的次数:count
统计字符串的长度:len
字符串的遍历:while循环和for循环
这三个函数和前面的用法一模一样就不进行代码展示了
总结:

字符串的特点:
- 只可以存储字符串
- 长度任意(取决于内存大小)
- 支持下标索引
- 允许重复字符串存在
- 不可以修改(增加或删除元素)
- 支持for循环
练习:
#给定一个字符串:"we are all in the gutter,but some of us are looking at the stars"
#统计有多少个t
my_str = "we are all in the gutter,but some of us are looking at the stars"
print(f"t一共有{my_str.count("t")}个")
#将字符串空格全部替换为"|"
new_str = my_str.replace(" ","|")
print(new_str)
#按照|进行分割得到列表
new_str2 = my_str.split("|")
print(new_str2)
DAY7:数据容器(序列)的切片操作
序列:
内容连续,有序,可使用下标索引的一类数据容器
列表、元组、字符串,均可以视为序列
操作:
切片:
从一个序列中,取出一个子序列
语法:序列[起始下标:结束下标:步长]
表示从序列中,从指定位置开始,依次取出元素,到指定位置结束,得到一个新序列
结束下标是不包含,如果留空则到结尾 ,起始和结束都不写,表示从头到尾,步长为1可以省略
步长:
- 步长为1,一个一个取元素
- 2,每次跳过一个元素取
- 步长为N,每次跳过N-1个元素取
- 步长为负数,表示反向取(注意,起始下标和结束下标也要反向标记)
注意:
切片的操作不会影响序列本身,而是会得到一个新的序列(元组和字符串都是不支持修改的)
#对list进行切片,从1开始,4结束,步长为1
my_list = [0,1,2,3,4,5,6,7,8,9]
my_new_list = my_list[1:4]#结束的开区间,步长默认为1所以可以不写
print(my_new_list)
#对tuple进行切片,从头开始,到最后结束,步长为1
my_tuple = (1,2,3,4,5,6,7,8,9)#元组是小括号
my_new_tuple = my_tuple[:]#起始和结束为空时就自动从头到末尾,步长为1可以省略
print(my_new_tuple)
#对str进行切片,从头开始,到最后结束,步长为2
my_str = "dwfeshbtdgrdgdgdgdrg"
my_new_str = my_str[::2]
print(my_new_str)
#对str进行切片,从头开始,到最后结束,步长为-1
my_str1 = "1dadadadsxaxaxaxa65"
my_new_str1 = my_str1[::-1]#等同于将序列反转了
print(my_new_str1)
#对列表进行切片,从3开始,到1结束,步长为-1
my_list = [1,2,3,4,5,6,7,8,9]
my_new_list = my_list[3:1:-1]
print(my_new_list)
#对元组进行切片,从头开始,到位结束,步长为-2
my_tuple = (1,2,3,4,5,6,7,8,9)
my_new_tuple = my_tuple[::-2]
print(my_new_tuple)

总结:
-
起始和结束为空时就自动从头到末尾(结束是开区间)
-
步长为1可以省略
-
步长为-1,等同于将序列反转了
-
从头开始,末尾结束直接省略开头和结尾
案例:
#案例需求:ogogog,}!FTC!OLLEH{galf,yppah倒序过来,取出flag
str = "ogogog,}!FTC!OLLEH{galf,yppah"
str1 = str[::-1]
print(str1)
str2 = str1.split(",")#逗号会把原来的str变成被逗号分割的不同str
print(str2[1])

集合:
我们已经学习了列表、元组、字符串三个数据容器了
为什么要学习集合呢?
1、列表可修改、支持重复元素且有序
2、元组、字符串不可修改、支持重复元素且有序
集合:
特点:
自带去重处理且内容无序
列表:[]
元组:()
字符串:""
集合:{}
语法:
#定义集合字面量
{元素,元素,................,元素}
#定义集合变量
变量名称 ={元素,元素,................,元素}
#定义空集合‘
变量名称 = set()
my_set = {212,3213,5435,7657,7657,7657,212,True,"7657",True}
print(my_set)
print(type(my_set))

集合的常见操作:
1、因为集合是无序的,因此不支持下标索引访问
修改:
- 添加元素:add()
- 移除元素:remove(元素)
- 随机取出一个元素:pop()
- 清空集合:clear()
- 取2个集合的差集:集合1.difference(集合2),功能:取出集合1有但是集合2中没有的元素(会得到一个新的集合,集合1和集合2不变)
- 消除2个集合的差集:集合1.difference_update(集合2)在集合1中消除和集合2中相同的元素(集合1会发生变化,集合2不会发生变化)
- 2个集合并为1个集合:集合1.union(集合2)(原来的2个集合都不变,直接返回一个新的集合)
- 统计集合元素的数量:len(集合)
- 集合的遍历:for循环(while不可用)
练习:
#我们有如下的列表
my_list = ['a',"dadw","w","dadwa","dadwa",23232]
#定义一个空集合
my_set = set()
#通过for循环遍历列表
for element in my_list:
my_set.add(element)
print(my_set)
字典:
需要通过学生的姓名来检索学生的成绩
使用字典最为合适
定义:
字典的定义,同样是使用{},不过存储的元素是一个个的:键值对,
#定义字典字面量
{key: value,key: value,...........}
#定义字典变量
my_dict = {key: value,key: value,...........}
#定义空字典
my_dict = {}#方式1
my_dict = dict()#方式2
#定义字典
my_dict = {"小王":99,"小花":88,"小绿":22}
#定义空的字典
my_dict2 = {}#定义空字典时需要set(),因为{}被字典占用了
my_dict3 = dict()
print(my_dict)
#定义重复key的字典
my_dict4 = {"小王":99,"小花":88,"小绿":22,"小王":54}
print(my_dict4)

后面的key会把前面的key覆盖掉
因为python的字典不允许重复
字典可以通过key值来获取对应的value
my_dict = {"小王":99,"小花":88,"小绿":22}
score = my_dict["小王"]
print(score)
![]()
字典的嵌套:
- 字典的key和value可以是任意数据类型(key不可为字典)
那么就表示字典是可以嵌套的
stu_score_dict = {
"小王":{
"语文":77,
"数学":88
},"小红":{
"语文":79,
"数学":98
},"小黄":{
"语文":66,
"数学":22
}
}
print(stu_score_dict)
#如何获取信息
score = stu_score_dict["小王"]["语文"]
print(score)
字典的常用操作:
1.新增元素:
语法:
字典[key] = value,结果:字典被修改,新增了元素
2、更新元素
语法:
字典[key] = value , 结果:字典被修改,元素被更新
字典key不可以重复,所以对已存在的key执行上述操作,就是更新value值
3、删除元素:
语法:
字典:pop(key),结果:获得指定key的value,同时字典被修改,指定key的数据被修改
4、清空字典:
语法:
字典.clear()
5、获取全部的key
语法:
字典.keys() 结果:得到字典中的全部key
6、遍历字典
语法:
for循环
7、统计字典内的元素数量
语法:
len(字典)
my_dict = {"小周":323,"小李":88,"小黄":99}
#新增元素
my_dict["小张"] = 87
print(my_dict)
#更新元素
my_dict["小周"] = 33
print(my_dict)
#删除元素
score = my_dict.pop("小周")
print(my_dict)
#清空元素
my_dict.clear()
print(my_dict)
#获得全部的key
my_dict = {"小周":323,"小李":88,"小黄":99}
temp = my_dict.keys()
print(temp)
#遍历字典
#方式1
for key in my_dict.keys():
print(f"字典的key是{key}")
print(f"字典的value值是{my_dict[key]}")
#方式2
for key in my_dict.keys():
print(f"字典的key是{key}")
print(f"字典的value值是{my_dict[key]}")
#统计字典内的元素数量
print(len(my_dict))

注意:
对value的修改和添加就是对重复值的覆盖
小练习:
com_dict = {
"小王":{
"部门":"科技部",
"工资":3000,
"级别":1
},
"小周":{
"部门":"市场部",
"工资":5000,
"级别":2
},
"小李": {
"部门": "市场部",
"工资": 7000,
"级别": 3
},
"小张":{
"部门": "科技部",
"工资": 4000,
"级别": 1
},
"小刘": {
"部门": "市技部",
"工资": 6000,
"级别": 2
}
}
print(com_dict)
for k in com_dict.keys():
if com_dict[k]["级别"] == 1:
com_dict1 = com_dict[k]
com_dict1["工资"] += 1000
com_dict1["级别"] += 1
print(com_dict)
注意:
我们在遍历时,可以先将最外层的字典赋值给一个变量,这样我们就可以直接传第二个key‘给这个变量了
容器总结:
1、是否支持下标索引:
支持:列表、元组、字符串
不支持:集合、字典
2、是否支持元素重复
支持:列表、元组、字符串
不支持:集合、字典
3、是否可以修改
支持:列表、集合、字典
不支持:元组、字符串

数据容器的通用操作:
len(容器):元素的个数
max(容器):元素的最大值
min(容器):元素的最小值
my_list = [1,2,3,4,5,6,7,8,9]
my_tuple = (1,2,3,4,5,6,7,8,9)
my_str = "dadadadw"
my_set = {1,2,3,4,5,6,7,8,9}
my_dict = {
"key1":1,
"key2":2,
"key3":3,
"key4":4,
"key5":5
}
#len元素个数
print(len(my_list))
print(len(my_tuple))
print(len(my_str))
print(len(my_set))
print(len(my_dict))
#max最大元素
print(max(my_list))
print(max(my_tuple))
print(max(my_str))
print(max(my_set))
print(max(my_dict))
#min最小元素
print(min(my_list))
print(min(my_tuple))
print(min(my_str))
print(min(my_set))
print(min(my_dict))
#容器转列表
print(list(my_list))
print(list(my_tuple))
print(list(my_str))
print(list(my_set))
print(list(my_dict))
#容器转元组
print(tuple(my_list))
print(tuple(my_tuple))
print(tuple(my_set))
print(tuple(my_dict))
#转字符串
print(str(my_list))
print(str(my_tuple))
print(str(my_set))
print(str(my_dict))
#转换成集合
print(set(my_list))
print(set(my_tuple))
print(set(my_set))
print(set(my_dict))
#对容器进行排序
print(sorted(my_list))
print(sorted(my_list,reverse=True))
排序:
sorted(my_list,reverse=True)
reverse默认值是false,默认情况下是从小到大
改为true之后就是从大到小
字符串的大小比较原理:
ASCII码表
实际上就是比较ASCII码表
a:97
A:65
字符串是按位比较,就是一位位进行比对,只要有一位大,那么整体大
DAY8函数多返回值
注意:
执行第一个return之后就退出函数了
返回多个值:
return多个值
- 按照返回值的顺序,写对应顺序的多个变量接受
- 变量之间用逗号隔开
- 支持不同类型的数据return
def test_return():
return 1,2,"dadada"
x,y,z = test_return()
print(x,y,z)
函数的多种传参方式:
位置参数:
调用函数时根据函数定义的参数位置来传递参数
传递的参数和定义的参数的顺序以及个数必须一致
def user_info(name,age,gender):
print(f"您的名字是{name},年龄是{age},性别是{gender}")
user_info("TOM",67,"男")
关键字参数:
函数调用时通过“键 = 值”的形式传递参数
可以让函数更加清晰、容易使用,同时也清楚了参数的顺序需求
def user_info(name,age,gender):
print(f"您的名字是{name},年龄是{age},性别是{gender}")
user_info("TOM",67,"男")
#关键字传参可以不按照固定的顺序
user_info(name = "tom",gender = "男",age = 87)
#可以和位置参数混用,位置参数必须在前面,且匹配参数顺序
user_info("TON",gender = "男",age = 33)
#关键字传参可以不按照固定的顺序
#可以和位置参数混用,位置参数必须在前面,且匹配参数顺序
缺省参数:
缺省参数也叫默认参数,用于定义函数,为参数提供默认值,调用函数时可不传该默认参数的值
(注意:所有位置参数必须出现在默认参数前,包括函数定义和调用)
作用:
当调用函数时没有传递参数,就会使用默认是用缺省参数对应的值
def user_info(name,age,gender = "男"):
print(f"您的名字是{name},年龄是{age},性别是{gender}")
user_info("TONM",232)
这个默认值也可以通过手动传入来进行覆盖
设置默认值必须在最后
不定长参数(可变参数):
位置传递的不定长:
传进的所有参数都会被args变量手机,他会根据传入参数的位置合并为一个元组(tuple),args是元组类型,这就是位置传递
def user_info(*args):
print(args)
user_info(1,2,3,4,5)
关键字传递:
参数是“键=值”形式的情况下,所有的键值都会被kwargs接受,同时会根据键值组成字典
def user_indo(**kwargs):
print(kwargs)
user_indo(name = "小王",age = 20,id = 111)

匿名函数:
在之前的函数学习中,我们所使用的函数,都是接受数据作为参数传入
其实,我们也可以将函数本身作为参数传入另一个函数中
def test_func(compute):
result = compute(1,2)
print(result)
def compute(x,y):
return x+y
test_func(compute)
这个代码中也可以不传
def test_func():
result = compute(1,2)
print(result)
def compute(x,y):
return x+y
test_func()
我们之前的是数据确定,计算逻辑不确定
现在是数据不确定,但是逻辑是确定的
这是计算逻辑的传递,而不是数据的传递。
lambda匿名函数:
- def关键字,可以定义带有名称的函数
- lambda关键字,可以定义匿名函数(无名称)
有名称的函数,可以基于名称重复使用。
无名称的匿名函数,只能临时使用一次
语法:
lambda 传入参数:函数体(一行代码)
- lambda是关键字,表示定义匿名函数
- 传入参数表示匿名函数的形式参数,如:x,y表示接受2个形式参数
- 函数体,就是函数的执行逻辑,要注意:只能写一行,无法写多行代码
def test_func(com):
result = com(1,2)
print(result)
def compute(x,y):
return x+y
test_func(lambda x,y : x +y)
lambda函数就是直接返回return
DAY9文件的操作
1、文件编码以及常见的编码
计算机只能识别0和1,那我们的文本计算机是怎么识别并且存储在硬盘中的呢?
使用编码技术将内容翻译成0和1存入
可用的编码技术:
- UTF-8:全球比较通用
- GBK:中文
- Big5:繁体字
- .。。
不同的编码也就是不同的密码本
2、文件的读取
文件的操作:打开、关闭、读、写
打开文件:
open(naem,mode,encoding)打开函数
name:是要打开的 目标文件名号的字符串(具体路径)
mode:设置打开文件的模式(访问模式):只读、写入、追加等等。
encoding:编码格式(UTF-8)

相关的方法:
文件对象.read(num)
num表示要从文件中读取的数据的长度(单位是字节),如果没有传入num,那么就表示读取文件的所有数据
readlines()方法:
可以按照行的方式把整个文件中的内容进行一次性读取,并且返回的是一个列表,其中每一行的数据为一个元素
如果我们多次调用read函数那么我们下一次调用read函数会从上一次的结尾进行读取
文件读取的时候其实是有一个指针的
readline()方法:一次读取一行内容
for循环读取文件每一行
for line in 文件的对象:
print..........
close()关闭文件对象
关闭文件对象,也就是关闭对文件的占用
如果不调用close,同时程序没有停止运行,那么整个文件将一直被python程序占用
with open 语法操作文件
在执行完语句之后,可以自动关闭文件
import time
#打开文件
f = open("D:/test.txt","r",encoding="utf-8")
print(type(f))
#读取文件-read()
# print(f.read())#读取全部内容
# print(f.read(10))#读取十个字节
#读取文件-readLines()
# line_list = f.readlines()#读取的文件的全部行,然后封装在列表中
# print(f"lines的对象的类型是{type(line_list)}")
# print(line_list)
#读取文件-readline()
# print(f.readline())
#for循环读取文件行
for line in f:
print(line)
#文件的关闭
f.close()
#with open 语法操作文件
with open("D:/test.txt","r",encoding="utf-8") as f:
for line in f:
print(line)
time.sleep(36000)

练习:
统计hello出现的次数

#方式1直接读取全部内容
f = open("D:/test.txt","r",encoding="utf-8")
print(f.read().count("hello"))#直接统计
f.close()
#方式2一行一行的读取
with open("D:/test.txt","r",encoding="utf-8") as f:
count = 0
for line in f:
line = line.strip()#直接去除开头或结尾的空格或者换行符
words = line.split(" ")
for word in words:
if word == "hello":
count += 1
print(count)
文件的写入操作:
write方法
f.write("hello ,world")
1、打开文件 ‘w'
2、文件写入
3、内容刷新
直接调用write方法,内容并未真正写入文件,而是会积攒在程序的内存中,称之为缓冲区
避免频繁的操作硬盘,导致效率下降
f = open("D:/TXT.txt","w",encoding= "UTF-8")
#f.write("hello,world")#内容写入到内存中
#f.flush()#将内存中积攒的内容,写入到硬盘中的文件中
#f.close()#close方法,内置了flush功能
#打开一个存在的文件
f.write("是不是前面的内容被覆盖了")
f.close()
注意:
如果文件不存在,它会创建文件,之后将内容写入,如果文件已经存在,就会清空原有内容,然后再写入内容(相当于将原本内容覆盖了)
追加写入操作:
将打开文件时的“w”该换成“a“就行了
(a就是add)
注意:
如果文件不存在,就会创建然后写入,如果文件存在,就会再后面追加
f = open("D:/HELLP.txt","a",encoding="utf-8")
f.write("hello world")
f.write("hello world")
f.write("hello world")
f.close()

如果我们想要换行写入
f = open("D:/HELLP.txt","a",encoding="utf-8")
f.write("hello world")
f.write("\nhello world")
f.write("hello world")
f.close()
如果是这样:
f = open("D:/HELLP.txt","a",encoding="utf-8")
f.write("hello world\n")
f.write("\nhello world")
f.write("hello world")
f.close()

DAY10python异常、模块、包
当检测到一个错误时,python解释器就无法继续执行了,反而出现了一些错误的提示,这就是所谓的异常,也就是bug
为什么要捕获异常?
对可能出现的异常,进行提前准备,当真正出现异常的时候,可以有后续手段。
基本语法:
try:
可能出现错误的代码
except:
如果出现异常时执行的代码
try:
f = open("D:/abc.txt","r",encoding="utf-8")
except:
print("出现异常了,因为文件不存在,我将open的模式,改为w模式去打开")
f = open("D:/abc.txt","w",encoding="utf-8")
捕获指定异常:
基本语法:
try:
print(name)
except NameError as e:
print(‘name变量名未定义错误’)
#捕获指定的异常 try: print(name) except NameError as e: print("出现了变量未定义的异常") print(e)
我们可以用as设置对象渠道,进行直接打印(可以把e当作一个变量)

捕获多个异常:
语法:
try:
print(1/0)
except(NameError,ZeroDivisionError):
print('.....')
通过写入一个元组,用逗号隔开
#捕获多个异常
try:
print(name)
print(1/0)
except (NameError, ZeroDivisionError):
print("出现了变量未定义 或者 除以0的异常错误")
捕获全部异常:
try:
print(name)
print(1/0)
except Exception as e:
print("出现异常了")
try:
print(name)
print(1/0)
except:
print("出现异常了")
这两种写法是一样的(Exception是顶级异常)
异常else:
else是表示如果没有异常要执行的代码。
try:
print("hello world")
except Exception as e:
print("出现异常了")
else:
print("没有异常")
可以写也可以不写
异常的finally:
finally表示的是无论是否异常都要执行的代码,例如关闭文件。
try:
print("hello world")
except Exception as e:
print("出现异常了")
else:
print("没有异常")
finally:
print("hello world pro max")
try:
f = open("D:/123.txt","r",encoding="utf-8")
except Exception as e:
f = open("D:/123.txt","w",encoding="utf-8")
else:
print("没有异常")
finally:
f.close()
异常的传递:
异常是具有传递性的
def func01():
print("这是func01的开始")
num = 1 / 0
print("这是func01函数的结束")
def func02():
print("这是func02的开始")
func01()
print("这是func02函数的结束")
def main():
try:
func02()
except Exception as e:
print(f"出现异常了,异常的信息是{e}")
main()
python的模块:
什么是python的模块:
python模块(Module),是一个python文件,以.py结尾,模块能定义函数,类和变量,模块里也能包含可执行的代码。
模块的作用:
可以帮助我们快速实现一些功能,一个模块就是一个工具包
语法:
[from 模块名] import [模块 | 类 | 变量 | 函数 | *] [as 别名]
(【】内表示可选内容)
常用的组合形式:
- import 模块名
- from 模块名 import 类、变量、方法等
- from 模块名 import *
- import 模块名 as 别名
- from 模块名 import 功能名 as 别名
import模块名:
基本语法:
import 模块名
import 模块名1,模块名2
模块名.功能名()
#使用import导入time模块使用sleep功能(函数)
import time#导入python内置的time模块
print("你好")
time.sleep(5)#time内部的sleep功能
print("hello world")
通过.就可以使用模块内部的全部功能(类、函数、变量)
from 模块名 import 功能名
基本语法:
from 模块名 import 功能名
功能名()
from time import sleep
print("hello world")
sleep(5)
print("hello world agin")
from 模块名 import *
基本语法:
from 模块名 import *
功能名()
from time import *
sleep(5)
和第一种的效果相同,只不过写法不一样
as别名定义
基本语法:
#模块定义别名
import 模块名 as 别名
#功能定义别名
form 模块名 import 功能 as 别名
import time as t
t.sleep(1)
from time import sleep as sl
sl(5)
就是为了改名字,防止有写模块及其功能的名字太长不便使用
自定义模块
注意:
每个python文件都可以作为一个模块,模块名就是文件的名称,也就是说定义模块名必须符合标识符的命名规则

import my_module1
my_module1.test(676,54)
必须要在同一个文件夹下
导入不同模块下的同名功能,后面的会覆盖前面的
def test(a,b):
print(a+b)
if __name__ == '__main__':
test(1, 2)
这种情况下我们既保留了测试的函数,又在调用模块的时候不会执行测试函数
(__name__叫做内置变量,当我们运行时,内置变量就会变成__main__然后if的判断就会变成true于是执行test,在from的时候内置变量不会被赋值也就不会执行)
__all__变量:
如果一个模块文件中有_all_变量,当使用from时候就只能导入这个列表中的元素
__all__ = ["test_A"]
def test_A():
print("test_A")
def test_B():
print("test_B")

我们写*的时候是把所有的都导入进来,但是当我们写了__all__之后,我们能导入进来哪些会受到
__all__控制,我们手动导入不受影响
python包:
自定义包:
如果我们python的模块太多了,就可能会造成一定的混乱,如何管理?
通过python包来管理(文件夹)
什么是python包:
从物理上看:
包就是一个文件夹,该文件夹下包含了一个__init__.py文件,该文件可用于包含多个模块文件
(有__init__.py文件就是包,没有就是普通的文件夹)
从逻辑上看:
包的本质依然是模块
方式一:
import 包名.模块名
包名.模块名.目标
import my_package.my_module1
import my_package.my_module2
my_package.my_module1.info_print1()
my_package.my_module2.info_print()
方式二:
from 包名(模块名) import 模块(功能)
from my_package import my_module1
from my_package import my_module2
my_module1.info_print1()
my_module2.info_print()
from my_package.my_module1 import info_print1
from my_package.my_module2 import info_print
info_print1()
info_print()
然后这个时候我们的__all__ = [模块]就可以写在那个自动生成的模块里了
从来控制import *的功能
如何安装第三方包:
第三方包就是非python官方的包,需要我们手动导入
pip程序:
pip install(默认连接的是国外的)

连接国内的:
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple 包的名称

检验我们是否安装成功

DAY11:python基础综合案例:数据可视化——折线图可视化
JSON:
什么是json?
json是一种轻量级的数据交互格式。可以按照json指定的格式去组织和封装数据
json本质上是一个带有特定格式的字符串
主要功能:json就是一种在各个编程语言中流通的数据格式,负责不同编程语言中的数据传递和交互。
(不同语言之间的中转站)

是python的字典或者是列表(嵌套字典)

dumps(data):把python数据转换为json数据
loads(data):把json数据转换为python数据
import json
#准备列表,列表中每一个元素都是字典,将其转换为json
data = [{"name":"张三","age":13},{"name":"王五","age":16},{"name":"李四","age":19}]
json_str = json.dumps(data)
print(json_str)
print(type(json_str))

我们发现中文内容被编码了
import json
#准备列表,列表中每一个元素都是字典,将其转换为json
data = [{"name":"张三","age":13},{"name":"王五","age":16},{"name":"李四","age":19}]
json_str = json.dumps(data,ensure_ascii=False)
print(json_str)
print(type(json_str))
ensure_ascii=False
就可以使中文正常输出了(我们不用ascii码去转换它,而是直接的输出)

import json
#准备列表,列表中每一个元素都是字典,将其转换为json
data = [{"name":"张三","age":13},{"name":"王五","age":16},{"name":"李四","age":19}]
json_str = json.dumps(data,ensure_ascii=False)
print(json_str)
print(type(json_str))
s = '[{"name":"张三","age":13},{"name":"王五","age":16},{"name":"李四","age":19}]'
l = json.loads(s)
print(l)
print(type(l))
这个是转换成列表
JSON 格式规范:JSON 数据的最外层必须是单个值(要么是 {} 包裹的对象,要么是 [] 包裹的数组,不能是多个对象直接用逗号拼接)。一个列表或者是一个字典
import json
#准备列表,列表中每一个元素都是字典,将其转换为json
data = [{"name":"张三","age":13},{"name":"王五","age":16},{"name":"李四","age":19}]
json_str = json.dumps(data,ensure_ascii=False)
print(json_str)
print(type(json_str))
s = '[{"name":"张三","age":13},{"name":"王五","age":16},{"name":"李四","age":19}]'
l = json.loads(s)
print(l)
print(type(l))
s = '{"name":"张三","age":13}'
d = json.loads(s)
print(d)
print(type(d))
pyecharts模块介绍
帮助做出数据可视化效果图
pyecharts - A Python Echarts Plotting Library built with love.
基础折线图:
#导包,导入Line功能构建折线图对象
from pyecharts.charts import Line
#得到折线图对象
line = Line()
#添加x轴的数据
line.add_xaxis(["中国","美国","英国"])
#添加y轴的数据
line.add_yaxis("GDP",[30,20,10])
#生成图表
line.render()

全局配置选项:
set_global_opts方法

系列配置选项:
数据处理:
DAY12对象
对象
1、设计类
#设计一个类(类比生活中的设计一张登记表)
class Student:
name = None#记录学生姓名
gender = None#记录学生的性别
nationality = None#记录学生的国籍
native_place = None#记录学生的籍贯
age = None#记录学生的年龄
2、创建对象
#创建一个对象(打印一张登记表)
stu_1 = Student()
3、对象属性赋值
#对象属性进行赋值
stu_1.name = "小张"
stu_1.gender = "男"
stu_1.nationality = "中国"
stu_1.native_place = "山东"
stu_1.age = 18
4.获取对象中的数据
#获取对象中记录的信息
print(stu_1.name)
print(stu_1.gender)
print(stu_1.nationality)
print(stu_1.native_place)
print(stu_1.age)
成员变量
类的定义和使用:
我们可以用类去封装属性,并基于类创建出一个个的对象来使用。
类的使用语法:
class 类名称:
类的属性(成员变量)
类的行为(成员方法)
创建类对象的语法
对象 = 类名称()
方法:类内部的函数
成员方法语法:
def 方法名(self,形参1,。。。。。。。,形参N):
方法体
self:
- 它用来表示类对象自身的意思
- 当我们使用类对象调用方法的时候,self会自动被python传入
- 在方法内部,想要访问类的成员变量,必须使用self
注意:
想要访问成员属性,必须使用self中国关键字
#定义一个带有成员方法的类
class Student:
name = None#学生的姓名
def say_hi(self):
print(f"大家好!我是{self.name},请大家多多关照")
def say_hi2(self,msg):
print(f"大家好!我是{self.name},{msg}请大家多多关照")
stu = Student()
stu.name = "小李"
stu.say_hi2("hhh")
stu1 = Student()
stu1.name = "小林"
stu1.say_hi2("aaaaaaaa")

类和对象:
面向对象编程:
类只是一种程序内的“设计图纸”,需要基于图纸生产实体(对象),才能正常工作
class Clock:
id = None
price = None
def ring(self):
import winsound
print(f"id = {self.id}, price = {self.price}")
winsound.Beep(68,3000)
clock1 = Clock()
clock1.id = 121212
clock1.price = 1111111
clock1.ring()
(代码的声音很友好,不必害怕)
构造方法:
python类可以使用:__init__()方法,称之为构造方法
可以实现:
- 在创建类对象(构造类)的时候,会自动执行
- 在创建类对象(构造类)的时候,将传入参数自动传递给__init__方法使用
class Student:
#下面三行可以省略
name = None
age = None
tel = None
def __init__(self,name,age,tel):
self.name = name
self.age = age
self.tel = tel
print(f"Student创建了一个对象名字是{name},年龄是{age},电话号码是{tel}")
stu1 = Student("小明",77,13812676898)
class Student:
def __init__(self,name,age,tel):
self.name = name
self.age = age
self.tel = tel
print(f"Student创建了一个对象名字是{name},年龄是{age},电话号码是{tel}")
stu1 = Student("小明",77,13812676898)
其他内置方法:(魔术方法)
如__init__构造方法,是python类内置方法之一
这些内置的类方法,各自有各自特殊的功能,这些内置方法我们称之为:魔术方法
__str__:字符串方法
当对象需要被转换为字符串之时,会输出如上结果(内存地址)
class Student:
def __init__(self,name,age):
self.name = name
self.age = age
# __str__魔术方法
def __str__(self):
return f"Student类对象,name:{self.name},age:{self.age}"
student = Student("小周",44)
print(student)#不写str魔术方法结果<__main__.Student object at 0x00000214C4E7F620>
print(str(student))#不写str魔术方法结果<__main__.Student object at 0x00000214C4E7F620>
#Student类对象,name:小周,age:44
#Student类对象,name:小周,age:44
__lt_:小于、大于符号比较
class Student:
def __init__(self,name,age):
self.name = name
self.age = age
# __str__魔术方法
def __str__(self):
return f"Student类对象,name:{self.name},age:{self.age}"
# __lt__魔术方法
def __lt__(self, other):
return self.age < other.age
student = Student("小周",66)
student1 = Student("大明",33)
print(student < student1)#False
print(student > student1)#True
__le__:小于等于、大于等于符号比较
class Student:
def __init__(self,name,age):
self.name = name
self.age = age
# __str__魔术方法
def __str__(self):
return f"Student类对象,name:{self.name},age:{self.age}"
# __lt__魔术方法
def __lt__(self, other):
return self.age < other.age
#__le__魔术方法
def __le__(self, other):
return self.age <= other.age
student = Student("小周",66)
student1 = Student("大明",33)
print(student <= student1)#False
print(student >= student1)#True
__eq__: ==符号比较
class Student:
def __init__(self,name,age):
self.name = name
self.age = age
# __str__魔术方法
def __str__(self):
return f"Student类对象,name:{self.name},age:{self.age}"
# __lt__魔术方法
def __lt__(self, other):
return self.age < other.age
#__le__魔术方法
def __le__(self, other):
return self.age <= other.age
#__eq__魔术方法
def __eq__(self, other):
return self.age == other.age
student = Student("小周",66)
student1 = Student("大明",33)
print(student <= student1)#False
print(student >= student1)#True
print(student == student1)#False(默认比较内存地址)
面向对象的三大特性:
封装:
私有成员:
既然现实事物有不公开的属性和行为,那么作为现实世界在程序中映射的类,也应该支持
定义私有成员方法的方式:
- 私有成员变量:变量名以__开头(2个下划线)
- 私有成员方法:方法名以__开头(2个下划线)
class Phone:
__current_voltage = None#当前手机运行电压
def __keep_single_core(self):
print("让cpu单核模式运行")
phone = Phone()
phone.__keep_single_core()
print(__current_voltage)

通过对象来调用私有的方法,私有的变量都会报错
类的对象不能使用,但是类中的其他成员可以使用
class Phone:
__current_voltage = 5#当前手机运行电压
def __keep_single_core(self):
print("让cpu单核模式运行")
def call_by_5g(self):
if self.__current_voltage >= 1:
print("5g通话开启")
else:
self.__keep_single_core()
phone = Phone()
phone.call_by_5g()
继承:
继承就是把之前老的类里面的功能继续拿来用
在定义类的时候把老的类放在括号里
语法:
class 类名(父类名):
类内容体
被继承的类:父类
继承别人的类:子类
单继承:
一个子类继承单个父类
class Phone:
IMEI = None #序列号
producer = "XM"
def call_by_4g(self):
print("支持4g通话了")
class Phone2022(Phone):
face_id = "10001"
def call_by_5g(self):
print("2022年新功能支持5g")
phone = Phone2022()
print(phone.producer)
phone.call_by_4g()
phone.call_by_5g()
多继承:
一个子类继承多个父类
语法:
class 类名(父类1,父类2,父类3.。。。。):
类的内容
class Phone:
IMEI = None #序列号
producer = "XM"
def call_by_4g(self):
print("支持4g通话了")
class NFCReader:
nfc_type = "第五代"
producer = "xm"
def read_card(self):
print("NFC读卡")
def write_card(self):
print("NFC写卡")
class RemoteControl:
rc_type = "红外遥控"
def control(self):
print("红外遥控开启了")
class MyPhone(Phone,NFCReader,RemoteControl):
pass#表示空的
phone = MyPhone()
phone.call_by_4g()
phone.read_card()
phone.write_card()
phone.control()
注意:
输出同名属性时,左边的优先(谁先来的谁优先级高)
复写和使用父类成员:
复写:
子类继承父类的成员属性和成员方法之后,如果对其“不满意”,那么可以进行复写/
即:在子类中重新定义重名的属性或方法
class Phone:
IMEI = None
producer = "xm"
def call_by_5g(self):
print("5g")
class MyPhone(Phone):
producer = "dm"
def call_by_5g(self):
print("cpu单核")
print("5g")
myPhone = MyPhone()
myPhone.call_by_5g()
print(myPhone.producer)
调用父类的成员:
方式1:
父类名.成员变量
父类名.成员方法(self)
方式2:
super().成员变量
super().成员方法()
class Phone:
IMEI = None
producer = "xm"
def call_by_5g(self):
print("5g")
class MyPhone(Phone):
producer = "dm"
def call_by_5g(self):
print("cpu单核")
#super().call_by_5g()
Phone.call_by_5g(self)
myPhone = MyPhone()
myPhone.call_by_5g()
print(myPhone.producer)
类型注解:
为什么内置模块的方法可以提示类型
自己定义的就不行
因为pycharm无法通过代码确定应该传入什么类型
在代码中涉及数据交互的地方,提供数据类型的注解(显式的说明)
功能:
- 帮助第三方IDE工具对代码进行类型推断,协助做代码提示
- 帮助开发者自身对变量进行类型注释
支持:
- 变量的类型注解
- 函数(方法)形参列表和返回值的类型注解
注意:
类型注解仅仅是个备注,写错了也不会影响代码的运行
变量的类型注解:
语法:
变量:类型
#基础数据类型注解
var_1: int = 10
var_2: str = 'hello'
var_3: bool = True
类对象类型注解
class Student:
pass
stu: Student = Student()
#基础容器类型注解
my_list:list = [1,2,3]
my_tuple: tuple = (1,"dadada",True)
my_dict: dict = {'a':1,'b':2,'c':3}
#容器类型详细注解
my_list:list[int] = [1,2,3]
my_tuple: tuple[int,str,bool] = (1,"dadada",True)
my_dict: dict[str,int] = {'a':1,'b':2,'c':3}
#在注释中进行类型注解
var_1 = random.randint(1,10) #type: int
var_2 = json.loads('{"a":1,"b":2,"c":3}') #type:dict[str,int]
def func():
return 10
var_3 = func() #type:int
函数(方法)的类型注解-形参注解:
语法:
def 函数方法名(形参名:类型,形参名:类型):
pass
#对形参进行类型注解
def add(x: int,y: int):
return x+y
add(1,2)

函数(方法)的类型注解-返回值注解:
语法:
def 函数方法名(形参:类型,。。。。。,形参:类型)->返回值类型:
pass
#对返回值注解
def func(data:list) -> list:
return data
都是建议性的不是强制性的
Union类型:
语法:
Union[类型,。。。。。。。类型]
可以定义联合类型注解


from typing import Union
my_list: list[Union[int,str]] = [1,2,"dadad","dadadv"]
def func(data:Union[int,str]) -> Union[int,str]:
pass
func()
多态:
多种状态,即完成某个行为时,使用不同的对象会得到不同的状态
- 以父类做定义声明
- 以子类做实际工作
- 用以获得同一行为,不同状态
class Animal:
def speak(self):
pass
class Dog(Animal):
def speak(self):
print("汪汪汪")
class Cat(Animal):
def speak(self):
print("喵喵喵")
def make_noise(animal:Animal):
animal.speak()
dog = Dog()
cat = Cat()
make_noise(dog)
make_noise(cat)
父类方法pass的含义:
- 父类来确定有哪些方法
- 具体的方法实现,由子类自行决定
这种写法,就叫做抽象类(也称为接口)
抽象类:含有抽象方法的类就叫做抽象类
抽象方法:方法体是空实现的(pass)称之为抽象方法
抽象类:
提出标准,具体怎么做要子类去实现
DAY13
SQL入门和实战:
数据库:
库-表-数据
sql语言就是一种对数据库、数据进行操作、管理、查询的工具。
MySQL安装:
MySQL的入门使用:
- show databases ;查看有哪些数据库
- use 数据库名 使用某个数据库
- show tables 查看数据库内有哪些表
- exit退出MySQL的命令行环境


使用MySQL图形化工具
DBeaver Community | Free Open-Source Database Management Tool
DAY14:
SQL基础与DDL:
SQL:结构化查询语言,用于访问和处理数据库的标准的计算机语言
就是操作数据库的工具
SQL的特点:
- 大小写不敏感
- SQL语句以分号结尾(可以多行书写,最后有分号就行)
- SQL支持注释:单行注释:-- 注释内容(--后面要有个空格) 单行注释:# 注释内容(#后面可以不加空格,推荐加上) 多行注释:/* 注释内容*/

数据定义:DDL-库管理:
查看数据库:
show databases;
使用数据库:
use 数据库;
创建数据库:
create database 数据库名称 [charset utf8];(中括号的意思就是可写也可以不写,默认就为utf8)
删除数据库:
drop database 数据库名称;
查看当前使用的数据库:
select database();

DDL-表管理:
查看有哪些表:
show tables;
注意:
要先选择数据库
删除表:
drop table 表名称;
drop table if exits 表名称;
创建表:
create table 表名称(
列名称 列类型,
列名称 列类型,
。。。。。。。
);
列表类型有:
- int 整数
- float 浮点数
- varchar(长度) 文本,长度为数字,做最大长度限制
- date 日期类型
- timestamp 时间戳类型


SQL-DML
数据操作语言:
插入insert
insert into 表[(列1,列2,。。。。。,列N)] values(值1,值2,。。。。。,值N)
【(值1,值2 ,值。。。。。值N),。。。。。,(值1,值2,。。。。。,值N)】
当给表内所有的列传值时,可以不写各个列,直接写值,但是顺序要对应

删除delete
delete from 表名称 [where 条件判断]
条件判断:
- = < > <= >= !=

更新update
update 表名 set 列 = 值 [where 条件判断];
![]()
SQL-DQL:
数据查询:
select 字段列表 |* from 表

过滤:
select 字段列表|* from 表 where 条件判断

分组聚合查询:
先按照某项要求分组,然后统计每个组内的人数
语法:
select 字段 | 聚合函数 from 表 [where 条件 ] group by 列
聚合函数:
- sum求和
- avg 求平均值
- min求最小值
- max求最大值
- count 求数量(数条)
![]()
在非聚合函数中group by后面出现谁,前面select才能有谁
排序和分页:
结果排序:
select 列|聚合函数|* from 表
where 。。。
group by 。。。
order by 。。。(列) [asc|desc]
limit n[,m]
n:限制几条
n,m:从第n条开始,取m条
asc:升序(默认)
desc:降序
python来操作MYSQL:
from pymysql import Connection
#构建到MySQL数据库的连接
conn = Connection(
host='localhost',#主机名(IP)
port=3306,#端口
user='root',#账户
password="mysql"#密码
)
print(conn.get_host_info())
print(conn.get_server_info())
#执行非查询性质的sql
cursor = conn.cursor() #获取游标对象
#选择数据库
conn.select_db('sys')
#执行操作(通过游标对象)
#cursor.execute("create table if not exists py_student(id int);")
#执行sql
cursor.execute('select * from student')
result = cursor.fetchall()
print(result)
DAY15:python的一些高阶技巧
闭包:
在函数嵌套的前提下,内部函数使用了外部函数的变量,并且外部函数返回了内部函数,我们把这个使用外部函数变量的内部函数称为闭包。(这样某些全局变量就不会被篡改了)
#简单闭包
def outer(logo):
def inner(msg):
print(f"{logo}{msg}{logo}")
return inner
fn1 = outer("你好")
fn1("小明")
让fn1=outer的返回值inner函数,fn1就相当于inner函数,使用fn1传参就只会调用inner,不改变logo,如果想改变,就只能通过改变inner的执行语句来改变
在内部函数中修改外部函数的值:
正常情况下,我们在内部函数里面想直接对外部函数的值赋值时是不被允许的
#使用nonlocal关键字修改外部函数的值
def outer(num1):
def inner(num2):
nonlocal num1
num1 += num2
print(num1)
return inner
fn = outer(10)
fn(20)
fn(20)
fn(20)
ATM小案例方便理解:
#使用闭包实现ATM小案例
def account_creat(initial_amount = 0):#这里就是我们的余额
def atm(num,deposit = True):
nonlocal initial_amount
if deposit:
initial_amount += num
print(f"存款:+{num},余额还剩{initial_amount}")
else:
initial_amount -= num
print(f"存款:-{num},余额还剩{initial_amount}")
return atm
atm = account_creat()
atm(500)
atm(100,False)

这个闭包的目的,
准确的说: 是为避免在"本次"函数执行中, 有外部模块修改amount
优点:
- 无需定义全局变量即可实现通过函数,持续的访问、修改某个值
- 闭包使用的变量的所用于在函数内,难以被错误的调用而修改
缺点:
- 由于内部函数持续引用外部函数的值,所以会导致这一部分内存空间不被释放,一直占用内存
三、关键差异:闭包 vs 类对象
- 语法形态
- 闭包:本质是函数嵌套 + 变量捕获 + 返回内层函数,最终是一个 “函数”。
- 对象:是类的实例,本质是数据(属性)+ 方法(行为)的集合。
- 状态管理
- 闭包:只能捕获外层函数的变量,状态封装在函数作用域里。
- 对象:可以定义多个属性(
self.xxx),状态封装在实例命名空间里,更灵活。
- 功能边界
- 闭包:通常只提供单一功能(示例中只有
print这一个行为)。 - 对象:可以定义多个方法,实现复杂的多行为逻辑。
- 闭包:通常只提供单一功能(示例中只有
- 设计思想
- 闭包:函数式编程思想,强调 “函数作为一等公民”,用函数封装状态和行为。
- 对象:面向对象编程思想,强调 “封装、继承、多态”,用类抽象事物。
四、核心差异:为什么不能完全取代?
我们用 “场景适配性” 来拆解,你会更清楚两者的不可替代性:
| 维度 | 闭包(函数式) | 类(面向对象) |
|---|---|---|
| 代码轻量化 | 实现简单逻辑时,几行代码就能完成(如示例) | 必须定义类、__init__、方法,代码量翻倍 |
| 临时 / 一次性逻辑 | 用完即弃,无需定义 “类” 这个 “模板” | 即使只用一次,也需先定义类,冗余且没必要 |
| 函数作为返回值 | 天生支持:外层函数返回内层函数,可直接调用 | 需返回对象 + 调用方法,多一层 “对象” 的包裹 |
| 闭包的 “隐藏状态” | 状态(如logo)隐藏在函数作用域,外部不可见 | 状态(如self.logo)是对象属性,可被修改 |
| 适用场景 | 简单的状态封装、函数装饰器、回调函数 | 复杂的多属 |
装饰器
装饰器其实也是一种闭包,其功能就是在不破坏目标函数原有的代码和功能的前提下,为目标函数增加新功能。
装饰器的一般写法(闭包)
def sleep():
import random
import time
print("睡眠中")
time.sleep(random.randint(1,5))
#装饰器的一般写法
def outer(func):
def inner():
print("睡着了")
func()
print("起床了")
return inner
fn1 = outer(sleep)
fn1()
装饰器的语法糖写法:
#装饰器的语法糖写法
def outer(func):
def inner():
print("我睡觉了")
func()
print("我起床了")
return inner
@outer
def sleep():
import time
import random
print("睡眠中")
time.sleep(random.randint(1, 7))
sleep()
当我们使用语法糖写法的时候,我们在目标函数的前面增加一个@outer,再后面调用这个目标函数的时候其功能就会发生变化
设计模式:
最常见、最经典的设计模式,就是我们所学习的面向对象。
单例模式:
定义:保证一个类只有一个实例,并提供一个访问它的全局访问点
适用场景: 当一个类只能有一个实例,而客户可以从一个众所周知的访问点访问它

我们正常情况下创建两个对象是完全不同的两个对象(由图中输出的地址可以看出)
class StrTools():
pass
strTools = StrTools()
from str_tools_py import strTools
s1 = strTools
s2 = strTools
print(s1)
print(s2)

当我们使用单例模式时,无论创建多少个对象最终都是一个相同的对象
(由图中的地址可见)
好处:
- 节省内存
- 节省创建对象的开销
工厂模式:
当需要大量创建一个类的实例的时候,可以使用工厂模式。
即,从原生的使用类的构造去创建对象的形式
迁移到,基于工厂提供的方法去创建对象的形式。
class Person:
pass
class Worker(Person):
pass
class Student(Person):
pass
class Teacher(Person):
pass
class PersonFactory:
def get_person(self,p_type):
if p_type == 'w':
return Worker()
elif p_type == 's':
return Student()
else:
return Teacher()
person = PersonFactory()
worker = person.get_person('w')
student = person.get_person('s')
teacher = person.get_person('t')
在 Python 中,实例方法(也就是你定义在类里的普通方法)的第一个参数必须是 self(这个名字只是约定俗成,你也可以用其他名字,但强烈不建议),它的核心作用是:
- 指向当前类的实例对象本身
- 让方法能够访问和操作该实例的属性、调用该实例的其他方法
当类的名字发生变化时,如果想之前的写法需要一个一个改名称,但如果是工厂模式下,只需要改一下实例方法
多线程:
进程、线程和并性执行:
进程:就是一个程序,运行在系统之上,那么便称这个程序为一个运行进程,并且分配进程id方便系统管理
线程:线程是归属于进程的,一个进程可以开启多个线程,执行不同的工作,是进程的实际工作最小单位
操作系统中可以运行多个进程,即多任务运行
一个进程内可以运行多个线程,即多线程运行
注意:
进程之间的内存是隔离的,即不同的进程拥有各自的内存空间。
线程之间是内存共享的,线程是属于进程的,一个进程内的多个线程之间是共享这个进程所拥有的内存空间的。
并行执行:
并行执行的是指的是同一时间做不同的工作。
进程之间是并行执行的,操作系统可以同时运行好多程序,这些程序都是在并行执行。
除了进程外,线程其实也可以并行执行:
一个程序在同一时间做两件/更多的事情,我们就称之为:多线程并行执行
并发:
指多个线程对应的多条指令被快速轮回的执行
并行:
指同一时刻有多条指令在多个处理器上同步执行
多线程编程:
threading模块

import time
import threading
def sing():
while True:
print("我在唱歌,啦啦啦啦")
time.sleep(1)
def dance():
while True:
print("我在跳舞,呱呱呱")
time.sleep(1)
if __name__ == '__main__':
#创建一个唱歌的线程
sing_thread = threading.Thread(target=sing)
#创建一个跳舞的线程
dance_thread = threading.Thread(target=dance)
sing_thread.start()
dance_thread.start()
网络编程
Socket:
socket(简称 套接字)是进程之间通信一个工具,好比现实生活中的插座,所有的家用电器要想工作都是基于插座进行
进程之间想要进行网络通信需要socket
Socket服务端:等待其他进程的连接、可接受发来的消息、可以回复消息
Socket客户端:主动连接服务端、可以发送消息、可以接收回复
Socket服务端编程:


import socket
#创建Socket对象
socket_server = socket.socket()
#绑定IP地址和端口
socket_server.bind(("localhost", 8888))#bind要传入的是一个元组
#监听端口
socket_server.listen(1)#listen方法内接受一个整数传参,表示接受的链接数量
#等待客户端的链接
# result:tuple = socket_server.accept()
# conn = result[0]#客户端和服务端的链接对象
# address = result[1]#客户端的地址信息
conn, addr = socket_server.accept()
#accept方法返回的是二元元组(链接对象,客户端地址信息)
#可以通过变量1,变量2 = socket_server.accept()的形式,直接接受二元元组的两个元素
#accept()方法,是阻塞方法,等待客户端的链接,如果没有链接,就卡在这一行,不向下执行
print(f"接受到了客户端的链接,客户端的信息是:{addr}")
#接受客户端的信息,要使用客户端和服务端的本次链接对象,而非socket_server对象
while True:
data:str = conn.recv(1024).decode("utf-8")
#recv接受的参数是缓冲区大小,一般用1024
#recv方法的返回值是一个字节数组,即bytes对象,不是字符串,可以通过decode方法来编码,将字节数组转化成字符串对象
print(f"客户端发来的消息是:{data}")
#发送回复信息
msg = input("请输入你要回复客户端的消息")
if msg == "exit":
break
#encode可以将字符串编码成字节数组对象
conn.send(msg.encode("utf-8"))
#关闭链接
conn.close()
socket_server.close()
正则表达式

# import re
#
# s = '22python dapython dwadpythondbuaihdwuihduiahudaiudha'
# #match是从头开始匹配
# # result = re.match("python",s)
# # print(result)
# # print(result.span())
# # print(result.group())
# #search找到匹配项,从前往后,找到第一个之后就停止
# # result = re.search('python',s)
# # print(result)
# result = re.findall('python',s)
# print(result)




1497

被折叠的 条评论
为什么被折叠?



