文章目录
- 变量与数据类型
- 变量
- 定义与使用
- 变量的多次赋值
- 数据类型
- 整数类型[^integer]
- 浮点类型[^float]
- 布尔类型[^bool]
- 字符串类型[^str]
- 字符串方法(直接调用)
- 查询操作
- 大小写转换
- 对其操作
- 劈分操作
- 字符串的判断
- 字符串替换
- 字符串拼接
- 字符串切片
- 格式化字符串
- 不同数据类型的转换
- 列表[^可变数据类型]
- 列表内存示意图
- 列表的创建
- 列表查询
- 列表的切片操作
- 判断元素是否存在
- 列表遍历
- 列表的增删改操作
- 列表元素的排序
- 列表生成式
- 列表的相关方法
- 字典
- 字典的创建
- 字典元素的获取
- 字典元素的增删改
- 字典的遍历
- 字典生成式
- 元组与集合
- 元组[^不可变类型,有序支持索引]
- 集合[^无序的结构]
- 集合的创建
- 集合增删改操作
- 集合取值
- 集合间的关系
- 程序组织结构
- 选择结构if
- 循环结构
- while循环
- for in 循环
- for else 循环
- 嵌套循环
- 流程控制语句
- 内置函数
- range函数
- pow函数
- len函数
- random函数
- abs与round
- map()--重点
- zip()--重点
- reduce()
- filter()
- eval()函数
- 函数
- 简单函数
- 函数的定义
- 函数调用
- 变量的作用域
- 函数2
- 交换变量值
- 递归函数
- lambda表达式
- python文件操作
- 面向对象
- 类与对象
- 类的创建
- 创建实例对象
- 属性与方法的调用
- 动态绑定属性与方法
- 类与继承
- 单继承与多继承
- 单继承
- 多继承
- 重写与调用父类的同名属性和方法
- 多层继承
- super()
- 类与对象封装
- 多态
- 模块封装与异常处理
- 模块的导入
- 制作模块
- 制作包
- 异常处理
- try except
- 模块封装与异常处理
- 模块的导入
- 制作模块
- 制作包
- 异常处理
- try except
变量与数据类型
变量
定义与使用
- 定义:
name=....... #'name'为变量名字,'='号将某值赋予变量存储
- 三要素:
- id(地址):变量名
- type(类型):数据类型
- value(值):具体的值
变量的多次赋值
name='张三'
name='李四' #变量最终的值为'李四'
数据类型
- 有序的数据类型都可以使用索引
- 有序的数据类型都可以强制进行类型转换
整数类型[^integer]
浮点类型[^float]
布尔类型[^bool]
表示真或假
- True:真,以1表示
- False:假,以0表示
bool值可转换为整数计算:
p1=True
p1=False
print(False+1) #输出结果为1
字符串类型[^str]
字符串方法(直接调用)
查询操作
操作 | 描述 |
index() | 查找子串第一次出现的位置,如果不存在则抛出ValueError |
rindex() | 查找子串最后一次出现的位置,如果不存在则抛出ValueError |
find() | 查找子串第一次出现的位置,不存在则返回-1 |
rfind() | 查找子串最后一次出现的位置,不存在则返回-1 |
大小写转换
操作 | 描述 |
upper() | 把字符串中所有字符都转换成大写字母 |
lower() | 都转成小写字母 |
swapcase() | 大小写字母反转 |
capitalize() | 第一个字符转为大写,剩余转为小写 |
title() | 把单词的第一个字母转为大写,其余转为小写 |
对其操作
操作 | 描述 |
center() | 居中对齐,第一个参数指定宽度,第二个参数指定填充符,第二个参数可选,默认是空格 |
ljust() | 左对齐,参数同上 |
rjust() | 右对齐,参数同上 |
zfill() | 右对齐,只需要指定宽度,左边用0填充 |
劈分操作
返回列表类型
操作 | 描述 |
split(sep,maxsplit) | 从左边开始劈分返回列表,默认以空格劈分,可以使用sep指定劈分符,maxsplit指定劈分次数,最大劈分次数之后,剩余的部分单独作为一部分 |
rsplit(sep,maxsplit) | 从右侧开始劈分,同上 |
字符串的判断
操作 | 描述 |
isidentifier() | 是否是合法的标识符 |
isspace() | 是否全部由空白字符组成(回车、换行、水平制表符) |
isalpha() | 是否全部是字母 |
isdecimal() | 是否全部由十进制的数字组成 |
isnumeric() | 是否全部是数字 |
isalnum() | 是否全部由字母和数字组成 |
字符串替换
使用replace(被替,替换,次数)
s1='你的我的他的'
s2=s1.replace('的','我','3')
#返回s2='你我我我他我'
字符串拼接
使用 join() #可指定连接符,默认连接到一起
s=['你的','我的','他的']
s1=''.join(s)
#返回s1='你的我的他的'
字符串切片
s[start,stop,step] #切片后产生新对象
格式化字符串
- 以’%为占位符’
操作 | 描述 | 宽精度 |
%s | 字符串 | %10s[^宽度为10] |
%i/%d | 整数 | %10d[^宽度为10] |
%f | 浮点数 | %.3f[保留3位小数],%10.3f[宽度为10,保留3位小数] |
print('我叫%5s,今年%5s岁了'%(name.age))
- 以{ }为占位符:{index}.format(value)
- {index:.3}: .3表示三位数
- {index:10.3f}: 宽度为10,保留3位小数
- f-string方法:
name='张三'
age=21
f'我叫{name},今年{age}岁了'
不同数据类型的转换
使用代表数据类型的符号进行转换:str/int/float
age=1
name='张三'
print('我叫'+name+今年+str(age)+'岁了')#使用str将int类型转换成字符串,否则str与int进行拼接时报错
列表[^可变数据类型]
列表内存示意图
列表的创建
- 使用[ ]创建:
lst1=[1,2,3]
- 使用内置函数list[ ]:
lst2=list[(1,2,3)]
==注意:==列表不止存放数字,还可以混合其他数据(可以存储所有类型的数据,以及对象)
列表查询
- 获取索引[^元素在列表中的位置]:使用index()
lst=[1,2,3,3]
print(lst.index(2,start,stop)) #起始与结束可不指定,当存在相同元素时,返回第一个元素的位置
- 获取列表元素:使用 lst[index] ,正向排列为0~n,逆向排列为-n~-1
lst=[1,2,3]
print(lst[2]) #获取位置为2的元素,即列表中的3
print(lst[-1])#获取位置为-1的元素,即列表中的3
列表的切片操作
切片后的列表是一个新的列表对象
**语法格式:new_lst=lst[start,stop,step] ** ➡️不包含stop(左闭右开),范围是[star,stop]
- 默认步长为1:简写为[start:stop]
- step为正数:从start开始往后切片
格式 | 切片 |
[:stop:step] | 默认从第一位开始切片 |
[start::step] | 默认切片至列表最后一位,且包含列表最后一位 |
- step为负数: 从start往前切片
格式 | 切片 |
[:stop:step] | 默认从列表的最后一个元素开始切片 |
[start::step] | 切片的最后一个元素默认是列表的第一个元素,且包含第一个元素 |
lst=['a','b','c','d','e','f','g']
print(lst[1:5]) #返回b,c,d,e
print(lst[1:-1]) #返回除了a和g之外的其他
print(lst[1:]) #返回除了a之外的其他
判断元素是否存在
使用 in/not in
lts=[1,2,3,4]
print(1 in lst) #返回0,代表True
#可用作条件判断
if 1 in lst: #条件成立,程序继续执行
列表遍历
使用 for in 进行遍历
lst=[1,2,3,4]
for i in lst:
print(i) #依次返回1,2,3,4
i=0
while i<len(lst):
print(lst[i])
i+=1
列表的增删改操作
- 增加操作
操作 | 描述 |
append() | 在列表末尾添加一个元素,可以是一个列表,形成列表嵌套 |
extend() | 在列表末尾至少添加一个元素。可以传入列表或元组,会讲列表中的元素提取出来添加到列表中。 |
insert(index,元素) | 在列表的任意位置添加指定元素 |
lst[]=()(切片操作) | 使用切片操作,替换指定范围的元素 |
lst1=[10,20,30,40]
lst2=[10,20]
lst1[1:2]=lst2
print(lst1) #返回的lst1为[10,10,20,30,40],lst1的第1个元素被替换成了lst2
- 删除操作
方法 | 描述 |
remove() | 指定一个元素进行删除,重复元素只删除第一个,元素不存在时抛出ValueError |
pop() | 删除指定索引上的元素,索引不存在时抛出IndexError,不指定索引默认删除最后一个元素。使用pop()弹出的元素,可以被接收,即可以赋值给一个变量 |
切片 | 一次至少删除一个元素 |
clear() | 清空列表 |
del | 删除列表 |
- 修改操作
方法 | 描述 |
lst[index]= | 修改指定索引的元素 |
切片lst[]=[] |
列表元素的排序
使用sort()函数
方法 | 描述 |
lst.sort() | 默认升序排序 |
lst.sort(reverse=True) | 降序排列(reverse指是否将列表倒置)。 |
lst.sorted() | 产生新列表,原列表不发生变化。也可指定参数reverse=True使其变为降序 |
lst.reverse() | 将列表进行反转。 |
列表生成式
生成式:[i*i for i in range()]
列表的相关方法
.count(元素)
- 统计列表中指定元素出现的次数,返回 int 类型
字典
形式:
- {‘key’:‘value’}:[^键值对的形式]
- 字典是无序排列的,通过键来取值
- 键和值可以是字符串、数字、元组等,不仅限于字符串
- 字典可以嵌套
字典的创建
- 使用 { } 的方式
scorse={'name':'张三','age':'20',True:true}
- 使用内置函数 dict()
scorse=dict(name='张三',age='20')
字典元素的获取
- 使用 [键] 的形式
name=scorse['name']
#若不存在,则显示KeyErorr
- 使用 字典的get()方法
name=scorse.get('name')
#若不存在,则返回NONE
- 获取字典试图
scorse.keys() | 获取键,返回dict_keys对象,该对象为可迭代对象,使用list函数将所有键放入列表中 |
scorse.values() | 获取值,返回可迭代对象 |
scorse.items | 获取所有对,返回可迭代对象,列表嵌套元组 |
keys=scorse.keys() #返回dict_keys对象 dict_keys(['张三'])
for i in keys:
print(i)
#将对象中的键依次打印输出
keys=list(keys) #keys=['张三']
字典元素的增删改
- 增加操作
- dictname [newkey]=value 如:
dict1['name']='张三'
- 字典的update方法:仅限于字典对象之间的合并,若dict2中有与dict1重复的键,则用dict2覆盖dict1
dict1={'name':'张三','gender':'男'}
dict2={'age':21,'class':5}
dict1.update(dict2)
#返回dict1={'name':'张三','gender':'男','age':21,'class':5}
- 修改操作
- dictname [oldkey]=value 如:
dict1['name']='李四'
- **删除操作:**使用del函数
- del(dictname[key])
字典的遍历
使用 for in 循环
for item in scorse:
print(item) #遍历的是key
print(scorse[key]) #通过key取value
scores={'张三':23,'王五':33,'李四':56}
items=scores.items()
print(items)
#items为dict_items([('张三', 23), ('王五', 33), ('李四', 56)])
for key,value in items: #数据解包,变量(key,value)的个数要与数据对应
print(key,value)
字典生成式
生成式: { key:value for key,value in zip(keys,values)}
keys=['张三','李四','王五']
values=[21,22,23]
people={name:age for name,age in zip(keys,values)}
#返回{'张三':'21','李四':'22','王五':‘23}
元组与集合
元组[^不可变类型,有序支持索引]
元组的创建:
- 使用 () 形式
- t=( ), ()可省略不写,但是元素间用逗号隔开,只有一个元素时,末尾也要加上逗号
- 使用内置函数 tuple( ( ) )
集合[^无序的结构]
集合的创建
- 使用s={}, 有键无值 —集合会自动去重,不允许出现重复的值
- 内置函数 set():
- s=set( ),括号内可以是range()、列表、元组、字符串等
集合增删改操作
- 增加
操作 | 描述 |
add() | 一次添加一个元素 |
update() | 至少添加一个元素,可以是集合、列表、元组(只能添加具有序列的数据类型) |
- 删除
操作 | 描述 |
remove() | 删除指定的元素 |
pop() | 随机删除 |
discard() | 指定删除,元素不存在也不会报错 |
clear() | 清空集合 |
集合取值
- 只能通过for循环取值
集合间的关系
操作 | 关系 |
==、!= | 是否相等 |
issubset() | 是否是子集 |
issuperset() | 是否是超集 |
isdisjoint | 是否是交集 |
程序组织结构
三个基本结构:
- 顺序结构
- 选择结构 if
- 循环结构 while、for in
选择结构if
- 单分支if结构
if answer='yes':
print('yes')
- 双分支结构
if answer='yes':
print('yes')
else: #除了if条件的其他情况
print('no')
- 多分支结构
if answer='yes':
print('yes')
elif answer='':
print('')
elif answer='no':
print('no')
else:
print('请重新输入')
- 嵌套if
if 条件:
if 内层条件:
内层执行体
else:
内层执行体
else:
执行体
循环结构
while循环
- 四部循环法:
- 初始化变量
- 条件判断
- 条件执行
- 改变变量
#求0~5的和
a=0 #初始化
while a<=5: #条件判断
sum += a #条件执行
a+=1 #改变变量
print(sum)
for in 循环
格式:for 自定义变量 in 可迭代对象:
sum=0
for item in range(1,101):
if item%2==0:
sum+=item
print('1-100之间的偶数和为:',sum)
for else 循环
for 循环体:
执行语句
else:
执行语句
#若for未通过break结束,则执行else语句
嵌套循环
#输出三行四列的矩形
for i in range(1,4):#三次大循环,行运行三次
for j in range(1,5):#四次小循环,每次输出四个星号,即四列
print('*',end='\t')#四个星号不换行
print('')
流程控制语句
- continue: 结束当前循环进入下一循环
for item in range(1,51):
if item%5!=0:#只有当结果为Ture时才进入循环,不是5的倍数时结果为true
continue#执行下一次循环
print(item)
- break:用于结束循环(只能结束最近的一个循环)
for pwd in range(3):
pwd=int(input('请输入六位密码'))
if pwd==443800:
print('密码正确')
break #整个循环结束,不再执行循环
else:
print('密码错误,请重新输入')
- else:
a=0
while a<3:
pwd=input('请输入密码')
if pwd=='443800':
print('密码正确')
break
else:
print('密码错误')
a+=1
else:
print('错误次数过多,请稍后再试')
- 嵌套循环中的break:
for i in range(1,6):
for j in range(1,101):
if j%3==0:
break #当遇到3的倍数时,结束小循环,回到大循环
#continue 遇到3的倍数时不执行打印,而是进行下一次循环
print(j,end='\t')
print('第',i,'次循环')
内置函数
range函数
用于生成整数序列
注意:
起始值start可大于stop,步长可以为-1
格式 | 描述 |
range(stop) | 默认从0开始,步长为1 |
range(start,stop) | 默认从0开始,步长为1 |
range(start,stop,step) | 默认从0开始,步长为step |
例:
r=range(3)
print(list(r))
#返回[0,1,2],不包含stop
for i in r:
print(i)
#range可用于表示循环次数,循环体执行3次
r=range(5,1,-1)
#表示从5开始,每次减1
pow函数
用于计算次方
格式:pow(x,i)
print(pow(4,2))
#返回4的2次方,16
len函数
可以计算长度
random函数
==格式:==random.randint(start,stop)
获取区间中的随机数
双闭区间,包括start和stop
abs与round
- abs:取绝对值
- round:取整数,四舍五入
map()–重点
==格式:==map(func,lst)
- 将传入的函数(规则)作用到lst的每一个元素中,并将结果组成新的列表(python2)/迭代器(python3)对象返回
==注意:==括号内func只需要输入函数名而不需要加括号,不加括号表示声明,只是告诉map函数要遵循func所定义的规则,加了括号则表示调用函数
例子:
lst=[1,2,3,4,5]
def func(x):
return x**2
result=map(func,lst)
result=map(lambda x:x**2,lst)
zip()–重点
组包:将两个序列一一对应打包,返回有序对象。如果两个数据的序列数不一样,将会按照最小的进行一一对应
例子:
lst1=[1,2,3]
lst2=[4,5,6]
result=zip(lst1,lst2)
print(list(result))
#案例
#使用循环将https://www.bbsmax.com/A/?user=7001&id=1305 中的user构建到7010,id到1314
#观察规律构建序列
user_count=range(7001,7011)
id_count=range(1305,1315)
combine=zip(list(user_count),list(id_count))
for user,id in combine:
url=f'https://www.bbsmax.com/A/?user={user}&id={id}'
print(url)
reduce()
需先 import functools
==格式:==reduce(func,lst)
对参数序列中元素进行累积。func必须有两个参数,每次func计算的结果继续和序列的下一个元素做累积计算
累积只,对前面两个参数根据规则进行相关操作,将结果保存并作为下一次操作的其中一个参数
例子:
#计算lst序列中各个数字的累加和
lst=[1,2,3,4,5]
def func(a,b):
return a+b #a*b a-b
result=functools.reduce(func,lst)
print(result)
filter()
==格式:==filter(func,lst)
用于过滤序列,过滤掉不符合条件的元素,**返回一个filter对象。**如果要转换为列表,可以使用list()来转换
例子:
lst=[1,2,3,4,5,6,7,8,9,10]
def func2(x):
return x%2 == 0
result=filter(func2,lst)
print(list(result))
eval()函数
eval是Python的一个内置函数,功能十分强大,这个函数的作用是,返回传入字符串的表达式的结果。就是说:将字符串当成有效的表达式 来求值 并 返回计算结果。
函数
函数可以提高代码的复用性,它是命名的用于区分的代码段,函数可以接受任何数字或其他类型的输入作为参数,并且返回数字或者其他类型的结果
简单函数
**函数:**就是封装了一段可被重复调用执行的代码块,通过此代码块可以实现大量代码的重复调用。
函数的使用包含两个步骤:
- 定义函数–封装独立的功能
- 调用函数–享受封装的成果
函数的定义
def function (arg1,arg2):
return 'something'
#取最大值
def get_max(num1,num1):
#max_num=None
if num1>num2:
#max_num=num1
return num1
else:
#max_num=num2
return num2
#return max_num
- **def:**定义函数的关键字
- **function:**函数名
- **agr1:**定义函数时的形式参数,没有具体的意义
- return:
- 关键字,返回函数的结果,以供其他代码使用
- 所有函数遇到return就会立马结束整个函数的执行
- 当函数返回多个值时,会以元组的形式返回
def ck(num):
odd=[]#用于存储奇数
even=[]#用于存储偶数
for i in num:
if i%2:
odd.append(i)
else:
even.append(i)
return odd,even
lst1=[23,45,89,65,22,14]
s=ck(lst1)
print(s)
#返回([23, 45, 89, 65], [22, 14])
函数的其他形式:
- 有参数有返回值
- 有参数无返回值:无return
- 无参数有返回值:数据在函数内已经设置完毕,函数只有一个结果,灵活性差
- 无参数无返回值
函数调用
#函数名()
function(a,b) #其中a,b是对应于agr1,agr2的,给函数传入的实际参数
参数传递:
- 位置传参:根据数据与参数对应的位置给参数赋值
def calc(a,b): #定义中的参数成为形式参数
c=a+b
return c
result=calc(10,20) #调用的参数成为实际参数
- 关键字传参:通过指定参数名字来为参数赋值
def fun3(a,b,c):
print('a=',a)
print('b=',b)
print('c=',c)
fun3(a=100,b=200,c=300)
- 默认参数:定义函数时可以指定参数的默认值,当调用没有传入对应参数,则使用参数的默认值
- 不定长参数:
- 个数可变的位置参数*args:用*定义,结果为元组
- 个数可变的关键字参数*kwargs:用**定义,返回值为字典
- 若两个一起定义,则要求位置形参放在关键字形参之前
def fun1(*args):#个数可变位置参数
print(args)
fun1(12,13,45,231)
def fun2(**args):
print(args)
fun1(12,13,45,231)
fun2(a=23,b=12,c=45)
#返回(12, 13, 45, 231),相当于传进去的参数是元组的形式,需要使用元组取值的方法来取值
#返回{'a': 23, 'b': 12, 'c': 45},相当于传进去的参数是字典形式,需要使用字典取值的方式来取值
规定:
当位置参数与关键字参数一起使用时,把位置参数放在前面
变量的作用域
- 全局变量:定义在函数体之外的变量,默认在函数体中不能修改全局变量的值。
num=10
def result():
global num #使用global来声明修改全局变量
num=20
return num
- 局部变量:定义在函数中的变量,需要return才可返回全局来使用
函数2
交换变量值
冒泡排序
#对给定的数值,将其从大到小排序,不能使用函数
def bubbleSort(num):
n=len(num)
for i in range(n): #有n个数,需要循环n次
for j in range(0,n-1): #构造索引
#print(i,j)
if num[j]>num[j+1]: #将前一个数与后一个数相比较,若条件成立则交换值
num[j],num[j+1]=num[j+1],num[j] #交换值之后继续往后比较,直到索引n-2与n-1进行比较,比较之后进行下一次大循环
print('-'*30)
return num
lst1=[23,45,34,78,56,12,66,44,70,9,3,2]
print(bubbleSort(lst1))
递归函数
- 找到结束条件
- 找到等价的等式
特点:
- 自己调用自己
- 必须设置停止条件
案例:
- 累加与阶乘
- 斐波那契数列
lambda表达式
如果一个函数只有一个返回值,并且只有一句代码,可以使用lambda简化
语法:
lambda 参数:表达式/返回值
注意:
- lambda表达式的参数可有可无,函数的参数在lambda表达式中完全适用
- lambda表达式能接收任何数量的参数,但只能返回一个表达式的值
lambda的参数形式:
- 无参数形式
- 有参数形式
- 一个参数形式
- 默认参数:可以设置参数的默认值
- 可变参数
例子:
# 通过函数返回100(无参数)
func=lambda :100
func()
#lambda函数是没有名字的,可以用一个变量接收lambda函数,这个变量就是函数的名字
# 求和(有参数)
func2=lambda a,b:a+b
func2(3,4)
# 默认参数
func3=lambda a,b=5,c=10:a,b,c
# 不定长参数
func4=lambda *args:args
func5=lambda **kwargs:args
lambda的条件判断:
lambda num1,num2:num1 if num1>num2 else num2
python文件操作
步骤:
- 打开文件
- 读写等操作
==注意:==文件只允许写入字符串,不允许写入对象等 - 关闭文件
- 打开
open(filename,mod,encoding,newline)
- filename:文件路径
- 相对路 径:相对于py文件当前所在的路径
- 绝对路径:从盘符的根目录开始
- mod:操作模式,windows默认编码是gbk
模式 | 描述 |
- encoding:编码格式
- newline
- 读写操作
- 只能写入字符串和二进制数据
- 文件对象常用方法 :
方法 | 描述 |
- with上下文管理器 ,
with open()
- 有自己的代码块
- 不需要关闭文件,当文件操作完毕,上下文管理器会自动关闭文件
- 备份文件
#代码实现
#设置新文件名
old_name=input('请输入要备份的文件名')
#获取.的索引
index=old_name.index('.')
#切片操作来获取后缀名,也可以用split分割
postfix=old_name[index:]
new_name=old_name[:index]+'[备份]'
new_file=new_name+'.txt'
old_file=open(old_name,'r',encoding='utf-8')
new_file=open(new_file,'w',encoding='utf-8')
new_file.write(old_file.read())
old_file.close()
new_file.close()
- 目录操作
- 需要导入python内置模块os,
import os
- 常用操作:
操作 | 描述 |
rename(oldname,newname) | 将旧的文件名替换为新的文件名 |
- 深浅拷贝:import copy
copy.copy()
,拷贝后产生新对象,指向新的id地址
- 浅拷贝:只能拷贝到一维数据,当存在嵌套数据时,嵌套数据指向的还是同一个id地址
- 深拷贝:将每个维度的内容都拷贝,所有数据都指向新的id地址
- 应用场景:在循环中操作同一对象
data={
'cate':'童书馆',
'sub_cate':None
}
sub_cate=['科普百科','儿童文学','幼儿启蒙','动漫卡通','少儿英语']
all_data=[]
for cate in sub_cate:
data['sub_cate']=cate
all_cata.append(copy.copy(data))
#若直接append(data)则其中的sub_cate相同,为'少儿英语'
#这是因为,append到all_data里的data,其实是对象引用,他们具有相同的id地址,因此修改其中一个时,所有的会一起改变。
pprint.pprint(data)
面向对象
类与对象
**类(class)**是面向对象升序设计实现信息封装的基础,包含由各特殊的事物或现象抽出来的共同点。
对象是单个事物的抽象,是一个容器,封装了属性(property)和方法(method),是一个类里面的具有自己特点的个体。python中一切皆对象
个人理解:
类的创建
class 类名(object): #括号中代表创建的类所继承的父类
属性
类方法
class Student:
native_place='吉林' #类属性
#初始化函数在基于类创建对象时会默认被调用
#创建的对象称为类的实例对象
def __init__(self,name,age):
self.name=name #name,age称为实例属性,self为对象,进行了赋值操作,将name赋值给实例对象
self.age=age
#实例方法,在类中定义的函数
def eat(self):
print('学生在吃东西')
#静态方法,用staticmethod声明,括号中不能填东西
@staticmethod
def drink():
print('学生在喝水')
#类方法,用classmethod声明,cls指代的是类属性
@classmethod
def cm(cls):
print('我是类方法,我用classmethod声明')
- 属性:
- 类属性:该类的所有对象所共享的属性
- 实例属性:创建对象时传入的属性
- 方法:
- 实例方法:类对象中使用def定义的函数
- 类方法:使用@classmethod声明的方法,传入类属性作为参数
- 静态方法:
- 使用@staticmethod声明的方法,不用传入参数
- 它不需要访问实例属性或调用实例方法
- 不需要访问类属性或调用类方法
__init__
:初始化方法
- 创建对象时默认调用该方法,相当于为对象提供了内部变量
- __init__方法的参数可以多种形式来完成赋值
- 可以传入常规变量
- 可以传入对象,并且在编写实例方法的时候,还可以调用传入对象的属性,并对其进行相关操作
stu1=Student('张三',23)
class Student(): #接上边的对象
def eat(self,obj_stu):
print('{self.name}在吃{obj_stu.name}的东西')
#将stu1对象作为参数传入,在方法中调用对象的属性
self
:指代的是实例对象
创建实例对象
stu1=Student('张三',21) #创建了一个对象student1
#由于类中指定了实例对象,所以创建对象时必须传入相应的参数
stu2=Student('王五',22)
stu3=Student('李四',23)
属性与方法的调用
#实例方法调用
stu1.eat()
Student.eat(stu1) #类对象调用实例方法时,必须传入实例对象作为参数
#实例属性调用
stu1.name
#'-----------类方法与静态方法的使用-----------------'
#直接使用类名
Student.drink()
Student.cm()
#通过对象调用
stu1.drink()
stu1.cm()
动态绑定属性与方法
# 动态绑定属性
stu2.gender='男' #为stu2对象绑定gender属性,并将其设置为'男',不会影响其他对象
print(stu2.name,stu2.age,stu2.gender)
print(stu3.name,stu3.age)
# 类属性的修改
# 将所有类的属性进行修改
print(stu2.native_place)
Student.native_place='天津' #修改之后的籍贯,调用后也会改变
print(stu3.native_place)
# 只修改类中的其中一个对象
stu1.native_place='山东'
# 动态绑定方法
def show():
print('定义在类之外,我是函数')
stu3.show=show #为stu3对象绑定show方法,并将show函数赋值给show方法
stu3.show()
类与继承
**继承:**子类会将父类的属性与方法全部继承,即子类拥有父类的属性和方法,可在子类中调用父类的属性和方法
单继承与多继承
单继承
类的继承关系除object之外只有一个
class Master:
def __init__(self):
self.secret='[古法煎饼果子配方]'
def make_cake(self):
print(f'使用{self.secret}制作了煎饼果子')
class Apprentice(Master): #只继承一个类,所以是单继承
pass
多继承
class Master:
def __init__(self):
self.secret='[古法煎饼果子配方]'
def make_cake(self):
print(f'使用{self.secret}制作了煎饼果子')
class School:
def __init__(self):
self.secret='[青灯煎饼果子配方]'
def make_cake(self):
print(f'使用{self.secret}制作了煎饼果子')
class Apprentice(Master,School): #继承一个以上的类,所以是多继承
pass
app1=Apprentice()
app1.secret
'''
1.当继承的父类中存在同名的属性与方法时,在调用父类属性或方法的过程中,会优先调用先继承的(如以上的Master)父类属性或方法
2.继承的父类中存在不同名的属性或方法:
在调用父类的属性与方法时,会优先在先继承的父类中查找是否存在所调用的属性或方法,若不存在则报错,不会查找第二个继承的父类
'''
重写与调用父类的同名属性和方法
class Person():
def __init__(self,name,age):
self.name=name
self.age=age
def info(self):
print('姓名:{0},年龄:{1}'.format(self.name,self.age))
# 定义子类
class Student(Person):
def __init__(self,name,age,stu_no):
#用super调用父类的方法
super().__init__(name,age)
self.stu_no=stu_no #重写属性:在继承的基础上,添加了一个属性
def info(self):
print('学号为:{0}'.format(self.stu_no)) #重写方法:在方法中添加了一个操作
super().info()
#也可以使用 父类名.方法/属性 的方式来调用
#Person.info(self)
class Teacher(Person):
def __init__(self,name,age,teachofyear):
super().__init__(name,age)
self.teachofyear=teachofyear
def info(self):
super().info()
print('教龄为:{0}'.format(self.teachofyear))
#创建对象、调用方法
stu=Student('张三',21,'1001')
teacher=Teacher('王五',35,10)
stu.info()
teacher.info()
多层继承
一次一次地进行继承与方法重写
如:
Person继承父类Human
Student继承父类Person
super()
调用父类方法与属性
类与对象封装
多态
是一种使用对象的方式,子类重写父类方法,调用不同类对象的相同父类方法,可以产生不同的执行结果
class Dog:
def __init__(self,name):
self.name=name
def work(self):
pass
class ArmyDog(Dog):
def __init__(self,name):
super().__init__(name)
def work(self):
print('追击敌人-----')
class DrugDog(Dog):
def __init__(self,name):
super().__init__(name)
def work(self):
print('搜寻毒品-----')
class Person:
def work_with_dog(self,dog): #将一个对象作为参数传入,可以调用对象的属性与放啊
print('正在与{dog.name}')
dog.work()
dog1=ArmyDog('警犬')
dog2=DrugDog('缉毒犬')
person1=Person()
person1.work_with_dog(dog1) #调用此方法时,传入dog1对象
person1.work_with_dog(dog2)
'''
正在与警犬
追击敌人-----
正在与缉毒犬
搜寻毒品-----
'''
案例:使用对象封装的方式实现学生信息管理系统
需求:
- 系统要求:学员数据储存在文件中
- 系统功能:添加学员,删除学员,修改信息,查询信息,显示所有,保存及退出
实现:
- 方法一:
- 封装学生类对象
- 封装系统对象
- 初始化系统:空列表
- 添加学生等函数对象
- 方法二:数据模型思路
- –封装数据模型相当于建立数据库,其有自身的属性(数据类型)和对数据进行处理的方法。将这些属性与方法定义好之后,在系统类的操作中,只要遇到与数据处理有关的操作,都可以通过调用数据模型中的方法来实现–
- 封装学生数据模型:定义数据类型与数据模型的相关方法
- 封装系统对象:在数据处理时调用数据模型对象的方法
模块封装与异常处理
模块的导入
- import 模块名 [as 别名]:
import math
- from 模块名 import 功能 [as 别名]:
from math import sqrt
,可直接引用sqrt()功能,不需要使用模块名 - from 模块名 import *:
from math import *
,导入该模块的所有功能与属性
制作模块
注意:
- 命名规则:不能以数字开头
- 在导入模块时相当于将模块中的代码复制,若导入的模块中存在函数的调用,则程序在运行时也会执行模块中的相关操作,可以在模块文件中进行相关声明
# 新建名为 calc1.py的python文件
def add(a,b):
return a+b
def div(a,b):
return a/b
# 新建calc2.py文件
def add(a,b):
return a+b
if __name__ == '__main__': #用于声明,只有在calc2作为主程序运行时,此代码才会运行
print(add(10, 20)) #在测试代码时使用
# 新建mod_test.py文件
# import calc 并调用相关方法 #直接导入只能用于同路径下的文件,不同路径下的文件需要使用相对路径,且导入的必须是包
import calc1
print(calc1.add(100,200))
import calc2
print(calc2.add(2,3)) #直接导入calc2时,其中的代码也会运行,因此需在源代码中声明
制作包
包将有联系的模块组织在一起,即放到同一个文件夹下,并且在这个文件夹创建一个名字为
__init__py
文件,那么这个文件夹就称之为包
步骤:
- 新建python软件包
- 在包下,创建py文件
# 新建python软件包,并在软件包下创建moudleA.py 文件
a=10
#新建 bao_test.py 文件,导入包中的模块,并引用属性
import import package1.modoulA as ma
print(ma.a)
**案例:**学生信息管理系统的封装
异常处理
try except
try:
可能发生异常的代码
except [可以指定错误类型/Exception] as [别名]: #不指定的表示,捕获所有类型的错误,可以为异常起别名
发生异常时执行的操作
对象
+ 初始化系统:空列表
+ 添加学生等函数对象
- 方法二:数据模型思路
- –封装数据模型相当于建立数据库,其有自身的属性(数据类型)和对数据进行处理的方法。将这些属性与方法定义好之后,在系统类的操作中,只要遇到与数据处理有关的操作,都可以通过调用数据模型中的方法来实现–
- 封装学生数据模型:定义数据类型与数据模型的相关方法
- 封装系统对象:在数据处理时调用数据模型对象的方法
模块封装与异常处理
模块的导入
- import 模块名 [as 别名]:
import math
- from 模块名 import 功能 [as 别名]:
from math import sqrt
,可直接引用sqrt()功能,不需要使用模块名 - from 模块名 import *:
from math import *
,导入该模块的所有功能与属性
制作模块
注意:
- 命名规则:不能以数字开头
- 在导入模块时相当于将模块中的代码复制,若导入的模块中存在函数的调用,则程序在运行时也会执行模块中的相关操作,可以在模块文件中进行相关声明
# 新建名为 calc1.py的python文件
def add(a,b):
return a+b
def div(a,b):
return a/b
# 新建calc2.py文件
def add(a,b):
return a+b
if __name__ == '__main__': #用于声明,只有在calc2作为主程序运行时,此代码才会运行
print(add(10, 20)) #在测试代码时使用
# 新建mod_test.py文件
# import calc 并调用相关方法 #直接导入只能用于同路径下的文件,不同路径下的文件需要使用相对路径,且导入的必须是包
import calc1
print(calc1.add(100,200))
import calc2
print(calc2.add(2,3)) #直接导入calc2时,其中的代码也会运行,因此需在源代码中声明
制作包
包将有联系的模块组织在一起,即放到同一个文件夹下,并且在这个文件夹创建一个名字为
__init__py
文件,那么这个文件夹就称之为包
步骤:
- 新建python软件包
- 在包下,创建py文件
# 新建python软件包,并在软件包下创建moudleA.py 文件
a=10
#新建 bao_test.py 文件,导入包中的模块,并引用属性
import import package1.modoulA as ma
print(ma.a)
**案例:**学生信息管理系统的封装
异常处理
try except
try:
可能发生异常的代码
except [可以指定错误类型/Exception] as [别名]: #不指定的表示,捕获所有类型的错误,可以为异常起别名
发生异常时执行的操作
==python报错:==层级报错,因此只需要找自己写的代码的错误,不需要关注模块内部运行的错误
声明:
此文章仅仅记录学习过程
内容并不百分百准确,读者需自行尝试验证
欢迎提出建议与看法