当前位置: 首页 > article >正文

最新Python大数据之Python基础【十】学生管理系统面向对象版_python面向对象学生管理系统

1、在子类中调用父类方法

  • super().方法名()
  • 类名.方法名(self)
  • spuer(要从哪一个类的上一级类开始查找, self).方法名()
  • 子类调用父类方法时,一般都是想对父类方法进行扩展
class Person(object):
    def \_\_init\_\_(self, name, age):
        self.name = name
        self.age = age

    def driver(self):
        print('开车太好玩了 ,10迈,太快了')


class Father(Person):
    # 如果我们现在想在原有父类方法基础上扩展,例如我们现在需要重写一个init方法
    # 可以接收 name, age ,gender三个属性
    def \_\_init\_\_(self, name, age, gender):
        # 在父类方法中已经添加了name,和age我们可不可以直接使用呢???
        super().__init__(name, age)
        # 在父类方法的基础上我们在添加一个子类方法独有的功能
        self.gender = gender

    def driver(self):
        print('我要去天安门完,开挖掘机不让我进')

    def \_\_str\_\_(self):
        return f'我的姓名是{self.name},我的年龄是{self.age},我的性别是{self.gender}'

class Son(Father):
    def driver(self):
        # 调用Person中的dirver
        # TypeError: driver() missing 1 required positional argument: 'self'
        # Person.driver()
        Person.driver(self)
        # 从Father类的上一级类开始查找方法,并进行调用
        super(Father,self).driver()

        # 调用Father中的dirver
        super().driver()
        # 格式:super(从哪个类的上一级开始查找,self).方法名()
        # 如果类名是当前类,可以省略括号内的内容
        super(Son, self).driver()
        # 书写特有功能


# 所有的参数都传递到了Father类中,并且添加为当前对象的属性
print(Father('Jack', 28, '男'))
s1 =Son('xiaoming', 12, '男')
s1.driver()

# 子类中调用父类方法的三种方式:
# super().方法名() # 只能调用当前类的上一级类中的方法或函数
# 类名.方法名(self) # 所使用的类名,必须在当前类的继承关系中 这种方法可以调用不在类中的类方法,但是不能使用self作为对象出现
# super(要从哪一个类的上级类开始查询,self).方法名() # 类名必须在继承关系内,如果类名是当前所在的类,则可以将括号内内容省略,就是第一中方式

2、多态

  • 在继承链条中,子类重写父类方法,即多个子类和父类中都拥有同名方法,将其对象传入函数或方法内部,执行相同方法后,所展示的效果完全不同,这种现象叫做多态
class Person(object):

    def driver(self):
        print('开车太好玩了 ,10迈,太快了')


class Father(Person):

    def driver(self):
        print('我要去天安门完,开挖掘机不让我进')


class Mother(Person):
    def driver(self):
        print('我会开小汽车,嘟嘟嘟')


class Son(Father):
    def driver(self):
        print('我会骑自行车,真好玩')


def go_shopping(Driver):
    Driver.driver()
    print('很快就到超市了,真好呀')

class Monkey(object):
    def driver(self):
        print('我在骑自行车')


# 在我调用go_shopping时,可以将什么对象传进来???

p1 = Person()
f1 = Father()
s1 = Son()
m1 = Mother()

# 多态: 在继承链条中,无论是多级继承还是多继承,不同的类同种方法会进行重写,重写后在函数或者方法中传入不同的子类创建的对象,调用相同方法所展示的效果完全不同
go_shopping(p1)
go_shopping(f1)
go_shopping(s1)
go_shopping(m1)

# 如果创建一个Monkey对象,能否传入go_shopping并正确执行???
# 如果一个没有继承关系的类,也存在指定方法,也可以进行对象的传递,并在方法或函数内部使用,但是逻辑会有偏差,这种语法没有问题,但是逻辑上有严重偏差的方式叫做"鸭子类型"(扩展,不要求掌握)
# monkey1 = Monkey()
# go_shopping(monkey1)

3、类属性

  • 类属性,就是所有的对象所共有的属性,在对其修改够,所有对象的类属性放生了改变
  • 实例属性,每个对象所独有的,对象被创建后,添加修改实例属性,对其他对象不产生影响
# 类属性 ,有些地方也叫类变量 就是在类中创建的属于所有对象的属性

class Chinese(object):
    # 类属性是所有对象所共有的
    color = 'yellow'
    def \_\_init\_\_(self, name):
        self.name = name


c1 = Chinese('xiaohong')
c2 = Chinese('xiaohuang')
c3 = Chinese('xiaolv')

# 上述三个对象拥有的实例属性是什么??? name
# 他们每个人的实例属性相同么???之间有联系么??? 不相同,每个对象间的实例属性互不相关
# 但是三个对象的类属性是完全相同的
print(c1.color)
print(c2.color)
print(c3.color)
# 类属性的获取方式
# 格式1:对象名.类属性名 在实例属性中,不能有与类属性同名的属性,否则类属性不能通过这种方式提取
# 格式2:类名.类属性名 (推荐)

# 修改类属性
# 格式:类名.类属性名 = 值
Chinese.color = 'orange'
# 注意:修改类属性不能使用 对象名.属性名 = 值 这种方式会添加一个实例属性
print(c1.color)
print(c2.color)
print(c3.color)

# 类属性使用场景:
# 可以进行计数
# 可以控制或者包含多个对象
class Apple(object):
    apple_list = []
    def \_\_init\_\_(self):
        Apple.apple_list.append(self)

    count = 10
    def eat(self):
        Apple.count -= 1

a1 = Apple()
a2 = Apple()
a3 = Apple()
a4 = Apple()

a1.eat()
a2.eat()
a3.eat()
a4.eat()
print(Apple.count)
print(Apple.apple_list)

4、类方法

  • 如果在方法内部不需要使用实例属性和实例方法,但是需要使用类属性或者类方法我们就定义类方法
  • 定义方式:需要在方法上方写@classmethod
  • 在类方法中会自动传入cls,这个参数代表的是当前类本身
class Apple(object):
    num = 10
    def \_\_init\_\_(self):
        self.eat_num = 0

    def eat(self):
        # 每次吃苹果,当前的食用数量加1
        self.eat_num += 1
        # 每次吃苹果,让苹果总数 -1
        Apple.num -= 1
    # 当方法中不适用实例属性和实例方法,只会使用到类属性和类方法的时候我们就选择类方法
    # 因为类方法,不需要创建实例去进行调用,可以直接使用类名调用
    @classmethod
    def eat\_apple\_num(cls):
        # 在类方法中传入的cls即为当前类的类名
        print(f'一共被吃了{10-cls.num}个,还剩{cls.num}个')

# 类方法的调用
# 格式: 类名.类方法名
Apple.eat_apple_num()

# 创建对象
a1 = Apple()
a2 = Apple()
a3 = Apple()
a4 = Apple()
# 吃苹果
a1.eat()
a2.eat()
a3.eat()
a4.eat()
a4.eat()

# 调用类方法
Apple.eat_apple_num()

# 查看每人吃了几个苹果
print(a1.eat_num)
print(a2.eat_num)
print(a3.eat_num)
print(a4.eat_num)

# 类方法可以使用对象调用么?
# a1.eat\_apple\_num() 不推荐这样使用

5、静态方法

  • 既不依赖于实例,也不依赖于类,这种方法我们就可以定义为静态方法
class Person(object):
    # 在静态方法中,不会传入self, 也不会传入cls 所以在我们使用静态方法时,最好再静态方法中不要使用类或对象的属性或者方法
    # @classmethod 类方法修饰

    @staticmethod
    def func():
        print('我是一个静态方法')

# def func():
# print('我是一个静态方法')
# 一般能够定义为函数的内容,都可以改写为静态方法,理论静态方法不依赖与类和对象,但是为了更好的封装,我们会将其写到类中
Person.func()


# 静态方法就是一个普通函数,放到类内部就是为了封装,方便我们去继承和导入模块

6、面向对象案例

# 需求: 进行游戏
# 1/显示游戏信息
# 2/展示历史最高分
# 3/开始游戏

class Game(object):
    top_score = 100

    def \_\_init\_\_(self, name):
        self.name = name
    # 定义一个静态方法,与类和实例都没有关系
    @staticmethod
    def print\_game\_info():
        print('游戏信息展示')
    # 定义类方法,内部可以调用类属性和类方法,依赖于类
    @classmethod
    def show\_top\_score(cls):
        print(f'历史最高分数为{cls.top\_score}')
    # 定义了一个实例方法,内部可以调用实例属性和实例方法,依赖于实例
    def start\_game(self):
        print(f'{self.name}开始游戏')

Game.print_game_info()
Game.show_top_score()
# 实例方法必须使用实例进行调用
g1 = Game('xiaoming')
g1.start_game()

7、异常捕获

  • 使用try和except可以捕获异常,也就是在出现异常后不会将代码终止运行,而是执行except中的代码处理异常
# 异常捕获:通过代码将可能出现异常的文件放入try中,然后如果出现异常就执行except中的命令
'''
格式:
try:
 可能出现异常的代码
except:
 如果出现了异常,就执行其中的代码
'''

# 需求:读取文件,如果文件不存在,则以写入方式打开
# 如果我们try中的代码出现了异常,则执行except中的命令
# 如果我们try中的代码没有出现异常,则不会执行
try:
    file = open('test.py', 'r')
except:
    file = open('test.py', 'w')

# 在正常的Python开发中基本每个函数中都要出现一次异常捕获
# 代码健壮性:代码抵御异常的能力

8、捕获指定类型的异常

  • 在except后边添加异常类型,就可以捕获指定类型的异常
  • 如果我们想要捕获多种异常
    • 可以在except后边添加多个异常类型,中间用逗号隔开,但是需要用括号包裹,变成一个元组
    • 可以书写多个except
  • 如果所有的异常类型都无法捕获到该异常, 或者我们需要捕获未知类型的异常,可以使用Exception
# try:
# # NameError: name 'a' is not defined
# # 如果先出现NameError 我们的后边一句没有办法执行 ZeroDivisionError没有办法捕捉到
# # print(a)
# print(1/0)
# # 如果想要捕获指定异常,就在except 后边添加异常的类型
# except ZeroDivisionError: # 这种方式只能捕获指定异常
# print('出现异常了!!!')

# 在出现异常后, NameError和 ZeroDivisionError 之类的Error就是异常类型
# ZeroDivisionError: division by zero
# print(1/0)
# NameError: name 'a' is not defined
# print(a)


# 能不能同时捕获多种异常呢? 可以
# 方法一:在except后边添加多个异常名称
# try:
# # NameError: name 'a' is not defined
# # 如果先出现NameError 我们的后边一句没有办法执行 ZeroDivisionError没有办法捕捉到
# # print(a)
# print(1 / 0)
# # 如果想要捕获指定异常,就在except 后边添加异常的类型
# except (ZeroDivisionError, NameError): # 这种方式只能捕获指定异常
# print('出现异常了!!!')

# 方法二: 在try后边书写多个except
# try:
# # NameError: name 'a' is not defined
# # 如果先出现NameError 我们的后边一句没有办法执行 ZeroDivisionError没有办法捕捉到
# # 在出现异常之后,后续代码将不会继续执行
# print(a)
# print(1 / 0)
# # 如果想要捕获指定异常,就在except 后边添加异常的类型
# except ZeroDivisionError:
# print('出现ZeroDivisionError异常了!!!')
# except NameError:
# print('出现NameError异常!!')

# 如果我们想要展示异常信息怎么办?
# 异常信息就是异常类型冒号之后的注释
# 可以通过获取异常对象,并对异常对象进行打印,得到异常信息
# try:
# print(a)
# print(1 / 0)
# # 如果想要捕获指定异常,就在except 后边添加异常的类型
# # 在异常类型之后添加上个as 变量名 这时候 变量就是异常对象,打印该对象就可以出现错误信息
# except ZeroDivisionError as error:
# print(error) # division by zero
# except NameError as error:
# print('出现NameError异常!!', error)

# 如果我们不知道异常类型是什么怎么办?

# 可以使用Exception进行捕获,Exception是所有异常类的父类,可以捕获所有异常类型

try:
    print('2' + 1)
    print(a)
    print(1 / 0)
except ZeroDivisionError as error:
    print(error)  # division by zero
except NameError as error:
    print('出现NameError异常!!', error)
except Exception:
    print('出现了未知异常')

9、else 和 finally

  • else: try中控制的代码没有出现异常,则执行该结构内的代码
'''
格式:
try:
 可能会出现异常的代码
except:
 在出现异常后执行该命令处理异常
else:
 当没有出现异常时,执行该代码
'''

try:
    a = 1
    print(a)
except:
    print('出现异常了')
else:
    # try中的代码正常执行没有任何异常,则执行else里边的代码
    print('没有异常,虚惊一场')

  • finally:无论出现什么情况都会执行finally里边的代码,哪怕程序崩溃
'''
try:
 可能出现异常的代码
except:
 代码出现异常后执行该代码处理异常
else:
 如果try中的代码不出现异常,则执行其中的代码
finally:
 无论如何都会执行finally中的代码
'''

# 无论任何情况,finally中的代码都要被执行
try:
    a = 1
    print(a)
    print(1/0)
except NameError:
    print('出现异常了')
else:
    print('没有出现异常')
finally:
    print('出现不出现异常都要执行')
# 代码写到finally中,哪怕程序报错终止,代码依旧需要执行完成,但是写到try结构之外,程序报错终止将不会继续执行外部代码
print('try结构之外书写内容')

10、自定义异常抛出

  • 自定义异常一定要继承自Exception
  • 自定义异常可以使用raise抛出,可以进行捕获或者导致程序终止
  • raise可以抛出系统异常,也可以抛出自定义异常
# 自定义异常的逻辑
# 在自定义异常时,只要继承自Exception就可以当做异常抛出
# 继承后要重写 Exception方法,添加我们需要的内容

class PassWorldError(Exception):
    error_count = 0

    def \_\_init\_\_(self, str):
        super().__init__(str)
        # 在此处可以添加自定义操作
        PassWorldError.error_count += 1

# raise可以手动抛出异常,抛出异常后,可以直接终止程序,或者使用try except进行捕获
# raise可以抛出自定义异常,也可以抛出系统异常
try:
    password = input('请输入您的密码:')
    if len(password) < 6:
        raise PassWorldError('您的密码不足6位,请重新输入')
        # raise NameError('您的密码错误了')
except PassWorldError as error:
    print(error)

# raise PassWorldError('密码错误')

11、模块的导入

import 模块名
调用: 模块名.功能名

from 模块名 import 功能名
调用: 功能名

from 模块名  import  \*
import 模块名  as 别名
from 模块名 import 功能名 as 别名

# Python中的模块就是可以将别人写好的,或者自己以前写好的功能直接导入新的文件或工程内,导入后可以直接调用 例如 : random time os

# 我们没有实现模块中的功能,但是我们讲模块导入后就可以使用该功能,类似于继承

# 导入模块的方式
'''
import 模块名
调用: 模块名.功能名

from 模块名 import 功能名
调用: 功能名

from 模块名 import \*
import 模块名 as 别名
from 模块名 import 功能名 as 别名
'''
# # 导入os模块
# import os
#
# # 使用os模块
# print(os.listdir())

# # 导入os模块中部分功能
# from os import listdir, mkdir
# # 使用os模块中的功能
# print(listdir())

# # 导入os模块中的所有功能
# from os import \*
# # \*就是通配符,表示导入os模块中所有允许导入的模块
#
# # 使用os模块
# print(listdir())

# # 导入os模块,将模块改名为xitong
# import os as xitong
# # 使用os模块
# # NameError: name 'os' is not defined
# # print(os.listdir())
# # 如果给模块起了别名.则原名称不可使用
# print(xitong.listdir())

# from os import listdir as ls
# print(ls())
# NameError: name 'listdir' is not defined
# 给功能名称起别名后,无法使用原名称只能使用新的功能名称
# print(listdir())

12、自定义模块

  • 模块名一定要遵循标识符的命名规则才能被导入
  • 模块中书写的全局变量,函数,类可以盗取其他文件
  • 导入模块时,会将模块中的所有文件执行一遍
  • 为了保证测试代码在导入模块时不被执行,我们的测试代码需要写入

if __name__ == '__main__:'

# 标识符的命名规则
# 1/以字母数字下划线组成
# 2/不能以数字开头
# 3/不能是关键字
# 4/严格区分大小写

age = 18


def func():
    print('我是module中的函数')


class Person(object):
    def eat(self):
        print('西瓜真好吃呀')




# 在书写模块或者工具类的时候,经常需要调试,每次调试完成后还要将代码删除,否则导包结束后测试代码都会被执行一遍

# 所以我们需要想一个办法,将我们写的测试代码在当前模块中执行时,调用,在导入模块时不调用
# \_\_name\_\_就是说明当前文件执行的模块名是什么?
# print(\_\_name\_\_) # \_\_main\_\_如果在当前文件中执行,模块名就是main
# 如果导入其他模块,则\_\_name\_\_的值就是文件名称module\_01
# 所以我们根据\_\_name\_\_的值的判断,就可以断定他是咋当前文件执行,还是导入模块

# 使用该判断,让我们的测试代码只有在当前文件中执行的时候才会被调用
if __name__ == '\_\_main\_\_':
    if age > 10:
        print('今晚不能尿床了')

13、模块查询顺序

  • sys.path可以查询模块调用路径列表,越靠前的路径越优先查询
# 可以使用sys.path查看模块的定位顺序,如果模块名相同,优先从最新的序列查找

import sys
print(sys.path)
# sys.path的返回值是一个路径列表,排名越靠前的路径,在调用模块时优先查找,如果这个路径下没有对应模块才去下一个路径中查找.

# 在开发中可以在列表中你添加路径(了解)

  • 开发中可以添加调用路径 sys.path.append(路径)

14、__all__的使用方式

# \_\_all\_\_可以控制模块使用功能from 模块名 import \*所导入的功能列表


http://www.kler.cn/a/527227.html

相关文章:

  • [STM32 - 野火] - - - 固件库学习笔记 - - -十二.基本定时器
  • 数据分析系列--⑤RapidMiner进行关联分析(中文数据案例)
  • 【C++动态规划 离散化】1626. 无矛盾的最佳球队|2027
  • 【Rust自学】15.0. 智能指针(序):什么是智能指针及Rust智能指针的特性
  • Swing使用MVC模型架构
  • 最新-CentOS 7 基于1 Panel面板安装 JumpServer 堡垒机
  • JAVA实战开源项目:网上购物商城(Vue+SpringBoot) 附源码
  • 随笔 | 写在一月的最后一天
  • Vue-cli 脚手架搭建
  • 翻译: Anthropic CEO:DeepSeek-R1是人工智能领域的革命吗?一
  • gentoo中利用ollama运行DeepSeek-R1
  • Bash 基础与进阶实践指南
  • 【搜索回溯算法篇】:拓宽算法视野--BFS如何解决拓扑排序问题
  • FreeRTOS从入门到精通 第十五章(事件标志组)
  • Spring Boot 配置文件详解:YAML vs Properties
  • 边缘计算与ROS结合:如何实现分布式机器人智能决策?
  • C 语言实现计算一年中指定日期是第几天 题】
  • 【Linux】软硬链接
  • 英语语法 第一天
  • 【算法应用】基于鲸鱼优化算法求解OTSU多阈值图像分割问题
  • python 之 zip 和 * 解包操作
  • 微店的Flutter混合开发组件化与工程化架构
  • SQL NOW() 函数详解
  • Day52:range()函数
  • 精准化糖尿病知识问答(LLM+机器学习预测模型)
  • ELK模块封装starter