python基础语法
前言#
语言:Python(python==3.9)
编译软件:VScode、PyCharm
环境:Anaconda
一、Python注释和输入输出#
注释分为单行注释,多行注释,被注释的代码不会运行,快捷键:选中代码+Ctrl+/
主要功能有:
1.对代码进行注释,方便进行理解
2.对代码进行禁用
1.单行注释#
# 单行注释
# 我是一个注释 不是运行的代码 写代码的时候:Ctrl+/
# print("hello")
print(123)**运行结果:**123
2.多行注释#
"""
三引号
引号内代码都注释
随便写多少行
"""
print("hello")**运行结果:**hello
3.输入和输出#
# 输出
print("打印文本")
print("打印数字:",123)
print("文本1","文本2","文本3",sep = "-")
print("文本1",end = "\n")
print("文本2",end = "123")
print("文本3",end = "\n")运行结果:
打印文本 打印数字: 123 文本1-文本2-文本3 文本1 文本2123文本3
# 输入
print(123)
x = input("打印到控制台,让程序暂停,等待用户输入")
print(x)
print(456)运行结果:
123 444(将在控制台显示“打印到控制台,让程序暂停,等待用户输入”,等到用户输入后再运行下面的程序,这里输入444,输出444) 456
二、变量#
什么是变量:用一个简短的名称来代替数据的使用
1.数值#
a = 100
print(a)
print(100)2.字符串#
b = "我是一个字符串"
# 声明了一个变量,名字叫b,后面程序运行时可以直接用b来表示
print(b)3.变量名称的要求#
一般场景下必须使用变量来保存数据,如果不需要使用到的数据需要接收,则用下划线“_”表示变量名
x = 123
y = "nihao"
_ = 200
print(x,y,_)变量名字必须是连续的字母,下划线,数字的组合。错误的命名方法:first name = "123"
firstname = "123123" #不会报错,但是不方便阅读数字不可以作为变量名的开头,变量名严格区分大小写Name和name是两个不同的变量
1app_version = "1.1.0"
print(1app_version)官方提供的关键字不可以作为变量名
True = 10中文作为变量名?可以,只要是Unicode编码符合的字符都可以作为变量名,一般约定用英文或者拼音字母而不用汉字
华清远见 = "华清远见成都分中心在西南交大地铁站旁"
print(华清远见)常把大写字母的变量名作为不改变的常量使用
PI = 3.141594.变量名命名规则#
三种写法:
1.小驼峰:huaQingYuanJian
2.大驼峰:AppVersion
3.匈牙利命名法(比较常用):ai_first_class_1
三、变量的赋值与取值#
1.数据直接量#
x = 100
x_2 = "hello"
#取出变量中的数据并打印
print(x)2.表达式#
x_3 = x
print(x_3)3.多变量一起赋值#
a = b = c = 100
print(a,b,c)4.解构赋值#
w,m,n = 100,10,1
print(w,m,n)5.变量的取值#
x = 10
x = 1#此时x最后被更新为1
print(x)#必须要等打印出来过后才执行后续的代码
x1 = 10
x2 = 20
x3 = 30
c = 666,x1,x2,x3
print(c)
x1,a,b,c= 666,x1,x2,x3
print(x1,a,b,c)
# 交换两个数据的取值
x1 = 10
x2 = 20
x1,x2 = x2,x1#x1<--x2,x2<--x1同时发生,优先级:先取值后赋值 生成一个元祖(x2,x1)==>(20,10)==>(x1,x2)
print(x1,x2)四、字符串#
1.字符串的写法#
x_1 = "我是一个字符串"
x_2 = ""#空字符串
x_3 = " "#空格也是字符串
print(type(x_2))x1 = "hello"
x2 = "hi"
x3 = """三引号也可以是字符串
可以随意换行
自带换行符
"""
print(x3)运行结果:
三引号也可以是字符串 可以随意换行 自带换行符
2.转义字符#
x1 = "我爱我的祖国和我的家乡\"四川\""
print(x1)
x2 = '我爱我的祖国和我的家乡\'四川\''
print(x2)
x3 = "我爱我的祖国和我的家乡'四川'"
print(x3)
x4 = "你好:\n 欢迎你"
print(x4)
x5 = "abcd\\efg\\hi"
print(x5)
x6 = "abc\tdef\tghi"
print(x6)
x7 = r"D:\桌面\华清\3.8\code\06-字符串.ipynb"#在字符串之前加r,表示\不转义
print(x7)运行结果:
我爱我的祖国和我的家乡"四川" 我爱我的祖国和我的家乡'四川' 我爱我的祖国和我的家乡'四川' 你好: 欢迎你 abcd\efg\hi abc def ghi D:\桌面\华清\3.8\code\06-字符串.ipynb
3.字符串常用运算操作#
加号:
x1 = "华清远见"
x2 = "成都分中心"
str_1 = x1 + x2
print(str)x3 = "我的年龄是:"
x4 = "18"
str_2 = x3 + x4#只能字符串和字符串进行连接,两个变量的类型不匹配则不能拼接
print(str_2)
x5 = '华清''远见''666'#多个字符串靠在一起自动变成一个字符串
print(x5)乘号:
# 乘号
x6 = "abc"
str_3 = x6*3
print(str_3)运行结果:
华清远见成都分中心 我的年龄是:18 华清远见666 abcabcabc
等号:(严格区分大小写)
x1 = "abc"
x2 = "Abc"
print(x1==x2)运行结果:
False
4.访问子串#
x7 = "华清远见成都分中心"
xx_7 = x7[0]
print(xx_7)
xx_77 = x7[-1]
print(xx_77)
xx__77 = x7[2:10:2]#切片,左闭右开,第三个数字代表每两个选中
print(xx__77)
xx__78 = x7[::2]
print(xx__78)
xx__79 = x7[:6:2]
print(xx__79)
xx__70 = x7[-1:6:2]
print(xx__70)
xx__74 = x7[9:3:-1]
print(xx__74)运行结果:
华 心 远成分心 华远成分心 华远成
心中分都成
比较常用的三个:
xx__71 = x7[::-1]
print(xx__71)
xx__72 = x7[:-1]
print(xx__72)
xx__73 = x7[-1]
print(xx__73)运行结果:
心中分都成见远清华 华清远见成都分中 心
5.输入一个字符串,判断是否回文#
x1 = input("请输入字符串")# 这里输入:上海自来水来自海上
x2 = x1[::-1]
print(x1==x2)**运行结果:**True
6.判断一个字符串是否为另一个字符串的子串#
x1 = "abcdefg"
x2 = "ab"
x3 = "gh"
print(x1 in x2)
print(x3 in x1)
print(x3 not in x1)运行结果:
False False True
7.查看字符串字符数量(长度)#
x1 = "abc"
n = len(x1)
print(n)**运行结果:**3
8.常见占位符#
占位符和类型码
| 占位符和类型码 | 说明 |
| :------------: | ------------------------------------------------------------ |
| %s | 转成字符串, 使用 str(x) 函数转换(常用) |
| %d | 转成十进制的整数(常用) |
| %o | 转成八进制的整数 |
| %x,%X | 转成十六进制的整数 |
| %e,%E | 转成指数格式的浮点数 |
| %f,%F | 转成小数格式的浮点数(常用) |
| %g,%G | 转成指数格式或小数格式的浮点数 |
| %% | 转成一个% |
| %m.nf | m是指总宽度,默认右对齐,加个 - 表示左对齐,n 是指保留的小数点位数 |9.字符串格式化表达式#
常用来在训练自己的神经网络模型时,控制台查看数据情况
x1 = "我叫%s今年%d岁"%("jack",23)
print(x1)
# 保留小数位数
x2 = "精确度是%.2f"%(100)
print(x2)
# 总宽度
x3 = "精确度是%50.3f"%(100)
print(x3)
# 进制转换
x4 = "十六进制的值是%x"%(11)
print(x4)
# 科学计数法
x5 = "科学计数法表示为%g"%(1000000000)
print(x5)运行结果:
我叫jack今年23岁 精确度是100.00 精确度是 100.000 十六进制的值是b 科学计数法表示为1e+09
10.另外一种格式化字符串的方式#
r = 144
g = 127
b = 255
x1 = "rgb(144,127,255)"
x2 = f"rgb({r},{g},{b})"
print(x1)
print(x2)运行结果:
rgb(144,127,255) rgb(144,127,255)
11.字符串常用的一些API(别人写的一些函数,可以直接调用)#
# 将字母全部转换为小写
text = "HELLO world"
text2 = text.lower()
print(text2)
# 将字母全部转换为大写
text3 = text.upper()
print(text3)
# 首字母大写
text4 = text.capitalize()
print(text4)
# 去除两边空白字符
text = " 1825648 "
text5 = text.strip()
print(text5)
# 将字符串分割成列表(默认是空格)
text = "hello my name is jack"
text6 = text.split()
print(text6)
# 综合使用
text = "http://www.hqyj.com/index.html?user_id=123&user_name=jack&count=20"
text7 = text.split("?")[0]
print(text7)
text8 = text.split("?")[1].split("&")[1].split("=")[1]
print(text8)
# 连接字符串
text = ['hello', 'my', 'name', 'is', 'jack']
text9 = "-".join(text)
print(text9)
# 字符串替换
text = "你好,我叫李华"
text0 = text.replace("李华","李雷")
print(text0)
# 查找特定字符
text = "hello,my name is lihua"
text11 = text.find("lihua",19)#第二个参数代表起始下标,返回-1表示未查找到
print(text11)
# 检查字符串是否以指定字符串开头
text = "std = 1"
text12 = text.startswith("std")
print(text12)
# 检查字符串是否以指定字符串结尾,返回布尔类型
text = "std = 1,name"
text13 = text.endswith("name")
print(text13)
# 是否全是数字
text = "1600"
text14 = text.isdigit()
print(text14)
# 是否只包含字母
text = "1600yuan"
text15 = text.isalpha()
print(text15)
# 是否只包含字母和数字字符
text = " price = 1600_yuan"
text16 = text.isalnum()
print(text16)
# 将字符串内每个单词首字母转变为大写
text17 = text.title()
print(text17)
# 将字符串首字母转变为大写
text18 = text.capitalize()
print(text18)
# 统计词频
text = "Hello, World! Hello, Python!"
text19 = text.count("Hello")
print(text19)
# 格式化字符串
name = "jack"
age = 18
text20 = f"my name is {name}, i am {age} year old"
print(text20)运行结果:
hello world HELLO WORLD Hello world 1825648 ['hello', 'my', 'name', 'is', 'jack'] http://www.hqyj.com/index.html jack hello-my-name-is-jack 你好,我叫李雷 -1 True False True False False Price = 1600_Yuan price = 1600_yuan 2 my name is jack, i am 18 year old False
五、数值型#
1.进制#
十进制
x = 10八进制,打印默认转化为十进制数
y = 0o100
print(y)十六进制
z = 0xD1BfD
print(z)二进制
m = 0b1010001
print(m)运行结果:
64 859133 81
2.浮点数与科学计数法#
x = 1.0
y = 2.
z = .6
# 科学计数法
x = 1e6
y = 2e03#0没有任何作用
z = 3e-3
import math
PI = math.pi
PI3.数字类型转换#
x = 6
x1 = bin(x)
x2 = oct(x)
x3 = hex(x)
x4 = float(x)
x5 = complex(x)
x = 3.0
x6 = int(x)
print(x1,x2,x3,x4,x5,x6)math.ceil(x)函数返回大于或等于x的最小整数。 math.floor(x)函数返回小于或等于x的最大整数。
print(math.ceil(3.14))
print(math.floor(3.94))运行结果:
0b110 0o6 0x6 6.0 (6+0j) 3 4 3
4.布尔类型#
x = 0
print(bool(x))
y = ""
print(bool(y))
z = "0"
print(bool(z))
# 空的集合,列表,字符串都是True
print(10<20)运行结果:
False False True True
5.字节串和空值#
# 字节串
text = b"hello"
print(type(text))
# 空值
x = None#表示没有
print(x)六、列表#
1.字面量#
x = []
print(type(x))
x = [1, 2, 3, 4, 5]
print(x)
x = [1, 2, [3,4]]
print(x)2.通过构造函数来创建列表#
x = list()
print(x)3.list函数可以传入一个可迭代对象用于创建列表中数据#
x = list("hello")
print(x)
# 或者
x = list(range(10))
print(x)4.列表的运算#
y = [4,5,6]
num = 5
z = x + y
print(z)
# 不能列表乘以列表,不能列表乘以浮点数
print(z)
z = x * num5.in / not in#
x = ["a","b","c"]
print("a" in x)
print("b" not in x)6.列表切片#
lst = [1,5,6,9,8,10]
# lst[起始下标:终止下标:步长]
# 取出一个元素
Lst_1 = lst[2]
# 取出多个元素
lst_2 = lst[2:5:2]
# 列表翻转
lst_3 = lst[::-1]
print(Lst_1,lst_2,lst_3)运行结果:
6 [6, 8] [10, 8, 9, 6, 5, 1]
7.列表的操作#
x = [10, 20, 30]
re = x.append(40)# 直接修改列表,在列表末尾添加一行新数据
print(x,re)
x.insert(2,666)# 在索引为2的地方插入666
print(x)
# 可以传入一个可迭代对象
x.extend([9,99,999])
print(x)
# id函数可以查看一个变量保存的数据的地址
x_1 = [1,2,3]
print(id(x_1))
x_2 = [1,2,3]
x_3 = x_1 + x_2
x_1.extend(x_2)
print(id(x_1))
print(id(x_2))#不改变id地址
print(id(x_3))
# 修改,删除数据
x = [1,2,3,5,6,8,9,7,1,2]
x[2] = 666
print(x)
# 切片可以越界
print(x[2:100])
# 传入元素
x.remove(666)
print(x)
# 传入下标
x.pop(1)
print(x)
x.clear()
print(x)
# 删除变量,变量名不在支持被引用
x = [1,2,3,5,6,8,9,7,1,2]
del x
# print(x)报错
x = [1,2,3,5,6,8,9,7,1,2]
# 寻找第一个出现元素的下标
print(x.index(1))
print(x.index(max(x)))运行结果:
[10, 20, 30, 40] None [10, 20, 666, 30, 40] [10, 20, 666, 30, 40, 9, 99, 999] 2303722066048 2303722066048 2303722068160 2303722005568 [1, 2, 666, 5, 6, 8, 9, 7, 1, 2] [666, 5, 6, 8, 9, 7, 1, 2] [1, 2, 5, 6, 8, 9, 7, 1, 2] [1, 5, 6, 8, 9, 7, 1, 2] []
0 6
七、元组#
元组和列表一样是保存数据的容器
1.创建元组#
x = ()
x = (1,2,3,5,6,8,5,4,2,5)
print(x)
print(x[1])
print(x[2:5])#得到一个新元组
# 只有一个数据,在后面打逗号
x = (10)
y = (10,)
print(type(x))
print(type(y))
x = 10,"hello",True
print(type(x))
x = tuple(range(5))
print(x)运行结果:
(1, 2, 3, 5, 6, 8, 5, 4, 2, 5) 2 (3, 5, 6) <class 'int'> <class 'tuple'> <class 'tuple'> (0, 1, 2, 3, 4)
2.元组的操作#
x = (1,"name","jack",6,5)
# 删除变量
# del x
print((x[1]))3.解构赋值#
解构赋值必须左右的结构一致
x1,x2 = (10,20)
print(x1,x2)4.元组的运算#
x = (10,20)
y = (30,40)
print(x+y)
print(x * 3)5.将其他数据类型转换为元组#
x_1 = [1,2,5,6]
x_2 = "nihao","yes","no"
print(tuple(x_1),tuple(x_2))
count = x_2.count("no")
print(count)八、字典#
1.创建空字典#
字典的元素没有下标,只有键和值
d = {}
print(d)
d = dict([("name","xiaowang"),("age",18)])
print(d)
d = dict(a = 1, b = 2, c = 3)
print(d)
# 字典的键不可以重复,否则后一个会覆盖前一个
title = {"name":"jack","age":"18","age":"10"}
print(title["age"])
# 并且需要是不可变类型,以此来访问数据,字典的键不存在会报错
title = {"name":"jack","age":"18","home":"beijing"}
print(title)
d = {(1,2,3):"id_num","age":18}
print(d)运行结果:
{} {'name': 'xiaowang', 'age': 18} {'a': 1, 'b': 2, 'c': 3} 10 {'name': 'jack', 'age': '18', 'home': 'beijing'} {(1, 2, 3): 'id_num', 'age': 18}
2.字典的操作#
# 添加和修改和访问
title = {"name":"jack","age":18,"home":"beijing"}
title["age"] = 20
print(title)
title["school"]="swust"
print(title)
print(title["home"])运行结果:
{'name': 'jack', 'age': 20, 'home': 'beijing'} {'name': 'jack', 'age': 20, 'home': 'beijing', 'school': 'swust'} beijing
3.in/not in#
只能用来判断键
title = {"name":"jack","age":18,"home":"beijing"}
print("name" in title)
print("jack" in title)运行结果:
True False
4.删除字典#
title = {"name":"jack","age":18,"home":"beijing"}
del title["name"]
print(title)
title.clear()
print(title)
del title运行结果:
{'age': 18, 'home': 'beijing'} {}
5.常见API#
title = {"name":"jack","age":18,"home":"beijing"}
print(len(title))
print(type(title))运行结果: 3 <class 'dict'>
把字典的字面量变成字符串,网络传输的时候,常常会把这种格式的字符串进行传输(JSON)
str1 = str(title)
print(str1,type(str1))运行结果: {'name': 'jack', 'age': 18, 'home': 'beijing'} <class 'str'>
6.字典的一些方法#
title = {"name":"jack","age":18,"home":"beijing"}
# 清空字典
title.clear()
print(title)
# 浅复制,存储地址不一样
# 因此更改其中一个不会对另外一个产生任何影响
title = {"name":"jack","age":18,"home":"beijing"}
str1 = title.copy()
print(str1)
print(id(title),id(str1))
str1["name"] = "mary"
print(str1,title)
# 获取字典中的数据
str2 = title.get("age")
print(str2)
str2 = title["age"]
print(str2)
# 若访问的键不存在,直接返回default的值
str2 = title.get("nn","None")
print(str2)
# 以可迭代对象来返回视图对象
items = title.items()
print(type(items))
for key,value in items:
print(key,value)
# 返回键名
keys = title.keys()
for key in keys:
print(key)
# 返回键值
values = title.values()
for value in values:
print(value)
title_1 = {"name":"jack","age":18,"home":"beijing"}
title_2 = {"food":"vegetable"}
# 将title_2添加到title_1中
title_1.update(title_2)
print(title_1)
# 删除字典的某个键
title.pop("name")
# 也可以将age的值置空,但是键仍然占用空间
title["age"] = None
print(title)运行结果:
{} {'name': 'jack', 'age': 18, 'home': 'beijing'} 2594022048448 2594031191872 {'name': 'mary', 'age': 18, 'home': 'beijing'} {'name': 'jack', 'age': 18, 'home': 'beijing'} 18 18 None <class 'dict_items'> name jack age 18 home beijing name age home jack 18 beijing {'name': 'jack', 'age': 18, 'home': 'beijing', 'food': 'vegetable'} {'age': None, 'home': 'beijing'}
九、集合#
1.创建集合#
s1 = set()
print(s1)
# 传入数据是可迭代对象
# 自动排序
s2 = set([1,2,3,8,5])
print(s2)
s2 = set(range(5))
print(s2)
s3 = {10,20,30}
print(s3)集合中不存在相同元素并且元素需要是不可变类型
s4 = {10,20,(2,3),10,1}
print(s4)易混点
s5 = {(10)}
print(s5)
s6 = {(10,),(10,),}
print(s6)运行结果:
{10}
{(10,)}
只有在python中相等,比较的是元素的值而不是地址
x = (10,20)
y = (10,20)
print(x==y)
print(id(x)==id(y))2.案例#
假设有一万个数字,每一个数字代表张图片的类别,用集合来查看到底有多少种类别
x = [0,0,0,0,1,1,1,1,2,2,4,4,4,4,4,4,2,2,1,1,1,1,0,0,0,0,3,3,3,3,3,5,1,2,2,1]
print(set(x))3.固定集合#
不可以更改元素
s1 = frozenset([1,2,3,4,5,5,6])
print(s1)4.eval()函数#
常出现在企业级别的项目中,向项目中添加代码
str1 = "10+20"
eval(str1)
lst = [1, 5, 6, 4, 5, 2, 3]
str2 = "+".join(map(str, lst)) # 将整数转换为字符串
print(eval(str2))十、运算符#
1.逻辑运算符#
A and B
A是一个表达式,B也是一个表达式
如果bool(A)为False,那么B不运行,否则整个表达式的结果为B的结果
x1 = 100
x2 = 200
x3 = 0
x = x1 and x2
print(x)
x = x3 and x2
print(x)运行结果:
200 0
A or B
如果bool(A)为True,那么B不运行,否则整个表达式的结果为B的结果
x = x1 or x2
print(x)
x = x3 or x2
print(x)运行结果:
100 200
not A
如果bool(A)为True,那么not A的结果为False,否则not A的结果为True
x = not x1
print(x)
x = not x3
print(x)运行结果:
False True
2.位运算符#
x1 = 0b1010
x2 = 0b1100
# 默认输出十进制数
print(x1 & x2)#按位与
print(x1 | x2)#按位或
print(x1 ^ x2)#按位异或
print(~x1)#按位取反运行结果:
8
14
6
-11
x1 = x1^x2
x2 = x1^x2
x1 = x1^x2
print(x1,x2)运行结果:
12 10
左移运算符
左移运算符是将一个数字的二进制位全部左移若干位,高位丢弃,低位补0。
x1 = 0b1010
x2 = 2
print(x1 << x2)#左移运算符右移运算符是将一个数字的二进制位全部右移若干位,低位丢弃,高位补0。
右移运算符
x1 = 0b1010
x2 = 2
print(x1 >> x2)#右移运算符运行结果:
40
2
3.身份运算符#
a = 10
b = 10
print(a is b) # True
print(a is not b) # False4.成员运算符#
a = [1, 2, 3, 4, 5]
b = 3
print(b in a) # True
print(b not in a) # False5.三元运算符#
a = 10
b = 20
result = a if a > b else b
print(result)运行结果:
20
十一、表达式#
\1. 算术表达式
\2. 逻辑表达式
\3. 关系表达式
\4. 赋值表达式
\5. 条件表达式
\6. 位运算表达式
\7. 成员运算表达式
\8. 身份运算表达式
十二、语句#
标准的语句写法是每一个语句结束以后 用分号结尾
例如x = 10;,但是python不需要分号
语句分为单行语句和多行语句
1.if语句#
if 1 == 1:
print("1 == 1")
else:
print("1 != 1")
if 1 == 1:
print("1 == 1")
elif 1 == 2:
print("1 == 2")
else:
print("1 != 1")2.循环语句#
# for循环
for i in range(2, 10,2):
print(i)
# while循环
i = 1
while i <= 10:
print(i)
i += 1
else:
print("循环结束")
# 死循环
# while True:
# print("永远不会结束")3.break和continue语句#
# break语句
# break语句用于终止当前循环,并跳出循环体。
# python代码示例:
# 1. 无限循环
i = 0
while True:
print(i)
i += 1
if i == 5:
break
# 2. 条件循环
for i in range(10):
if i == 5: # 当i等于5时,跳出循环
break
print(i)
# continue语句
# continue语句用于跳过当前循环的剩余语句,直接开始下一轮循环。
# python代码示例:
for i in range(10):
if i == 5: # 当i等于5时,跳过当前循环的剩余语句,直接开始下一轮循环
continue
print(i)4.推导式#
# 列表推导式
x2 = [i**2 for i in range(1, 11) if i%2 == 0]
print(x2)
# 元组推导式
x3 = tuple(i**2 for i in range(1, 11))
print(x3)
# 字典推导式
key = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k']
x4 = {key[i]: i**2 for i in range(1, 11)}
print(x4)
# 集合推导式
x5 = {i**2 for i in range(1, 11)}
print(x5)运行结果:
[4, 16, 36, 64, 100] (1, 4, 9, 16, 25, 36, 49, 64, 81, 100) {'b': 1, 'c': 4, 'd': 9, 'e': 16, 'f': 25, 'g': 36, 'h': 49, 'i': 64, 'j': 81, 'k': 100} {64, 1, 4, 36, 100, 9, 16, 49, 81, 25}
5.with语句#
# with语句
with open("test.txt","r") as f:
print(f)
for line in f:
print(line)
# with自动关闭文件
f = open("test.txt","r")
print(f)
for line in f:
print(line)
f.close()# 手动关闭文件十三、函数#
1.声明函数#
def f1():
print("f1运行")
f1()
def f2(x1,x2):
print(x1+x2)
f2(5,6)return会让函数停止执行并返回结果
def f2(x1,x2):
return x1+x2
a = f2(6,6)
print(a)运行结果:
f1运行 11 12
2.参数的数量和位置#
# 参数数量和位置一致
def add(a, b):
# return a + b
return b + a
print(add(2, 3)) # 5
# 参数数量不一致
# def add(a, b):
# return a + b + c
# print(add(2, 3)) # 语法错误,缺少参数c3.关键字参数#
先定义默认值,然后再调用时传入关键字参数
def my_func(a, b, c=0, d=0):
return a + b + c + d
print(my_func(1, 2, 3, 4)) # 10
print(my_func(1, 2, d=4)) # 64.元组解包参数#
def fn(a,b,c,*args):
print(a,b,c)
print(args,type(args))
fn(1,2,3)
fn(5,3,6,8,9,5,4,8)
def fn(*args):
# 任意传几个参数
print(*args)
fn(5,6,8)运行结果:
1 2 3 () <class 'tuple'> 5 3 6 (8, 9, 5, 4, 8) <class 'tuple'> 5 6 8
5.字典解包参数#
def fn(a,b,**args):
print(a,b)
print(args,type(args))
fn(20,30)
fn(10,20,name="jack",age = "18")运行结果:
20 30 {} <class 'dict'> 10 20 {'name': 'jack', 'age': '18'} <class 'dict'>
**args 与 *kwargs一起使用,可以接收任意数量的位置参数和关键字参数。
def my_func(*args, **kwargs):
print(args)
print(kwargs)
my_func(1, 2, 3, a=4, b=5) 运行结果:
(1, 2, 3) {'a': 4, 'b': 5}
只要是有下标的参数都可以解包
# 列表也可以解包
my_list = [1, 2, 3]
my_func(*my_list) # 解包
# 也可以用字典解包
my_dict = {'a': 1, 'b': 2, 'c': 3}
my_func(**my_dict) # 解包
# 元组也可以解包
my_tuple = (1, 2, 3)
my_func(*my_tuple) # 解包
# 字符串也可以解包
my_str = '123'
my_func(*my_str) # 解包6.占位符#
def my_func(x, *, y):
# *是一个占位符,他后面的参数必须是关键字参数
print(x, y)
# my_func(1,2)报错,缺少关键字参数y
my_func(1, y=2)7.匿名函数lambda#
fn=lambda x,y:x+y
print(fn(2,3))
fn = lambda x:"奇数" if x%2==1 else "偶数"
print(fn(11))
print(fn(2))案例1:判断是否是闰年
def is_leap(year):
if (year%4)==0 and (year%100)!=0:
return True
elif (year%400)==0:
return True
else:
return False
print(is_leap(2024))案例2:按比例划分数据集
def train_test_split(data,train_size = 0.8):
train_data = data[:int(len(data)*train_size)]
test_data = data[int(len(data)*train_size):]
return train_data,test_data
#测试
data = [1,2,3,4,5,6,7,8,9,10]
train_data,test_data = train_test_split(data,0.8)
print(train_data)
print(test_data)运行结果:
[1, 2, 3, 4, 5, 6, 7, 8] [9, 10]
函数分为三种:
官方内置函数,第三方函数,自己写的函数
8.官方内置函数#
# all传入的参数全部为True就返回True
x = [-10,0,30,-2]
re = all(x)
print(re)
# any只要有一个为True就返回True
print(any(x))
# sum(x)对x求和
print(sum(x))
# sorted(x)排序,key = fn表示按照函数返回值排序
def fn(x):
return x**2
print(sorted(x,key = fn))
# reverse(x)反转,返回一个可迭代对象
print([i for i in reversed(x)])
# callable(x)检测x标识符是不是能够当函数调用
fn = 100
print(callable(fn))
fn = lambda x,y:x+y
print(callable(fn))
# zip(x,y)将x,y两个数据容器组合成一个可迭代对象,打包成元组
x = [10,20,30,40,50]
y = [40,50,60]
print([i for i in zip(x,y)])
# exec()将传入的字符串中的代码执行
exec("print('hello')")运行结果:
False True 18 [0, -2, -10, 30] [-2, 30, 0, -10] False True [(10, 40), (20, 50), (30, 60)] hello
9.globals和locals()#
globals()返回值是一个字典,字典的key就是当前python环境全局变量的名字
x = 10
y = 20
print(globals())运行结果是一大串字典
locals()返回值是一个字典,字典的key就是当前函数的局部变量的名字
def fn(x,y):
print(locals())
fn(1,2)运行结果:
{'x': 1, 'y': 2}
10.filter函数#
filter(函数,可迭代对象),传入两个参数:函数和可迭代对象,返回一个经过函数筛选后的可迭代对象
x = [1,2,2,3,5,6,4,8,5,2]
x2 = filter(lambda el:el%2==1,x)
print(list(x2))实现:
def myfilter(fn,x):
x2 = []
for i in x:
if fn(i) ==True:
x2.append(i)
else:
continue
return x2
def fn(x):
if x%2==0:
return True
else:
return False
re = myfilter(fn,[1,2,2,3,5,6,4,8,5,2])
print(re)运行结果:
[2, 2, 6, 4, 8, 2]
11.map函数#
map(函数,可迭代对象),与filter不同的是不需要进行筛选,直接经过函数映射到可迭代对象中
x = [1,2,2,3,5,6,4,8,5,2]
def fn(x):
return x**2
print(list(map(fn,x)))实现
def mymap(fn,x):
x2 = []
for i in x:
x2.append(fn(i))
return x2
def fn(x):
return x**2
re = mymap(fn,[1,2,2,3,5,6,4,8,5,2])
print(re)运行结果:
[1, 4, 4, 9, 25, 36, 16, 64, 25, 4]
12.reduce函数#
reduce(函数,可迭代对象,初始值)
reduce()函数会对可迭代对象中的元素进行累积操作,并将结果作为第一个参数传递给函数,然后再将结果和第二个参数传递给函数,以此类推,直到可迭代对象中的所有元素都被处理完。最后,reduce()函数返回累积结果。
from functools import reduce
x = [1,2,4,3,5,6,4,8,5,2]
def fn(x1,x2):
print(x1,x2,"=====")
return x1+x2
reduce(fn,x)实现:
def myreduce(fn,x,start):
x1 = fn(start,x[0])
for i in range(len(x)-1):
x1 = fn(x1,x[i+1])
return x1
# 简洁版
# def myreduce(fn,x,start):
# re = start
# for i in x:
# re = fn(re,i)
# return re
def fn(x1,x2):
print(x1,x2,"=====")
return x1+x2
x = [1,2,4,3,5,6,4,8,5,2]
myreduce(fn,x,0)运行结果:
0 1 ===== 1 2 ===== 3 4 ===== 7 3 ===== 10 5 ===== 15 6 ===== 21 4 ===== 25 8 ===== 33 5 ===== 38 2 =====
13.作用域#
作用域只针对函数,函数内部可以访问函数内部和外部的变量,但是函数外部不能访问函数内部的变量
a = 100
def fn():
q = 10
a = 20#内层有a,访问内层作用域的a,外层没有,就去外层的外层,如果都没有就报错
print(a)
print(q)
return a+q
print(fn())# 每次调用函数内部都会产生一个作用域,调用完毕后,内部创建数据使用的内存销毁
print(a)
# print(q)报错运行结果:
20 10 30 100
b = [1,2,3,4,5,lambda x:x+1]
print(b[5](5))运行结果:
6
函数调用在A作用域 定义在B作用域,函数无论在哪个作用域中执行,一定是他定义的作用域下执行代码
a = 100
def fm():
print(a)
def fn():
a = 200
fm()
fn()运行结果:
100
函数也是一种数据
def f1():
a = 100
def f2():
print(a)
return f2
a = 200
re = f1()
re()# 执行函数作用域案例:
def fun(n = None,o = None):
print(o)
return {"fun":lambda m:fun(m,n)}
a = fun(0)
a["fun"](1)
a["fun"](2)
a["fun"](3)
b = fun(0)["fun"](1)["fun"](2)["fun"](3)
c = fun(0)["fun"](1)
c["fun"](2)
c["fun"](3)运行结果:
None 0 0 0 None 0 1 2 None 0 1 1
14.修改变量值#
# def fn():
# print(a)
# a = 2
# fn()报错
a = 10
def fn():
global a#声明全局变量
print(a)
a = 20#会访问全局变量a的值
fn()
print(a)
a = 10
def fn():
global a
a = 20
def fm():
global a
print(a)#访问和修改全局作用域“a = 10”这个a
a = 30
fm()
fn()
a = 10
def fn():
a = 20
def fm():
nonlocal a#访问和修改外层作用域“a = 20”这个a
print(a)
a = 30
fm()
fn()运行结果:
10 20 20 20
15.内建作用域#
print(__name__)运行结果:
main
16.递归#
def f(a):
if a > 5:
return a
else:
return f(a+1)
r = f(0)
print(r)运行结果:
6
函数返回值是一种数据,函数也是一种数据
def fn():
return 1+1
print(type(fn))
print(type(fn()))运行结果:
<class 'function'> <class 'int'>
16.回调函数 callback#
把一个函数传入另外一个函数,传入的函数就是回调函数
定义一个工具函数,传入两个数和一个函数,调用传入的函数并返回结果
a,b可以是数据也可以是字符串,func必须是函数
# 定义两个函数
def add(a,b):
return a+b
def sub(a,b):
return a-b
def calculate(a,b,func):
return func(a,b)
# 传进去的add就是回调函数
print(calculate(5,3,add)) # 8
print(calculate(5,3,sub)) # 2回调函数怎么体现:
遍历:把一个数据容器中的数据全部拿出来调用
设计一个工具函数:遍历列表中的所有元素,找出奇数拿来使用,但是这个工具自己并不适用
而是交给业务函数(回调)使用
def find_odd(arr,cb):
for el in arr:
if el%2==1:
cb(el)
x = [2,5,6,8,9,7]
def print_odd(el):
print("找到一个奇数:",el)
find_odd(x,print_odd)
find_odd(x,lambda m:print(m**2))运行结果:
找到一个奇数: 5 找到一个奇数: 9 找到一个奇数: 7 25 81 49
17.闭包函数 block#
函数内部有函数,内部的那个函数就是闭包函数
1.由于函数有作用域,而且多个函数的作用域是相互独立的
使用闭包函数把函数的值单独保存,让变量不要相互污染
2.由于函数调用和定义的作用域可以不是同一个,并且函数调用时是在定义的作用域中执行的
因此闭包函数可以在函数外部访问函数内部的变量
def alipay():
money_in = 100
def tool():
money_in = 300
print(money_in)
return tool
re = alipay()
re()
money_out = 200
print(money_out)
# print(money_in) 报错并没有更改程序内部的money,而是外部变量的money案例
# 案例
def alipay():
money1 = 200
def tool(pwd,new_money):
nonlocal money1
if pwd == 123:
money1 = new_money
print(money1)
def withdraw(pwd,amount):
# 取钱
nonlocal money1
if pwd == 123:
money1 -= amount
print(money1)
return tool,withdraw
def meituan():
tool,withdraw = alipay()
tool(123,666)
# fn(321,777)
withdraw(123,50)
meituan()运行结果:
666 616
十四、装饰器#
装饰器相当于一个闭包的调用,但是不同的是相较于Alipay的案例,不需要多余构建re变量,直接用@装饰器名字的方式来调用,相当于一种方便的写法
装饰器本质是回调函数和闭包函数的结合
装饰器本身是一个函数,把装饰的函数作为参数输入,然后吧调用封装在内部的闭包中,返回值那个闭包
不带参数的装饰器
def fn():
print("fn函数的业务是答应一句话:未来业务可能有很多行代码")
# 设计一个装饰器
def decorator(cb):
def block1():
print("装饰器执行的代码:怎么装饰由业务决定")
cb()
print("装饰器可以继续装饰:怎么装饰由业务决定")
return block1
@decorator
def fn2():
print("fn2函数的业务是打印一句话:未来就是具体业务代码")
fn2()运行结果:
装饰器执行的代码:怎么装饰由业务决定 fn2函数的业务打印是一句话:未来就是具体业务代码 装饰器可以继续装饰:怎么装饰由业务决定
带参数的装饰器:
# 带参数的装饰器
def my_decorator(func):
def wrapper(*args, **kwargs):
print("Before calling the function")
func(*args, **kwargs)
print("After calling the function")
return wrapper
@my_decorator
def my_function(x, y):
print("The sum of", x, "and", y, "is", x+y)
return x + y
my_function(2, 3) # Output: 5 运行结果:
Before calling the function The sum of 2 and 3 is 5 After calling the function
作用:
- *日志记录*:在函数执行前后自动添加日志记录,方便调试和监控程序行为。
- *性能测试*:装饰器可以用来测量函数的执行时间,帮助识别性能瓶颈。
- *权限验证*:在Web开发中,装饰器可以用于检查用户是否有权访问某个资源或执行特定操作。
- *缓存*(Memoization):通过装饰器实现函数结果的缓存,避免重复计算相同的输入值,从而提高效率。
十五、面向对象#
1.类和对象的语法#
定义一个类
class Person:
name = "张三"
age = 18
life = 1
def fn(self,num):
print("类中的函数叫做方法,参数是",num)
print(Person,type(Person))用这个类创造对象
p1 = Person()
print(p1,type(p1))对象内部保存了很多数据,想要访问需要通过成员名
语法:对象名.成员名
print(p1.name,p1.age,p1.life)
p1.fn(1)
p2 = Person()
p2.fn(2)运行结果:
<class '__main__.Person'> <class 'type'> <__main__.Person object at 0x00000187F9C19940> <class '__main__.Person'> 张三 18 1 类中的函数叫做方法,参数是 1 类中的函数叫做方法,参数是 2
2.init#
实用类创建对象时,可以初始化对象的成员的值
但是在Python当中__init__并不是构造函数,__new__才是
__init__是一个魔术方法,是一个特殊的函数,会在创建对象时调用
class Teacher:
# 类名(10,20)的10和20会传给__init__函数的参数
def __init__(self,name,age):
print("__init__ name:",name,"年龄:",age)
self.n = name# 给t1对象添加一个属性,属性名是n,属性中保存的值是:“xiaoming”,相当于赋值
self.a = age
def fn(self,name,age):
print("fn name:",name,"年龄:",age)
t1 = Teacher("xiaoming",18)
t1.fn("xiaoming",18)
t1.a运行结果:
init name: xiaoming 年龄: 18 fn name: xiaoming 年龄: 18
类每次创建对象时,创建对象有同样的属性和方法,而有一部分是创建的时候赋的值,有一部分创建的时候值一样
class Game_person:
life = 1
def __init__(self,name,rank):
self.name = name#前一个name是self的属性,后一个name是函数内部的一个变量
self.rank = rank
# 可以创建很多个
g1 = Game_person("boss",2000)
g2 = Game_person("npc",100)
print(g1.name,g1.rank)
print(g2.name,g2.rank)运行结果:
boss 2000 npc 100
3.对象语法#
class Box:
x = 100
def __init__(self,y):
self.y = 200
def change_y(self,new_y):
print("调用函数前",self.y )
self.y = new_y
print("调用函数后",self.y )
b1 = Box(99)
b1.x = 200
print(b1.x)#只修改了b1的x值
b2 = Box(98)
print(b2.x)#b1的x值不变
b3 = Box(97)
print(b3.y)#这里y还是200
# 修改y的值,这里只修改b3的值,b1,b2不受影响,但是b1,b2也可以调用这个方法来修改值
# 第一种直接修改:
b3.y = 1
print("直接修改后",b3.y)
# 第二种常见一个修改y的函数来修改self.y:
b3.change_y(2)
print(b3.y)运行结果:
200 100 200 直接修改后 1 调用函数前 1 调用函数后 2 2
4.对象的方法内部可以操作这个对象的属性和方法#
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def say_hello(self):
print("Hello, my name is {} and I am {} years old.".format(self.name, self.age))
p1 = Person("Alice", 25)
p1.say_hello()运行结果:
Hello, my name is Alice and I am 25 years old.
5.对象的方法可以传入参数,也可以返回值。#
class Box:
count = 100
def __init__(self,m):
self.m = m
def cal_total(self,price):
return self.count*self.m*price
b1 = Box(45)
re = b1.cal_total(108)
print(re)运行结果:
486000
案例1
假设有一个ATM类 用这个类创建出来的对象就是一个取款机对象
atm对象有一个属性 是一个列表 里面装了很多对象,每一个对象就是一个Person类型的对象
有一个属性 是一个数字 保存了余额
有一个方法可以往ATM里面添加Person对象
class Person:
def __init__(self,name,card_num,phone_num):
self.name = name
self.card_num = card_num
self.phone_num = phone_num
class ATM:
money = 5000
persons = []
def add_person(self,person):
if person not in self.persons:
self.persons.append(person)
print("添加成功")
else:
print("该卡号已存在")
atm = ATM()
person1 = Person("张三","123456","13800138000")
person2 = Person("李四","654321","13800138001")
atm.add_person(person1)
atm.add_person(person2)
print(atm.persons[0].name)
print(atm.persons[0].card_num)
print(atm.persons[0].phone_num)运行结果:
添加成功 添加成功 张三 123456 13800138000
案例2:
公司员工管理系统
设计一个公司员工管理系统,包含以下内容:
\1. 定义一个 Employee 类,包含以下属性:
- name(姓名)
- position(职位)
- salary(薪水)
\2. 定义一个 Company 类,包含以下内容:
- 一个列表属性,用于存储 Employee 对象。
- 一个方法 hire_employee,用于招聘新员工。
- 一个方法 fire_employee,根据员工的姓名,解雇该员工。
- 一个方法 list_employees,用于列出公司中所有员工的信息。
- 一个方法 total_salary,计算公司所有员工的总薪水。
\3. 测试代码:
- 创建一个 Company 对象。
- 招聘几个员工。
- 列出所有员工。
- 解雇一个员工。
- 再次列出所有员工。
- 打印公司总薪水。
class Employee:
def __init__(self,name,position,salary):
self.name = name
self.position = position
self.salary = salary
class Company:
Employee_lst = []
def hire_employee(self,Employee):
if Employee not in self.Employee_lst:
self.Employee_lst.append(Employee)
else:
print("已经添加该员工")
def list_employees(self):
for Employee in self.Employee_lst:
print("name:",Employee.name,"position:",Employee.position,"salary:",Employee.salary)
def total_salary(self):
salary_total = []
for Employee in self.Employee_lst:
salary_total.append(int(Employee.salary))
return sum(salary_total)
person1 = Employee("张三","经理","5000")
person2 = Employee("李四","客服","3000")
person3 = Employee("王五","地推","1000")
ali = Company()
ali.hire_employee(person1)
ali.hire_employee(person2)
ali.hire_employee(person3)
ali.list_employees()
salary = ali.total_salary()
print(salary)运行结果:
name: 张三 position: 经理 salary: 5000 name: 李四 position: 客服 salary: 3000 name: 王五 position: 地推 salary: 1000 9000
6.类属性和类方法#
class qox:
x = 100#他是一个类属性,这个类创建出来的实例也能访问
def fn(self):
print(qox.x)
# 两种调用方式
print(qox.x)
b1 = qox()
print(b1.x)
b1.x = 500
print(b1.x)#被更改
print(qox.x)#没有被更改,说明类自己本身也是一种数据容器
b1.fn()运行结果:
100 100 500 100 100
7.类属性和类方法#
它接收类本身作为第一个参数(通常命名为 cls),而不是实例(self)。
类方法可以访问类的属性和方法,但不能访问实例的属性
类变量是在类的定义中直接定义的变量,而不是在类的 init 方法或其他实例方法中定义的。
类变量属于类本身,而不是属于类的某个实例
class qox:
x = 100#他是一个类属性,这个类创建出来的实例也能访问
def fn(self):
print(qox.x)
# 两种调用方式
print(qox.x)
b1 = qox()
print(b1.x)
b1.x = 500
print(b1.x)#被更改
print(qox.x)#没有被更改,说明类自己本身也是一种数据容器
b1.fn()显式的指定类方法
class Box:
x = 100
def __init__(self,y):
self.y = y
def fn(self):
print(self.x)
@classmethod
def fm(cls):
print("fm被调用")
print(cls.x)
b1 = Box(100)
# b1对象可以使用的成员:x,y属性,y方法 fn方法,fm方法
print(b1.x)
print(b1.y)
b1.fn()
b1.fm()
# Box可以直接访问fm
Box.fm()案例:类方法常可以作为工厂方法
class single:
instance = None
# 类方法:
@classmethod
def share_instance(cls):
if cls.instance is None:
cls.instance = single()
return cls.instance
else:
return cls.instance
s1 = single.share_instance()
s2 = single.share_instance()
# 两个是一样的
print(s1)
print(s2)
o1 = single()
o2 = single()
# 两个是不同的
print(id(o1))
print(id(o2))批量创建对象
class student:
def __init__(self, name, age):
self.name = name
self.age = age
@classmethod
def create_students(cls,num):
arr = []
for i in range(num):
arr.append(cls(f"student{i}", i))
return arr
# 直接创建两个学生对象
s1 = student("Alice", 20)
s2 = student("Bob", 21)
print(s1.name, s1.age)
print(s2.name, s2.age)
# 先初始化好学生数量,再去更改学生的属性
students = student.create_students(10)
students[0].name = "jack"
students[0].age = 22
print(students[0].name, students[0].age)8.静态方法#
静态方法通常用于实现一些与类无关的工具函数,这些函数不需要访问类或实例的属性。
它们可以被类或实例调用,但不会影响类或实例的状态。
class Box:
count = 0
def fn(self):
print("fn普通方法")
@classmethod
def fm(cls):
print("fm类方法")
@staticmethod
def fz():
print("fn静态方法")
@staticmethod
def sigmod(x):
return 1.0/(1.0+math.exp(-x))
Box.fm()
Box.fz()
b1 = Box()
b1.fz()
re = Box.sigmod(10)
print(re)9.构造方法#
静态方法__new__ 方法负责创建并返回类的新实例,而 init 方法则用于初始化实例。
class Box:
def __new__(self):
print(self)
return super().__new__(self)
def __init__(self):
self.width = 0
b1 = Box()
print(b1.width)
print(b1,Box)10.魔术方法#
class Person:
# 初始化方法
def __init__(self, name, age):
self.name = name
self.age = age
# 打印方法
# 打印对象时,会调用该方法
# 该方法返回一个字符串,表示对象的信息
def __str__(self):
return f"Person(name={self.name}, age={self.age})"
#
def __repr__(self):
# 该方法返回一个字符串,表示对象的信息
# 该字符串可以被eval()函数解析,得到一个与该对象相同的对象
# 该方法的作用是方便调试
return f"Person(name={self.name}, age={self.age})"
def __delitem__(self):
# 删除对象时,会调用该方法
print("删除对象")
del self.name
def __add__(self, other):
# 实现两个对象相加,可以自己定义对象与对象的相加规则
# 该方法返回一个新的对象
return Person(f"{self.name}+{other.name}", self.age + other.age)
def __sub__(self, other):
# 实现两个对象相减,可以自己定义对象与对象的相减规则
# 该方法返回一个新的对象
return self.age - other.age
def __iter__(self):
# 实现对象可迭代,可以用for循环遍历对象
# 该方法返回一个迭代器对象
return iter([self.name, self.age])
# 创建对象
p = Person("Alice", 25)
# 打印对象
print(p)
# 调用__repr__方法
print(repr(p))
# 调用__delitem__方法
# del p.name
# 再次打印对象
# print(p) 'Person' object has no attribute 'name'
# 调用__add__方法
p2 = Person("Bob", 30)
p3 = p + p2#这里的+号调用的是__add__方法
print(p3)
# 调用__sub__方法
print(p2 - p)
# 调用__iter__方法
print(type(p))
for item in p:
print(item)11.比较常用的魔术方法#
class Images:
def __init__(self,path):
self.path = path
self.arr = ["6.jpg","5.jpg","4.jpg","3.jpg","2.jpg","1.jpg"]
def __len__(self):
return len(self.arr)#由自己决定的返回
def __getitem__(self,index):
print(index)
return self.arr[index]#利用传入的下标进行操作
def __setitem__(self,index,value):
print(index,value)
def __call__(self, *args, **kwargs):
print("调用了__call__方法",args,kwargs)
imgs = Images("./imgs")
count = len(imgs)
print(count)#自动调用__len__
# 调用__getitem__
# print(imgs[100]) 报错,arr越界了
print(imgs[2])
# 调用__setitem__
print("===========")
imgs[1] = 2
print("===========")
print("__setitem__",imgs[1])
# 调用__call__
imgs(1,2,3,a=1,b=2)12.继承#
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def eat(self):
print(f"{self.name}今年{self.age}岁,正在吃饭")
p1 = Person("张三", 20)
p1.eat()
class Student(Person):
# 子类构造函数中必须调用父类构造函数
# 否则无法调用父类属性
def __init__(self, name, age, school):
# 调用父类构造函数
# 必须在子类构造函数的第一行调用
super().__init__(name, age)
self.school = school
s1 = Student("李四", 21, "清华大学")
s1.eat()
print(s1.school)运行结果:
张三今年20岁,正在吃饭 李四今年21岁,正在吃饭 清华大学
13.覆盖-重写#
父类已经定义了一个方法,子类要将这个方法重新修改,就叫重写
class Animal:
def __init__(self,name):
self.name = name
def eat(self):
print("Animal的eat方法,{} is eating".format(self.name))
def sleep(self):
print("Animal的sleep方法,{} is sleeping".format(self.name))
class Dog(Animal):
def __init__(self, name,age):
super().__init__(name)
self.age = age
def say(self):
print("Dog的say方法,{} is barking".format(self.name))
def eat(self):
print("Dog重写了Animal的eat方法,{} is eating".format(self.name))
dog = Dog("旺财", 3)
print(dog.name)
print(dog.age)
dog.sleep()
dog.say()
dog.eat()14.多台#
class Animal:
def eat(self):
print("动物会吃东西")
class Dog(Animal):
def eat(self):
print("狗会吃骨头")
class Cat(Animal):
def eat(self):
print("猫会吃鱼")
def eat(animal):
animal.eat()# 体现了多态
dog = Dog()
cat = Cat()
eat(dog)
eat(cat)
# 看dog是否是Dog或他的父类的实例
print(isinstance(dog, Animal))
print(isinstance(dog, Dog))15.私有属性#
不同于类属性,在属性前面加__表示只能在类中调用这个属性
class Person:
__name = 'jack'
def __init__(self, __age):
self.__age = __age
def fn(self):
print("私有属性只能在类内部访问")
print("私有属性:", self.__name)
print("私有属性:", self.__age)
p = Person(25)
# print(p.__name) # 报错
# print(p.__age) # 报错
p.fn() # 通过实例化对象调用私有方法,可以在类内部访问私有属性和方法16.重载魔术方法#
下面重新定义了Python中的加减乘除,实质就是改写了底层的魔术方法
class Box:
def __init__(self, width, height):
self.width = width
self.height = height
def __add__(self, other):
return self.width + self.height + other.width + other.height
def __sub__(self, other):
return self.width - self.height - other.width - other.height
def __mul__(self, other):
return self.width * self.height * other.width * other.height
def __truediv__(self, other):
return self.width / self.height / other.width / other.height
def __floordiv__(self, other):
return self.width // self.height // other.width // other.height
b1 = Box(2, 3)
b2 = Box(4, 5)
print(b1 + b2)
print(b1 - b2)
print(b1 * b2)
print(b1 / b2)
print(b1 // b2)17.super()方法#
class Box:
x = 5
def fn(self):
print("这是Box类的fn方法")
def fm(self):
print("这是Box类的fm方法")
class Box2(Box):
# 重写父类的fn方法
x = 10
def fn(self):
super().fn()
print("这是Box2类的fn方法")
super().fm()
print("这是Box2类的fm方法")
b = Box2()
b.x = 400
super(Box2, b).fn() # 这是b对象调用父类的fn方法
# 总结:执行Box2父类的fn()函数 把b2作为第一个参数self传入进去
super(Box2, b).x十六、迭代器和生成器#
1.迭代器iter#
全局函数iter 可以把一个可迭代对象转换成一个迭代器,全局函数next 他可以迭代下一次迭代器中的数据,for 循环可以连续调用next
arr = [10,20,30,40,50]
iterator = iter(arr)
re1 = next(iterator)
print(re1)
re2 = next(iterator)
print(re2)
re3 = next(iterator)
print(re3)
for el in iterator:
# 接着re3迭代
print(el,"====================")
# re4 = next(iterator)
# print(re4)#报错,re3已经迭代完了案例:
实现数据加载器的底层核心源代码,有一个数据容器,里面有1000条数据,封装一个可迭代对象,这个对象迭代一次就取出这个列表的n条数据,n = 8
class myData:
def __init__(self,data):
self.data = data
self.index = -1
def __iter__(self):
return self
def __next__(self):
while self.index < len(self.data)//8:
self.index += 1
return self.data[self.index * 8:(self.index+1) * 8]
data = myData(["a", "b", "c", "d", "e", "f", "g",
"h", "i", "j", "k", "l", "m", "n",
"o", "p", "q", "r", "s", "t", "u",
"v", "w", "x", "y", "z"])
data_loader = iter(data)
re = next(data_loader)
print(re)
re = next(data_loader)
print(re)
re = next(data_loader)
print(re)2.生成器yield#
yield关键字在函数内部 会让函数暂时生成结果,但是函数还没有运行完毕,并且这个函数调用的代码的后面的代码会正常执行
def my_gen():
print("start")
yield 1
print("middle")
yield 2
print("end")
yield 3
re = my_gen()
print(next(re),"===========")
# re = my_gen()
print(next(re),"===========")
# re = my_gen()
print(next(re),"===========")
# 结束迭代
# re = my_gen()
# print(next(re),"===========")案例:
实现range函数源代码
def myrange(start,end,step):
i = start - step
while True:
i += step
if i >= end:
# raise StopIteration
break
yield i
for el in myrange(0,11,2):
print(el)十七、异常处理#
try:
arr = [100,20]
x = arr[100]
print(x)
except ValueError:
print("数组类型错误",ValueError)
except IndexError as e:
print("数组越界",e)
else:
print("没有异常")
finally:
print("不管有没有报错都执行finally")
print("后面的代码")运行结果:
数组越界 list index out of range 不管有没有报错都执行finally 后面的代码
常见的几种except选项:
| ZeroDivisionError | 除(或取模)零 (所有数据类型) |
| ----------------- | ---------------------------- |
| ValueError | 传入无效的参数 |
| AssertionError | 断言语句失败 |
| StopIteration | 迭代器没有更多的值 |
| IndexError | 序列中没有此索引(index) |
| IndentationError | 缩进错误 |
| OSError | 输入/输出操作失败 |
| ImportError | 导入模块/对象失败 |
| NameError | 未声明/初始化对象 (没有属性) |
| AttributeError | 对象没有这个属性 |或者直接不写这个错误类型
try:
print(3 / 0)
except:
print("报错")
else:
print("没错")运行结果:
报错
主动抛出错误:
def fn():
x = 10
if 5<x<6:
print(x)
else:
raise ValueError("x不在范围内")
try:
fn()
except ValueError as e:
print(e)
print("后续代码")运行结果:
x不在范围内 后续代码
十八、模块与包#
import model1 as m1
from model2 import area
from model2 import perimeter as peri
print(m1.is_prime(7))
print(m1.is_palindrome("racecar"))
print(area(5, 6))
print(peri(5, 6))1. file__和__name#
这两个全局变量保存的是字符串
print(__file__)# 保存的是当前文件路径
print(__name__)# 保存当前模块名
# 当运行这个Python文件,如果是入口程序运行结果:
d:\桌面\华清\基础语法\code\Python基础语法\21-模块与包.py main
十九、内置函数#
import random
import time
import os
if __name__ != "__main__":
# 随机数
# random.seed(42)
re1 = random.random()
print("re1",re1)
# 随机整数
re2 = random.randint(-5,6)
print("re2",re2)
# 随机取出
arr = [1,2,3,4,5,6,7,8,9]
re3 = random.choice(arr)
print("re3",re3)
# 打乱列表
re4 = random.shuffle(arr)
print("re4",re4)#返回None
print(arr)
# time 模块
def time_fn():
t = time.time()
print(t)
for i in range(3):
time_fn()
time.sleep(1)#每次循环时间间隔5秒
print(time.localtime())#获取时间信息
print(time.localtime().tm_mday)#具体到某一项
print(time.strftime("%y年%m-%d %H:%M:%S"))#格式化时间格式
# os 模块用于操作计算机的一些东西
def os_fn():
path = os.getcwd()#获取当前文件夹地址
print(f"====={path}=======")
# 绝对路径
re = os.path.join(path,"./img","a.jpg")
print(re)
# 相对路径
re1 = os.path.realpath(re)
print(re1)
# 创建文件夹
os.mkdir("./code/img")
if __name__ == "__main__":
# os模块
os_fn()
总结#
大纲已完结,后续会有补充