文章目录

  • 变量与数据类型
  • 变量
  • 定义与使用
  • 变量的多次赋值
  • 数据类型
  • 整数类型[^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

是否是交集

程序组织结构

三个基本结构

  1. 顺序结构
  2. 选择结构 if
  3. 循环结构 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])

函数的其他形式:

  1. 有参数有返回值
  2. 有参数无返回值:无return
  3. 无参数有返回值:数据在函数内已经设置完毕,函数只有一个结果,灵活性差
  4. 无参数无返回值

函数调用

#函数名()
function(a,b)  #其中a,b是对应于agr1,agr2的,给函数传入的实际参数

参数传递:

  1. 位置传参:根据数据与参数对应的位置给参数赋值
def calc(a,b): #定义中的参数成为形式参数
    c=a+b
    return c
result=calc(10,20) #调用的参数成为实际参数
  1. 关键字传参:通过指定参数名字来为参数赋值
def fun3(a,b,c):
    print('a=',a)
    print('b=',b)
    print('c=',c)
fun3(a=100,b=200,c=300)
  1. 默认参数:定义函数时可以指定参数的默认值,当调用没有传入对应参数,则使用参数的默认值
  2. 不定长参数
  • 个数可变的位置参数*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))

递归函数

  • 找到结束条件
  • 找到等价的等式

特点:

  • 自己调用自己
  • 必须设置停止条件

案例:

  1. 累加与阶乘
  2. 斐波那契数列

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文件操作

步骤:

  1. 打开文件
  2. 读写等操作
    ==注意:==文件只允许写入字符串,不允许写入对象等
  3. 关闭文件
  • 打开
  • 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报错:==层级报错,因此只需要找自己写的代码的错误,不需要关注模块内部运行的错误

声明:
此文章仅仅记录学习过程
内容并不百分百准确,读者需自行尝试验证
欢迎提出建议与看法