模块 类与对象 11月27-12月2日

模块 类与对象

模块

  • 内置模块 time, random, os,json
  • 第三方模块 requests, pandas,numpy
  • 自定义模块 xxx.py

常见的内置模块

hashlib 模块

该模块主要是进行数据加密的作用。

  • 常见的加密方式:sha256()【可逆】 md5()【不可逆】
import hashlib

info = '123456'
# 创建hashlib中的加密对象
md5_obj = hashlib.md5()
# 设置编码
md5_obj.update(info.encode('UTF-8'))
# 调用函数,开始加密
mi_wen = md5_obj.hexdigest()
print(f"明文:{info},通过md5加密后得到密文:
{mi_wen}") #
e10adc3949ba59abbe56e057f20f883e

一般情况下,在企业中,若想要对一个明文进行MD5

加密的话,一般都不是直接进行加密,而是先对名进

加盐操作,之后才会进行md5加密。

import hashlib

info = '123456'

# 创建hashlib中的加密对象
md5_obj = hashlib.md5('shujia'.encode('UTF-
8')) # 加盐操作
# 设置编码
md5_obj.update(info.encode('UTF-8'))
# 调用函数,开始加密
mi_wen = md5_obj.hexdigest()
print(f"明文:{info},通过md5加密后得到密文:
{mi_wen}") #
0ead149c250ec554aff85fa083312a83

json模板

本质上是一个特殊格式的字符串,但是相比较于字符

串而言,json是可以通过键获取值的。

判断一个字符串是否符合json的格式:

  • 看字符串是否是由双引号括起来,若不是,那么该

字符串转不了json格式数据

  • 若值是由小括号括起来的多个元素,也是不能够转

json格式数据的

序列化和反序列化

  • 序列化:将代码中的数据转化成网络中传输的数据流

    【python中的字典数据 --> json格式的字符串】

dict1 = {
    'name': '黄沪生',
'age': 18,
'likes': ['踢足球','钓鱼','打游戏'],
'pets': [{'name': '小花','age': 2},
{'name': '小黑','age': 3}]}

s3 = json.dumps(dict1, ensure_ascii=False)
print(s3, type(s3))
  • 反序列化:将网络中传输的数据流还原成代码中的数

    据格式 【json格式的字符串 --> python中的字典数

    据】

    s2 = '''
    {"name":"黄沪生","age":18,"likes":["踢足球","钓鱼","打游戏"]}
    '''
    
    print(s2, type(s2))
    # print(s2['age'])
    res1 = json.loads(s2)
    print(res1, type(res1)) # {'name': '黄沪生','age': 18,'likes': ['踢足球','钓鱼','打游戏']} <class 'dict'>
    print(res1['likes']) # ['踢足球','钓鱼','打游戏']
    

时间相关的模块

time

import time

res1 = time.time() # 得到的是一个时间戳格式的数据
print(res1, type(time)) # 2024-11-29
10:45:58

时间戳存储时占用的字节相比较于格式化后的字符串而言,是少很多的。

datetime

![datetime 时间戳 字符串之间转换](C:\Users\asus\Desktop\上课课间以及文件\datetime 时间戳 字符串之间转换.png)

时间戳,datetime, 格式化日期字符串互相转换

# '2024年11月29日 10时51分00秒'
# datetime -> str 日期格式化
res1 = datetime.strftime(s1,
'%Y-%m-%d
%H:%M:%S')
print(res1)
print("-------------------------------")
# time.time()
# 时间戳 -> datetime
tp = time.time() # 当前的时间戳
print(tp)
res2 = datetime.fromtimestamp(tp)
print(res2, type(res2))
# datetime -> str
res3 = datetime.strftime(res2,
'%Y/%m/%d
%H:%M:%S')
print(res3, type(res3))
print("-------------------------------")
# 字符串 -> datetime
s2 = '2024/11/29 11:02:28'
d2 = datetime.strptime(s2,
'%Y/%m/%d
%H:%M:%S')
print(d2, type(d2))
# datetime-> 时间戳
tp2 = d2.timestamp()
print(int(tp2))

date还有一种方式可以时间获取年月日时分秒, 使用datetime对象中的属性

tp = 1732849348
dt1 = datetime.fromtimestamp(tp)
print(f"{dt1.year}{dt1.month}{dt1.day}
{dt1.hour}{dt1.minute}{dt1.second}秒")

os模块

使用os模块中的功能操作文件或者文件夹

  • 判断目标是否存在
import os
# data/user_info
b =
os.path.exists('E:\\projects\\PycharmProjec
ts\\bigdata33\\base\\day07\\data\\user_info
')
print(b) # True
  • 路径拼接
s1 = os.path.join('data','user_info1')
print(s1,type(s1))

if os.path.exists(s1):
    f = open(s1,'r',encoding='UTF-8')
    text1 = f.read()
    print(text1)
else:
    print("目标路径不存在!")
  • 获取当前文件所在的路径
ml1 = os.path.abspath(__file__) # __file__
代表的是当前的文件
print(ml1, type(ml1)) #
E:\projects\PycharmProjects\bigdata33\base\
day07\os_demo.py
  • 获取某一个文件所处的父级目录路径
ml2 = os.path.dirname(ml1)
print(ml2,type(ml2)) #
E:\projects\PycharmProjects\bigdata33\base\
day07
  • 判断一个路径是否是文件
ml1 = os.path.abspath(__file__) # __file__
代表的是当前的文件
print(ml1, type(ml1))

ml2 = os.path.dirname(ml1)
print(ml2,type(ml2))

print(os.path.isfile(ml1)) # True
print(os.path.isfile(ml2)) # False
  • 判断一个路径是否是文件夹
ml1 = os.path.abspath(__file__) # __file__
代表的是当前的文件
print(ml1, type(ml1))

ml2 = os.path.dirname(ml1)
print(ml2,type(ml2))

print(os.path.isdir(ml1)) # False
print(os.path.isdir(ml2)) # True
  • 创建一个文件夹
lj1 = os.path.join('data','aaa')
os.mkdir(lj1)

注意:

  • 若要创建一个文件夹,使用os模块中的mkdir函数

  • 若要创建一个文件,使用open函数以写的方式打

ml1 = os.path.abspath(__file__) # __file__
代表的是当前的文件
ml2 = os.path.dirname(ml1)
res1 = os.walk(ml2)
'''
a1: 表示遍历到的文件夹的名称
b1: 表示遍历到的文件夹下所有的文件夹名称组成的列表
c1: 表示遍历到的文件夹下所有的文件名称组成的列表
'''
for a1,b1,c1 in res1:
    print(f"a1:{a1}")
    print(f"b1:{b1}")
    print(f"c1:{c1}")
    print("----------------------")
  • 删除路径

    • 若目标路径是一个文件
    lj1 = os.path.join('data','bbb')
    os.remove(lj1)
    
    • 若目标文件是一个文件夹
    lj1 = os.path.join('data','aaa')
    os.rmdir(lj1)
    
  • os模块练习

    • 练习1:企业中有一个网站,每一天都有新的用户

      注册,要求每一天需要使用一个新的文件存储当天

      注册的用户信息。

      import os.path
      import time
      import utils.login_tool as tool
      from datetime import datetime
      
      # 定义一个全局变量
      USERS_MU_LU =
      os.path.join('data','user_regs')
      
      
      def run():
          # 判断用户存储信息的文件父级目录是否存在,若
      不存在创建一个
          if not os.path.exists(USERS_MU_LU):
              os.mkdir(USERS_MU_LU)
          # 获取当天的时间
          # 1732776554 2024-11-28
          d=datetime.fromtimestamp(1732776554).strfti
      me('%Y-%m-%d')
          file_name = os.path.join(USERS_MU_LU,
      d)
          if not os.path.exists(file_name):
          f =open(file_name,'w',encoding='UTF-8')
          f.close()
          print("欢迎注册".center(50,'-'))
          name = input("请输入您要注册的姓名: ")
          pwd = input("请输入新密码: ")
          pwd = tool.md5_pwd(pwd)
          withopen(file_name,'a',encoding='UTF-8') as
      f:
              f.write(f"{name}|{pwd}\n")
              f.flush()
          time.sleep(3)
          print("用户注册成功!")
      
          
      if __name__ == '__main__':
          run()
      
    • 加入判断该用户是否在之前已经注册过?

    • 融合之前的登录注册案例。

    • 练习2:购票,一个用户购票的记录使用一个文件

      存储,判断这个用户是否是新用户;不仅可以订

      票,还可以查看历史记录。

    # 企业中有一个网站,每一天都有新的用户注册,要求
    每一天需要使用一个新的文件存储当天注册的用户信息。
    import os.path
    import time
    import utils.login_tool as tool
    from datetime import datetime
    
    # 定义一个全局变量
    USERS_MU_LU =
    os.path.join('data','user_regs')
    
    def run():
    # 判断用户存储信息的文件父级目录是否存在,若不存在创建一个
        if not os.path.exists(USERS_MU_LU):
            os.mkdir(USERS_MU_LU)
        # 获取当天的时间
        # 1732776554 2024-11-28
    d =datetime.fromtimestamp(1732776554).strfti
    me('%Y-%m-%d')
        file_name = os.path.join(USERS_MU_LU,
    d)
        if not os.path.exists(file_name):
            f =open(file_name,'w',encoding='UTF-8')
            f.close()
        print("欢迎注册".center(50,'-'))
        name = input("请输入您要注册的姓名: ")
        pwd = input("请输入新密码: ")
        pwd = tool.md5_pwd(pwd)
        with
    open(file_name,'a',encoding='UTF-8') as
    f:
            f.write(f"{name}|{pwd}\n")
            f.flush()
    
            time.sleep(3)
            print("用户注册成功!")
    
    if __name__ == '__main__':
        run()
    

递归

概述:方法定义时,内部调用自身的一个现象

注意:递归要有一个出口,否则就是一个死递归

'''
从前有座山,山里有座庙,庙里有个老和尚,老和尚在给小
和尚讲故事,讲的故事内容是: 故事1
从前有座山,山里有座庙,庙里有个老和尚,老和尚在
给小和尚讲故事,讲的故事内容是: 故事2
从前有座山,山里有座庙,庙里有个老和尚,老
和尚在给小和尚讲故事,讲的故事内容是: 故事3
从前有座山,山里有座庙,庙里有个老和
尚,老和尚在给小和尚讲故事,讲的故事内容是:故事4
          。。。


'''

例子

# 求5的阶乘 5! = 5*4*3*2*1
def jie_cheng(n):
    if n==1:
        return 1
    else:
        return n * jie_cheng(n-1)

res1 = jie_cheng(5)
print(res1)

异常

在python程序中出现不正常的情况

  • python中默认遇到异常的处理方案:抛出错误,

    程序停止,后续代码不会执行。

异常的分类

  • 语法错误(Syntax errors) 未运行之前出现的错误

    • 会在程序编写的过程中,出现了错误【例如

      pycharm会在错误的语法下出现红色下划线】

  • 异常(Exceptions)

    • 在程序运行过程中,出现了问题

异常的处理方案

  • try...except...语句
try:
    list1 = [1, 2, 3]
    print(list1[7])
except:
    print("出错啦!!!")

print("hello world")

try中的代码,若程序运行过程中出错,那么就会执行

except中的语句体,若没有出错,except语句体不会

执行。不管try中的代码有没有出错,整个python程

序正常运行。

当try中的代码,若程序运行过程中出错,且try中还

有其他的代码的时候,不会执行。

  • try...except...else语句
try:
    list1 = [1, 2, 3]
    print(list1[7])
    print("黄沪生真帅!")
except:
    print("出错啦!!!")
else:
    print("好好学习,天天向上!")

print("hello world")

只有当try中的代码不报错的时候,才会执行else中的代码

  • finally子句
try:
    list1 = [1, 2, 3]
    print(list1[1])
    print("黄沪生真帅!")
except:
    print("出错啦!!!")
else:
    print("好好学习,天天向上!")
finally:
    print("数加666")

print("hello world")

无论try中的代码是否报错,finally中的代码都会执

行。

finally中一般情况下存放释放资源的代码逻辑

异常的使用场景

异常可以帮助我们替换一些复杂的判断场景

import random
list1 = ['小虎','张成阳','黄涛','方直','杨浩东','黄沪生','查镕贤']
jiang_xiang = [('一等奖', 1,'mate70 pro'),
('二等奖', 1,'小米手环'),
('三等奖', 2,'按摩仪'),
('四等奖', 2,'京东购物卡')]
def chou_jiang(l1):
    for i, num, goods in jiang_xiang:
        print(f"正在抽取{i}".center(50,'-'))
        name_list = random.sample(l1,num)
    # 将中奖名单从原名单中删除
        for n in name_list:
            if n in l1:
                l1.remove(n)
info = f"恭喜{','.join(name_list)}中得{i}!!!!"
yield info
res1 = chou_jiang(list1)
try:
    for i in range(len(jiang_xiang)):
        input(f"开始抽{i+1}等奖....按下回车开始!")
        print(res1.__next__())
    print(res1.__next__())
except:
    print("所有奖项抽取完毕!!")

类和对象

面向对象概述

面向过程的编程思想:每一步的实现过程都是我们一步一步
参与实现的,相当于参与者
【代表语言:C语言】
面向对象的编程思想:我们在自己程序中,创建别人写好类
的对象,调用别人写好的功能,相当于指挥者
【代表语言:java,python】
举例现实生活中面向对象的例子:
吃饭:
面向过程的角度:自己买鸡蛋,自己打鸡蛋,自
己煮饭,自己将蛋和饭一起炒,自己装盘
面向对象的角度:点一份蛋炒饭,饭店人员完成
上面的事情
接水:
面向过程的角度:自己拿起水杯,走到饮水机面
前,选择热水还是冷水,接水
面向对象的角度:祈求同桌接水,剩下事情,由
同桌这个对象去完成
如何在python中描述或者使用现实生活中的一个对象呢?
1. 需要我们先创建一个概念性的东西,用于描述某一种所
有对象的共同特点,在python中称之为类 class
2. 我们就可以根据创建好的类,来创建若干个对象
世间万物,皆为对象,同一种对象之间,会有相同的特点,
都可以使用属性和行为对任意一个对象进行描述。
人: class
Person:
    属性:姓名,年龄,性别...
成员变量:name,age,gender
行为:吃饭,睡觉,学习...
成员方法:eat(),sleep(),study()

在python中使用类描述一个事物

示例1:创建一个类

# 错误的写法
class Person:
    def eat():
        print("吃饭")
    def call(name):
        print(f"打电话给{name}")

注意:class类中的函数,必须要有一个参数,且是第

一个定义,self

self: 表示当前调用该方法的对象

# 定义一个类
class Person:
    def eat(self):
        print("吃饭")

    def call(self,name):
        print(f"打电话给{name}")

示例2:通过一个类创建一个对象

class Person:
    def eat(self):
        print("吃饭")

    def call(self,name):
        print(f"打电话给{name}")
# 相当于创建一个Person类的对象,将对象的地址值赋值
给变量p1
p1 = Person()
p1.eat()
p1.call('马云')

示例3:通过一个类创建多个对象

类相当于一个汽车图纸,而创建出来的一个一个对象,是占用不同的内存空间,每个对象内部都有自己的属性和行为。

class Person:
    def eat(self):
        print("吃饭")
    def call(self,name):
        print(f"打电话给{name}")
# 相当于创建一个Person类的对象,将对象的地址值赋值
给变量p1
p1 = Person() # 在内存中开辟一个新的空间
p1.eat()
p1.call('马云')
print("----------------------------")
p2 = Person() # 在内存中开辟一个新的空间
p2.eat()
p2.call('马云')
print(id(p1)==id(p2)) # False 地址值不同

示例4:给对象赋予属性

  • 类中不写,创建对象的之后,单独为该对象创建新的

    属性

class Person:
    def eat(self):
        print("吃饭")

    def call(self,name):
        print(f"打电话给{name}")

p1 = Person()
p1.name = '小虎'
print(f"p1对象的姓名为:{p1.name}")
p2 = Person() # 在内存中开辟一个新的空间
# print(f"p1对象的姓名为:{p2.name}") # 报错
  • 类中编写,创建对象的时候,直接就拥有了某个属性,并且可以直接赋值

在python中创建一个类的对象的时候

# 使用类名() 的方式创建对象,实际上底层调用的是类中
的__init__(self)
# 若自己没写,默认一个类中有一个__init__(self),且
只能有一个

class Person:
    def __init__(self,name):
# self.name 定义一个类中的属性,叫做name
        self.name = name
    def eat(self):
        print("吃饭")
    def call(self,name):
        print(f"打电话给{name}")
# 使用类名() 的方式创建对象,实际上底层调用的是类中
的__init__(self)
# 若自己没写,默认一个类中有一个__init__(self),且
只能有一个
p1 = Person('小虎')
print(f"p1对象的姓名为:{p1.name}")
p2 = Person('张三')
print(f"p2对象的姓名为:{p2.name}")

# 手机
'''
手机:
属性: 品牌, 价格, 颜色
行为:打电话, 发短信
'''

class Phone:
def __init__(self, brand, price,color):
    self.brand = brand
    self.price = price
    self.color = color
    def call(self):
        print("打电话")
    def send_message(self):
        print("发短信")

# 创建第一部手机
p1 = Phone('小米15 pro', 5799,'黑色')
print(f"手机的品牌为:{p1.brand}, 价格:{p1.price}, 颜色:{p1.color}")
p1.call()
p1.send_message()

面向对象编程那些改进场景

可以改进多个传参的问题

def fun1(a1,b1,c1,d1):
    pass
def fun2(a1,b1,c1,d1):
    pass
def fun3(a1,b1,c1,d1):
    pass
fun1(11,22,33,44)
fun2(11,22,33,44)
fun3(11,22,33,44)
class Demo:
# 构造函数
def __init__(self,a1,b1,c1,d1):
    self.a1 = a1
    self.b1 = b1
    self.c1 = c1
    self.d1 = d1

    def fun1(self):
        print(f"a1:{self.a1},b1:{self.b1},c1:{self.c1},d1:{self.d1}")

    def fun2(self):
        print(f"a1:{self.a1},b1:{self.b1},c1:{self.c1},d1:{self.d1}")
    def fun3(self):
        print(f"a1:{self.a1},b1:{self.b1},c1:{self.c1},d1:{self.d1}")

d1 = Demo(11,22,33,44)
d1.fun1()
d1.fun2()
d1.fun3()

改进某一个事物的封装

'''
list1 = [{'name':'张三1,'age': 18},
{'name':'张三2','age': 19},
{'name':'张三3','age': 20},
{'name':'张三4','age': 21},
    ...
]
'''
user_list = []
while True:
    name = input("请输入用户的姓名:")

    user_dict = {}
    if name.upper()=='Q':
        break
    age = input("请输入用户的年龄:")
    user_dict['name'] = name
    user_list.append(user_dict)
    
print(user_list)
'''
list1 = [
p1,
p2,
p3,
...
]
'''
class Person:
    def __init__(self,n1,a1):
        self.name = n1
        self.age = a1
    def eat(self):
        print("吃饭")

    def sleep(self):
        print("睡觉")

user_list = []
while True:
    name = input("请输入用户的姓名:")
    if name.upper()=='Q':
        break
    age = input("请输入用户的年龄:")
    # 创建一个学生对象
    p = Person(name,age)
    user_list.append(p)

for per in user_list:
    print(f"姓名:{per.name}, 年龄:{per.age}")

若直接使用对象名, 默认调用的是一个class类中的杠杠__str__杠杠() 函数

'''
list1 = [
    p1,
    p2,
    p3,
    ...
]
'''
class Person:
    def __init__(self,n1,a1):
        self.name = n1
        self.age = a1
    
    def eat(self):
        print("吃饭")
    def sleep(self):
        print("睡觉")
    # 该函数将来在直接使用对象名的时候,自动被掉调用
    # __str__()函数必须要有一个返回值
    def __str__(self):
        return f"姓名:{self.name}, 年龄:{self.age}"
    # def show(self):
    # print(f"姓名:{self.name}, 年龄:{self.age}")

user_list = []
while True:
    name = input("请输入用户的姓名:")
    if name.upper()=='Q':
        break
    age = input("请输入用户的年龄:")
    # 创建一个学生对象
    p = Person(name,age)
    user_list.append(p)
for i in user_list:
    print(i) # 若直接使用对象名, 默认调用的是一class类中的__str__()函数

面向对象的三大特征

封装
继承
多态【在python语言中,多态体现不明显,因为python是
动态数据类型的语言】
抽象【python中独有的特点】

封装

# 需求:定义一个学生类,根据学生类创建一个学生对象,
并修改年龄
class Student:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def __str__(self):
    return f"姓名:{self.name}, 年龄:{self.age}"
    
    def eat(self):
        print("吃饭")
    def sleep(self):
        print("睡觉")
s1 = Student("张成阳", 18)
print(s1)
print("-----------------------------------")
s1.age = 1900
print(s1)

我们按照类和对象的使用方式,程序本身是没有任何语法的问题,但是呢我们在给学生年龄赋值的时候,可以赋值一些不合现实情况的值。

我们应该在赋值之前,先判断一下这个值是不是合理的,如果合理才允许赋值。

判断一下,是一个多个语句,不能直接加在变量上,需要额外写一个函数专门对年龄进行赋值

class Student:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def __str__(self):
    return f"姓名:{self.name}, 年龄:{self.age}"
    def set_age(self,age):
        if 120>=age>0:
            self.age = age

        else:
            print("您给的年龄不合法,默认已修改为18!")
            self.age = 18
    def eat(self):
        print("吃饭")
    def sleep(self):
        print("睡觉")
s1 = Student("张成阳", 11)
print(s1)
print("-----------------------------------")
# s1.age = 1900
s1.set_age(29)
print(s1)

虽然创建一个给年龄赋值的函数,但是我们依旧可以采用原始的直接获取属性进行赋值的方式。

依旧可以赋值一些不合法的年龄,如果我们能够让外界无法直接获取对象的属性就好了

class Student:
    def __init__(self,name,age):
        self.name = name
        self.__age = age
    def __str__(self):
        return f"姓名:{self.name}, 年龄:{self.__age}"
    def set_age(self,age):
        if 120>=age>0:
            self.__age = age
        else:
            print("您给的年龄不合法,默认已修改为18!")
            self.__age = 18
            def eat(self):
                print("吃饭")
            def sleep(self):
                print("睡觉")

s1 = Student("张成阳", 11)
print(s1)
print("-----------------------------------")
# s1.age = 1900 # 这里的age相当于是一个新的属性
# s1.__age = 1900 # 使用不了__的属性
s1.set_age(29)
print(s1)

在init函数中定义的属性前面加上__,就表示该属性为私有属性,而私有属性只能在一个class内部随意访问,出了class就访问不到了。

上午说了半天的例子,实际上就是想传达一个封装的思想

封装:将一个类中的成员进行私有化,只对外提供公共函数,对外隐藏类实现细节

类中私有的函数,可以间接地使用非私有的函数调用

class Student:
    def __init__(self,name,age):
        self.__name = name
        self.__age = age
    def __str__(self):
        return f"姓名:{self.__name}, 年龄:{self.__age}"
    def set_name(self,name):
        self.__name = name
    def get_name(self):
        return self.__name
    def set_age(self,age):
        if 120>=age>0:
            self.__age = age
        else:
            print("您给的年龄不合法,默认已修改为18!")
            self.__age = 18
    def get_age(self):
        return self.__age
    def eat(self):
        print("吃饭")
    def sleep(self):
        print("睡觉")
    def __fun1(self):
        print("hello world")
    def fun2(self):
        self.__fun1()
s1 = Student("张成阳", 11)
print(s1)
print("-----------------------------------")
# s1.age = 1900 # 这里的age相当于是一个新的属性
# s1.__age = 1900 # 使用不了__的属性
# s1.set_age(29)
# print(s1)
# print(s1.__age)
# print(s1.get_age())
# s1.fun1()
s1.fun2() # 间接地调用私有的函数

局部变量和成员属性同名的情况

class Demo1:
    def __init__(self, age):
        self.age = age
    def fun1(self):
        # age = 10
        print(self.age) # 获取当前对象的属性age
# print(age) # 获取当前函数中的局部变量age
d1 = Demo1(18)
d1.fun1()

继承

继承是将多个类中的相同的部分,单独提取到一个类中,这些类于单独提出来的这个类产生一个关系这个关系,就叫做继承关系,其他类中也就拥有了相同的部分,不需要特地定义出来。

class Student:
    def __init__(self,sid,name,age):
        self.sid = sid
        self.name = name
        self.age = age
    def __str__(self):
        return f"Student:({self.sid},{self.name}, {self.age})"
    def study(self):
        print("学生学习")
    def like(self):
        print("学生的爱好")
class HighStudent:
    def __init__(self, sid, name, age):
        self.sid = sid
        self.name = name
        self.age = age
    def __str__(self):
        return f"Student:({self.sid},{self.name}, {self.age})"
    def study(self):
print("学生学习")
def like(self):
print("学生的爱好")
s1 = Student('1001'
,
'张三'
,18)
s1.study()
s1.like()
s2 = HighStudent('1002','李四',19)
s2.study()
s2.like()

如果多个类中,相同的部分太多了,每一类都写一遍的话,语法上没有问题,但是从代码美观来说,冗余度太大了。

# 继承的语法改进
class 父类: 父类| 超类| 基类
    xxxx

class 子类(父类): 子类| 派生类
    pass
------------------------------

class Father:
    xxxx
class Son(Father):
    pass

通过继承,子类拥有了父类中的成员

class Person:
    def __init__(self,sid,name,age):
        self.sid = sid
        self.name = name
        self.age = age
    def __str__(self):
        return f"Student:({self.sid},{self.name}, {self.age})"
    def study(self):
        print("学生学习")
    def like(self):
        print("学生的爱好")
class Student(Person):
    pass
class HighStudent(Person):
    pass
s1 = Student('1001','张三',18)
s1.study()
s1.like()
s2 = HighStudent('1002','李四',19)
s2.study()
s2.like()
  • 子类无法继承父类中私有的成员
class Fu:
    def fun1(self):
        print("好好学习,天天向上!")
    def __fun2(self):
        print("这是父类中私有的成员函数__fun2")
class Son(Fu):
    pass
s1 = Son()
s1.fun1()
s1.__fun2()
  • 若子类中出现与父类的函数名以及函数参数都一样,只是实现不一样的情况,子类对象调用的是自己的函数
class Fu:
    def fun1(self):
        print("好好学习,天天向上!")
    def __fun2(self):
        print("这是父类中私有的成员函数__fun2")
    def fun3(self):
        self.__fun2()
class Son(Fu):
    def fun1(self):
        print("这是子类中的函数fun1")
    pass
s1 = Son()
s1.fun1()

子类中出现与父类的函数名以及函数参数都一样,只

是实现不一样的情况,称之为函数的重写 override

  • 子类继承父类的同时,可以出现父类中没有的行为
class Fu2:
    def fun1(self):
        print("shujia")
class Zi2(Fu2):
    def show(self):
        print("shujia666")

# d1 = Fu2()
# d1.fun1()
# d1.show()
d2 = Zi2()
d2.fun1()
d2.show()
  • 子类中可以使用super()来调用父类中非私有的成员
class Fu:
    def fun1(self):
        print("这是父类中的fun1")
class Zi(Fu):
    def fun1(self):
        print("这是子类中的fun1")
    def show(self):
        self.fun1() # 调用的是子类中重写后的fun1函数
        
        # 调用父类中的fun1
        super().fun1()
z = Zi()
z.show()
  • 子类中可以定义父类中没有的成员属性
class Fu:
    def __init__(self,name,age):
        self.name = name
        self.age = age
class Zi(Fu):
    def __init__(self, name, age, sid):
        super().__init__(name,age)
        self.sid = sid

z1 = Zi('张三',18, 1001)
print(z1.name,z1.age,z1.sid)
  • 在python中一个类可以同时继承多个类
class Fu:
    def fun1(self):
        print("这是父亲中的函数fun1")
class Mather:
    def fun2(self):
        print("这是母亲中的函数fun2")

class Son(Fu, Mather):
    def function1(self):
        print("这是儿子自己的函数")
s1 = Son()
s1.fun1()
s1.fun2()
s1.function1()

若同时继承的类中有相同的函数名,谁先写就调用谁的

class Fu:
    def fun1(self):
        print("这是父亲中的函数fun1")
    def show(self):
        print("这是父亲中的函数show")
class Mather:
    def fun2(self):
        print("这是母亲中的函数fun2")
    def show(self):
        print("这是母亲中的函数show")
class Son(Mather,Fu):
    def function1(self):
        print("这是儿子自己的函数")
s1 = Son()
s1.fun1()
s1.fun2()
s1.function1()
s1.show() # 调用的是母亲中的show

多态

表示的是某一个事物在不同时刻下的不同状态

  • 在python中默认支持多态,因为python是动态数

据类型语言

'''
水【气态的水, 固态的水, 液态的水】
动物【狗, 猫, 猪】
'''
class Animal:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def __str__(self):
        return f"name:{self.name}, age:{self.age}"
    def eat(self):
        print("吃")
    def sleep(self):
        print("睡")
class Dog(Animal):
    pass
a1 = Animal('小黄',2)
a1 = Dog('小黑',3)
print(a1)
# Animal a = new Dog('小黑',3)

抽象

class Animal:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def __str__(self):
        return f"name:{self.name}, age:{self.age}"
    @abstractmethod
    def eat(self):
        pass
    @abstractmethod
    def sleep(self):
        pass
class Dog(Animal):
    @override
    def eat(self):
        print("🐕吃🥩")
@override
    def sleep(self):
        print("🐕趴着睡")

# a1 = Animal('小黄',2)
a1 = Dog('小黑',3)
a1.eat()
a1.sleep()

类变量

将变量定义在类中函数外

class Demo1:
    # 类变量
    a = 100
    def fun1(self):
        a = 10
        print(a)
        print(Demo1.a)
d1 = Demo1()
d1.fun1()
# print(Demo1.a) # 通过类名直接访问
print(d1.a) # 也可以通过对象名进行访问
posted @   09250327  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示