Python入门二

news2024/11/19 14:43:21

目录:

  1. python封装与property装饰器
  2. python继承与类型检查
  3. python多态与super
  4. python 模块与包
  5. 错误与异常
  6. Debug 调试与分析
  7. python类型注解
  8. python数据类dataclass
  9. python内置装饰器
  10. python装饰器
  11. 学生信息管理系统

1.python封装与property装饰器

封装的概念

  • 封装(Encapsulation
    • 隐藏:属性和实现细节,不允许外部直接访问
    • 暴露:公开方法,实现对内部信息的操作和访问

封装的作用

  • 限制安全的访问和操作,提高数据安全性
  • 可进行数据检查,从而有利于保证对象信息的完整性

 封装的实现:隐藏

  • 保护属性:_属性名
  • 私有属性:__属性名
    • 被视作 _类名__属性名
class Account:
    # 普通属性
    bank = "BOC"
    # 内部属性
    _username = "tom"
    # 私有属性
    __password = "888"


# 通过类名访问类属性
print(Account.bank)  # 将会打印 BOC
print(Account._username)  # 将会打印 tom
print(Account.__password)  # 将会引发 AttributeError

print(Account.__dict__)

# 实例化
obj = Account()

# 实例访问类属性
print(obj.bank)  # 将会打印 BOC
print(obj._username)  # 将会打印 tom
print(obj.__password)  # 将会引发AttributeError

封装的实现:暴露

  • 提供数据访问功能(getter
    • 计算属性
    • 语法:使用@property装饰器
    • 调用:实例.方法名
class Account:
    # 普通属性
    bank = "BOC"
    # 内部属性
    _username = "tom"
    # 私有属性
    __password = "888"

    @property
    def password(self):
        return self.__password


# 实例化对象
obj = Account()

# 访问实例的私有属性
print(obj.password)  # 将会打印 888

封装的实现:暴露

  • 提供数据操作功能(setter
    • 语法:使用@计算属性名.setter装饰器
    • 调用:实例.方法名
class Account:
    # 普通属性
    bank = "BOC"
    # 内部属性
    _username = "tom"
    # 私有属性
    __password = "888"

    @property
    def password(self):
        return self.__password

    @password.setter
    def password(self, value):
        # 增加数据的校验
        if len(value) >= 8:
            self.__password = value
        else:
            print("密码长度最少要有8位!")


# 实例化对象
obj1 = Account()

# 修改私有属性(满足校验条件)
obj1.password = "tomtom666"  # 修改成功
print(obj1.password)  # 将会打印 tomtom666

# 实例化对象
obj = Account()
# 修改私有属性(不满足校验条件)
obj.password = "123"  # 修改不会生效
print(obj.password)  # 将会打印 888

2.python继承与类型检查

继承的概念

  • 继承(Inheritance
    • 复用父类的公开属性和方法
    • 拓展出新的属性和方法

继承的实现

  • 语法:class 类名(父类列表)
  • 默认父类是 object
  • Python 支持多继承
class Human:
    """人类"""

    # 类属性
    message = "这是Human的类属性"

    # 构造方法
    def __init__(self, name, age):
        # 实例属性
        self.name = name
        self.age = age

    # 实例方法
    def live(self):
        print("住在地球上")


class Student(Human):
    """学生类"""

    def study(self):
        print("正在学习")


# 实例化子类对象
stu = Student("哈利波特", 12)
# 访问类属性(继承)
print(stu.message)
# 访问实例属性(继承)
print(stu.name, stu.age)
# 访问实例方法(继承)
stu.live()
# 访问实例方法(扩展)
stu.study()

类型检查

  • isinstance(实例, 类名)
    • 检查对象是否是某个类及其派生类的实例
  • issubclass(类名1, 类名2)
    • 检查类名 1 是否是类名 2 的子类
# 人类
class Human:
    pass


# 学生类
class Student(Human):
    pass


# 老师类
class Teacher(Human):
    pass


# 检查实例与类的关系
stu = Student()
print(isinstance(stu, Human))  # 将会打印 True

# 检查类与类的关系
print(issubclass(Student, Human))  # 将会打印 True
print(issubclass(Student, Teacher))  # 将会打印 False

3.python多态与super

多态的概念

  • 多态(Polymorphism
    • 同名方法呈现多种行为

 运算符的多态表现

  • +
    • 加法:数字+数字
    • 拼接:字符串+字符串
    • 合并:列表+列表
# 加法:数字+数字
print(1 + 1)  # 打印 2

# 拼接:字符串+字符串
print("Hello" + "World")  # 打印 Hello World

# 合并:列表+列表
print([1, 2] + [3])  # 打印 [1, 2, 3]

函数的多态表现 

  • len()函数
    • 可以接收字符串
    • 可以接收列表
# 参数是字符串
print(len("hello"))

# 参数是列表
print(len([1, 3, 5]))

 方法的多态表现

  • 同名变量调用同名方法呈现多种行为
class China:
    def speak(self):
        print("汉语")


class Usa:
    def speak(self):
        print("英语")


# 实例化对象
cn = China()
us = Usa()

for x in (cn, us):
    # 同一个变量在调用同名方法时,呈现不同的行为
    # 具体呈现哪种行为,由该变量所引用的对象决定
    x.speak()

 多态与继承

  • 方法重写(Override):子类的方法名称与父类的相同
  • 重写构造方法
    • super().__init__()
    • 父类名.__init__(self)
class Human:
    """人类"""

    message = "这是Human的类属性"

    # 构造方法
    def __init__(self, name, age):
        # 实例属性
        self.name = name
        self.age = age

    # 实例方法
    def live(self):
        print(f"住在地球上")


class Student(Human):
    """学生类"""

    # 重写父类的构造方法
    def __init__(self, name, age, school):
        # 访问父类的构造方法
        super().__init__(name, age)
        # super(Student, self).__init__(name, age)
        # Human.__init__(self, name, age)
        # 子类实例属性(个性)
        self.school = school

    # 重写父类的实例方法
    def live(self):
        print(f"住在{self.school}")


# 实例化子类对象
stu = Student("哈利波特", 12, "月球")

# 访问实例方法
stu.live()  # 将会打印 住在月球

4.python 模块与包

模块

  • 模块是在代码量变得相当⼤了之后,为了将需要重复使⽤的有组织的代码放在⼀起,这部分代码可以被其他程序引⽤,从⽽使⽤该模块⾥的函数等功能,引⽤的过程叫做导⼊(import)
  • 在python中,⼀个⽂件(以“.py”为后缀名的⽂件)就叫做⼀个模块
  • 导⼊模块的写法:
  • ⽅法⼀:import modul1[,module2…[,moduleN]]
  • ⽅法⼆:from module import <name[,name2,….[,nameN]]>

 模块分类

  • 系统内置模块
    • sys、time、json模块等等;
  • 第三⽅的开源模块
    • 通过pip install进⾏安装,有开源的代码
  • ⾃定义模块
    • ⾃⼰写的模块,对某段逻辑或某些函数进⾏封装后供其他函数调⽤。

如何使⽤模块?

  • 系统内置模块
  • Python安装好之后⾃带的⼀些⾮常有⽤的模块(sys,os,time,json模块等) 
import sys

print("调⽤了sys模块")

for i in sys.argv:
    print(i)

第三⽅开源模块

  • 是通过包管理⼯具pip完成的。必须先知道该库的名称,可以在官⽹或者pypi上搜索,⽐如MySQL驱动程序,Web框架Flask,科学计算Numpy等
  • NumPy(Numerical Python)是Python语⾔的⼀个扩展程序库,⽀持⼤量的维度数组与矩阵运算,此外也针对数组运算提供⼤量的数学函数库
  • pip install numpy 
import numpy

# 创建一个数组
arr = numpy.array([1, 2, 3, 4, 5])

# 打印数组
print("原始数组:", arr)

⾃定义模块

  • ⾃定义模块是⾃⼰写的模块,对某段逻辑或某些函数进⾏封装后供其他函数调⽤。
  • 模块由变量,函数,或类组成
  • 举例:
    • 创建⼀个模块baidu.py
    • 创建⼀个调⽤模块index.py
  • 注意:⾃定义模块的名字⼀定不能和系统内置的模块重名,否则将不能再导⼊系统的内置模块。例如,⾃定义了⼀个sys.py模块后,那系统的sys模块就不能使⽤ 

 

导⼊模块

  • import 模块名 引⼊⼀个完整的模块
  • from <模块名> import <⽅法|变量|类>引⼊模块中的⼀个或多个指定部分
  • from <模块名> import *导⼊模块⾥⾯的所有的函数,变量
  • 区别:
  • import导⼊模块,每次使⽤模块中的函数,都要是定是哪个模块
  • from…import *导⼊模块,每次使⽤模块中的函数,直接使⽤函数就可以了(因为已经知道该函数是那个模块中的了)

作⽤域:

  • 搜索路径
  • 当你导⼊⼀个模块,Python解析器对模块位置的搜索顺序是:
    • 1、当前⽬录
    • 2、如果不在当前⽬录,Python则搜索在shell变量PYTHONPATH下的每个⽬录
    • 3、如果都找不到,Python会察看默认路径。UNIX下,默认路径⼀般为/usr/local/lib/python/
  • 模块搜索路径存储在system模块的sys.path变量中。变量⾥包含当前⽬录,PYTHONPATH和由安装过程决定的默认⽬录。

 使⽤模块的总结

  • 使⽤模块的好处
  • 提⾼代码的可维护性
  • ⼀个模块编写完毕之后,其他模块直接调⽤,不⽤再从零开始写代码了,节约了⼯作时间;
  • 避免函数名称和变量名称重复,在不同的模块中可以存在相同名字的函数名和变量名(不要和系统内置的模块名称重复)

 常用方法

  •  dir()找出当前模块定义的对象
  •  dir(sys)找出参数模块定义的对象

5.错误与异常

什么是异常?

  • 错误与异常的区别?
  • 错误与异常都是在程序编译和运⾏时出现的错误
  • 异常可以被开发⼈员捕捉和处理
  • 错误⼀般是系统错误,⼀般不需要开发⼈员处理(也⽆法处理),⽐如内存溢出
  • 什么是异常?
  • 异常即是⼀个事件,该事件会在程序执⾏过程中发⽣,影响了程序的正常执⾏。
  • 有些是由于拼写、配置、选项等等各种引起的程序错误,有些是由于程序功能处理逻辑不完善引起的漏洞,这些统称为程序中的异常 

错误

  • 语法错误
  • 逻辑错误
  • 系统错误

常见的异常类型:

  • ~除零类型,名称异常,索引异常,键异常,值异常,属性异常等等 

 异常处理流程

异常解决⽅案

  • 如果是拼写、配置等引起的错误,根据出错信息进⾏排查错误出现的位置进⾏解决
  • 如果是程序设计不完善引起的漏洞,根据漏洞的情况进⾏设计处理漏洞的逻辑

异常捕获与异常处理

(情况一)

 (情况二)

 (情况三)

代码示例:

try:
    # 可能会抛出异常的代码
    x = int(input("请输入一个整数:"))
    y = int(input("请输入另一个整数:"))
    # 执行正常代码
    result = x / y
except ZeroDivisionError:
    # 异常处理代码
    print("0不能做除数,请重新输入!")
else:
    # 如果没有异常,执行下面的代码
    print("计算结果为:", result)
finally:
    # 无论是否有异常,都会执行的代码
    print("程序执行完毕!")

 使⽤raise抛出异常

def divide(a, b):
    if b == 0:
        raise ValueError("除数为0!")
    return a / b


try:
    result = divide(10, 0)
except ValueError as e:
    print("发生异常:", e)

⾃定义异常

# 定义自定义异常类
class MyException(Exception):
    def __init__(self, message):
        self.message = message


# 定义一个函数,可能会抛出自定义异常
def divide(a, b):
    if b == 0:
        raise MyException("除数为0!")
    return a / b


# 在try块中调用函数,如果发生异常,则进入except块处理
try:
    result = divide(10, 0)
except MyException as e:
    print("捕获异常:", e)

6.Debug 调试与分析

程序调试

  • 程序调试是将编制的程序投⼊实际运⾏前,⽤⼿⼯或编译程序等⽅法进⾏测试,修正【语法错误和逻辑错误】的过程。

语法错误

  • 编写的python语法不正确,程序编译失败。 

逻辑错误

  • 代码本⾝能够正常执⾏,但是执⾏完成的结果不符合预期结果。 

什么是Bug

  • bug是计算机领域专业术语(⼩昆⾍;⾍⼦),计算机⾥叫漏洞,隐藏在程序中的⼀些未被发现的缺陷或问题统称为bug(漏洞) 

调试分类

1、语法错误
        类型错误,语法错误,缩进错误,索引错误,键错误
2、逻辑错误
        业务逻辑错误,并不会报错 

调试⽅法

  1. 对应位置使⽤`print`或者`logging`打印⽇志信息
  2. 启动断点模式debug调试 

7.python类型注解

  • https://docs.python.org/zh-cn/3/library/typing.html
def greeting(name: str) -> str:
    return 'Hello ' + name.split(',')[1]


print(greeting('python,java'))

 类型提示的好处

  • 1、增强代码可读性
  • 2、ide 中代码提示
  • 3、静态代码检查

类型别名: 

Vector = list[float]

def scale(scalar: float, vector: Vector) -> Vector:
    return [scalar * num for num in vector]

nums = [1.0, 2.0, 3.0]
print(scale(2.0,nums))

自定义类型:

class Student:
    name: str
    age: int


def get_stu(name: str) -> Student:
    return Student()

 # --> 有相应的提示
get_stu().

静态代码检查功能 

安装 mypy 
pip install mypy

8.python数据类dataclass

dataclass 介绍:

  • dataclass 优势
    • 可读性强
    • 操作灵活
    • 轻量
  • 应用场景
    • 创建对象
    • 完美融合平台开发 ORM 框架

 案例

  • 场景:如果创建一只猫,信息包括猫的名字、体重、颜色。同时打印这个对象的时候,希望能打印出一个字符串(包含猫的各种信息)应该如何编写代码
    • 问题:
      • 数据修改不方便
      • 代码冗余
    • 解决方案:
      • 使用自定义类实现数据类
class Cat:
    name: str
    color: str
    weight: int

    def __init__(self, name, weight, color):
        self.name = name
        self.weight = weight
        self.color = color

    def __str__(self):
        return f"喵星人姓名:{self.name}, 年龄:{self.weight},颜色:{self.color}"

    def __repr__(self):
        return f"===>>>>> 喵星人姓名:{self.name}, 年龄:{self.weight},颜色:{self.color}"


if __name__ == '__main__':
    cat = Cat("黑子", 10, "黑色")
    print(cat)

数据类更优雅的实现方案

  • 使用 dataclass 创建数据类
  • 实例化的时候自动生成构造函数
from dataclasses import dataclass

@dataclass
class Cat:
    name: str
    color: str
    weight: int


if __name__ == '__main__':
    cat = Cat("菠萝", "橘猫", 9)
    print(cat)

field 的使用

# 错误写法,执行报错
from dataclasses import dataclass

@dataclass
class Cat:
    name: str
    color: str
    weight: int
    children: list = [1, 2, 3]
# 正确写法,可变类型必须使用field
from dataclasses import dataclass, field

@dataclass
class Cat:
    name: str
    color: str
    weight: int = 2
    children: list = field(default_factory=list)

if __name__ == '__main__':
    cat = Cat("菠萝", "橘猫", 9, [1, 2, 3])
    print(cat)

 field 常用参数

参数名参数功能
default字段的默认值
default_factory定义可变量参数的默认值,default 和 default_factory 不能同时存在
init如果为 true(默认值),该字段作为参数包含在生成的 init() 方法中。
repr如果为 true(默认值),该字段包含在生成的 repr() 方法返回的字符串中。

field default 参数

  • 字段的默认值
import dataclasses

@dataclasses.dataclass
class Cat:
    name: str
    color: str
    weight: str = dataclasses.field(default=5)
    children: list = dataclasses.field(default_factory=list)
    children1: list = dataclasses.field(default_factory=lambda: [1, 2, 3])
    children2: dict = dataclasses.field(default_factory=lambda: {"name": "喵"})


if __name__ == '__main__':
    cat = Cat("菠萝", "橘猫", 9, [1, 2, 3])
    print(cat)

field init 参数

  1. 如果 init=True(未显式指定时的默认行为): 该字段将包含在生成的构造函数中, 可以在创建数据类的实例时为其提供值。name 和 color , weight 字段具有“init=True”,因此它们将包含在构造函数中。
  2. 如果 init=False: 该字段将被排除
import dataclasses

@dataclasses.dataclass
class Cat:
    name: str
    color: str
    weight: str = dataclasses.field(default=5)
    children: list = dataclasses.field(default_factory=list, init=False)

if __name__ == '__main__':
    cat = Cat("菠萝", "橘猫", 9)
    print(cat)

field repr 参数

  • 如果为 True(默认值),该字段包含在生成的 repr() 方法返回的字符串中。
  • 如果为 False,该字段不会包含在生成的 repr() 方法返回的字符串中。
import dataclasses

@dataclasses.dataclass
class Cat:
    name: str
    color: str
    weight: str = dataclasses.field(default=5)
    children: list = dataclasses.field(default_factory=list, repr=False)


if __name__ == '__main__':
    cat = Cat("菠萝", "橘猫", 9, [1, 2, 3])
    print(cat)

 运行结果:

常用的方法

  • asdict() 转化实例对象为字典格式
import dataclasses

@dataclasses.dataclass
class Cat:
    name: str
    color: str
    weight: int = 5
    children: list = dataclasses.field(default_factory=lambda: [1, 2, 3])
    children1: dict = dataclasses.field(default_factory=lambda: {"name": "喵"})


cat = Cat("aa", "red", 10, [1, 3], {"name": "喵喵"})
print(dataclasses.asdict(cat))

9.python内置装饰器

内置类装饰器

  • 不用实例化、直接调用
  • 提升代码的可读性
内置装饰器含义
classmethod类方法
staticmethod静态方法

 普通方法

  • 定义:
    • 第一个参数为self,代表 实例本身
  • 调用:
    • 要有实例化的过程,通过 实例对象.方法名 调用
# 1. 定义
class MethodsDemo:
    param_a = 0  # 类变量

    def normal_demo(self):  # 定义一个类方法,第一个参数必须为self
        """
        普通方法
        :return:
        """
        print("这是一个普通方法", self.param_a)


# 2. 调用
md = MethodsDemo()
md.normal_demo()

类方法

  • 定义:
    • 使用 @classmethod 装饰器,第一个参数为类本身,所以通常使用cls命名做区分(非强制)
    • 在类内可以直接使用类方法或类变量,无法直接使用实例变量或方法
  • 调用:
    • 无需实例化,直接通过 类.方法名 调用,也可以通过 实例.方法名 调用
# 1. 类的定义
class MethodsDemo:
    param_a = 0

    # 定义类方法必须加 classmethod装饰器
    @classmethod
    def classmethod_demo(cls):
        """
        类方法,第一个参数需要改为cls
        :return:
        """
        print("类方法", cls.param_a)


# 2. 类的调用
MethodsDemo.classmethod_demo()  # 无需实例化,直接调用

静态方法

  • 定义:
    • 使用 @staticmethod 装饰器,没有和类本身有关的参数
    • 无法直接使用任何类变量、类方法或者实例方法、实例变量
  • 调用:
    • 无需实例化,直接通过 类.方法名 调用,也可以通过 实例.方法名 调用
# 1. 定义
class MethodsDemo:
    param_a = 0

    @staticmethod
    def static_demo():
        """
        静态方法
        :return:
        """
        print("静态方法")  # 无法直接调用类变量


# 2. 调用
MethodsDemo.static_demo()

普通方法、类方法、静态方法

名称定义调用关键字使用场景
普通方法至少需要一个参数self实例名.方法名()方法内部涉及到实例对象属性的操作
类方法至少需要一个cls参数类名.方法名() 或者实例名.方法名()@classmethod如果需要对类属性,即静态变量进行限制性操作
静态方法无默认参数类名.方法名() 或者实例名.方法名()@staticmethod无需类或实例参与

普通方法实际案例

  • 下边的代码实现的需求是格式化输出时间
  • 如果现在需求变更,输入 年、月、日 没法保证格式统一,可能是json,可能是其他格式的字符串,在不修改构造函数的前提下,如何更改代码
class DateFormat:
    def __init__(self, year=0, month=0, day=0):
        self.year = year
        self.month = month
        self.day = day

    def out_date(self):
        return f"输入的时间为{self.year}年,{self.month}月,{self.day}日"


year, month, day = 2023, 8, 2

demo = DateFormat(year, month, day)
print(demo.out_date())
class DateFormat:
    def __init__(self, year=0, month=0, day=0):
        self.year = year
        self.month = month
        self.day = day

    def out_date(self):
        return f"输入的时间为{self.year}年,{self.month}月,{self.day}日"

    @classmethod
    def json_format(cls, json_data):
        year, month, day = json_data["year"], json_data["month"], json_data["day"],
        return cls(year, month, day)


json_date = {"year": 2023, "month": 12, "day": 24}
demo = DateFormat.json_format(json_date)
print(demo.out_date())

 静态方法实际案例

  • 此方法没有任何和实例、类相关的部分,可以作为一个独立函数使用
  • 某些场景下,从业务逻辑来说又属于类的一部分
  • 例子:简单工厂方法
class Game:
    def __init__(self, first_hero, second_hero):
        self.first_hero = first_hero
        self.second_hero = second_hero

    # fight有和实例变量交互的部分,所以需要定义为一个普通方法
    def fight(self):
        print(f"本轮比赛开始,由{self.first_hero} vs {self.second_hero}")

    # start没有和类或实例交互的部分,那么就可以使用staticmethod
    @staticmethod
    def start():
        print("游戏开始")


Game.start()
game1 = Game("Bob", "Mary")
game2 = Game("Mike", "Henry")
game1.fight()
game2.fight()

10.python装饰器

函数引用

  • 函数可以被引用
  • 函数可以被赋值给一个变量
def hello():
    print("hello world!")


harry = hello
harry()

闭包函数

  • 闭包的内部函数中,对外部作用域的变量进行引用
  • 闭包无法修改外部函数的局部变量
  • 闭包可以保存当前的运行环境
def output_student(grade):
    def inner(name, gender):
        print(f"hdc开学啦!学生的名称是{name},性别是{gender},年级是{grade}")

    return inner

student = output_student(1)
student("罗恩", "男")
student("哈利", "男")
student("赫敏", "女")

 为什么要学习装饰器

  • 行业需求: 涉及 Python 技术栈,面试常见题
  • 使用需求: 优化代码的可读性,可维护性

装饰器示例

  • 函数体开始执行与结束执行的时候分别添加打印信息
# 不使用装饰器的代码
def timer(func):
    print("计时开始")
    func()
    print("计时结束")

def hdc():
    print("xx学院")

timer(hdc)

装饰器:

# 使用装饰器的代码
def timer(func):
    def inner():
        print("计时开始")
        func()
        print("计时结束")

    return inner

@timer
def hdc():
    print("xx学院")

hdc()

装饰器练习

  • 实现一个计时器的装饰器,计算函数执行时间

 装饰带参数函数

import datetime

def timer(func):
    def inner(*args, **kwargs):
        # 获取当前时间
        start_time = datetime.datetime.now()
        func(*args, **kwargs)
        for i in range(1, 10000000):
            i += 1
        end_time = datetime.datetime.now()
        print(f"函数的执行时间{end_time - start_time}")

    return inner

@timer
def xueyuan(name):
    print("xxx学院", name)

xueyuan("hello")

11.学生信息管理系统

  • 编写学员实体类 Student,对应成员变量包含:学号 id、姓名 name、性别 sex;
  • 编写学员管理类 StudentManagement ,实现添加学员方法 addStudent()。
  • 编写StudentManagement的main()方法进行学员信息的添加:
学号:1001,姓名:张三,性别:男。
学号:1002,姓名:莉丝,性别:女。
学号:1003,姓名:王武,性别:男。
  • 编写学员管理类 StudentManagement ,实现删除学员方法 deleteStudent(),根据学员id 删除以下学员: 
学号:1002,姓名:莉丝,性别:女。

示例效果 命令行输出打印效果如下:

添加的学员信息:

  • 学号:1001,姓名:张三,性别:男
  • 学号:1002,姓名:莉丝,性别:女
  • 学号:1003,姓名:王武,性别:男

删除后的学员信息:

  • 学号:1001,姓名:张三,性别:男
  • 学号:1003,姓名:王武,性别:男
class Student:
    def __init__(self, id, name, sex):
        self.id = id
        self.name = name
        self.sex = sex

    def __repr__(self):
        return f"学号:{self.id},姓名:{self.name},性别:{self.sex}"


class StudentManagement:
    student_list = []

    # 单个添加学生
    def add_student(self, stu):
        result = self.get_student_by_id(stu.id)
        if result:
            print(f"学员{stu.id}已存在,请核对学生信息")
        else:
            self.student_list.append(stu)
            print(f"添加成功,添加的学员信息为:{stu}")

    # 添加多个学员
    def addStudents(self, stu_list):
        add_list = []
        for s in stu_list:
            result = self.get_student_by_id(s.id)
            if result:
                print(f"学员{s.id}已存在,请核对学生信息")
            else:
                self.student_list.append(s)
                add_list.append(s)

        if add_list:
            print("添加成功,添加的学员信息为:")
            for i in add_list:
                print(i)

    # 根据id查找学生
    def get_student_by_id(self, stu_id):
        for stu in self.student_list:
            if stu.id == stu_id:
                return stu

    # 查询所有学生
    def get_all_student(self):
        for stu in self.student_list:
            print(stu)

    # 根据id删除学生
    def delete_student_by_id(self, stu_id):
        result = self.get_student_by_id(stu_id)
        if result:
            self.student_list.remove(result)
            print(f"删除成功,删除的学员信息为:{result}")
            print("删除后的学员信息为:")
            self.get_all_student()
        else:
            print("删除失败,请核对学生信息")

    def menu(self):
        print("|----------欢迎来到学员信息管理系统------------------------|")
        print("|----------1.根据学号查看学员信息-------------------------|")
        print("|----------2.添加学员-----------------------------------|")
        print("|----------3.根据学号删除学员后:查看所有学员信息------------|")
        print("|----------4.查询当前所有学员的信息-----------------------|")
        print("|----------5.退出系统-----------------------------------|")


if __name__ == '__main__':
    stumg = StudentManagement()
    while True:
        stumg.menu()
        n = int(input("请输入你的选择:"))
        if n == 1:
            id = int(input("请输入想要查找的学员编号:"))
            print(stumg.get_student_by_id(id))
        elif n == 2:
            id = int(input("请输入学员编号:"))
            name = input("请输入学员姓名:")
            sex = input("请输入学员性别:")
            stumg.add_student(Student(id, name, sex))
        elif n == 3:
            id = int(input("请输入想要删除的学员编号:"))
            stumg.delete_student_by_id(id)
        elif n == 4:
            stumg.get_all_student()
        elif n == 5:
            print("成功退出系统,欢迎下次使用!")
            break
        else:
            print("输入有误!重新输入!")
            continue

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/827762.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深度学习各层负责什么内容?

1、深度学习——神经网络简介 深度学习(Deep Learning)(也称为深度结构学习【Deep Structured Learning】、层次学习【Hierarchical Learning】或者是深度机器学习【Deep Machine Learning】)是一类算法集合&#xff0c;是机器学习的一个分支。 深度学习方法近年来&#xff0c…

Expectation (Easy Version) 2023“钉耙编程”中国大学生算法设计超级联赛(5)hdu7330

Problem - 7330 题目大意&#xff1a;有n次游戏&#xff0c;每次游戏有a/b的概率获胜&#xff0c;且相互独立&#xff0c;如果当前赢了cnt次游戏&#xff0c;那么这次游戏会赢得的分数&#xff0c;问最后得分的期望 1<n<1e6;1<m,a<b<998244353 思路&#xff…

windows10 设置代理

场景&#xff1a;同一个办公室&#xff0c;只有A的电脑有权限访问网站 http://10.129.129.129:5601&#xff0c; 那办公室其他B,C同学想访问 http://10.129.129.129:5601&#xff0c;需要怎么处理&#xff1f; A 同学电脑安装代理软件&#xff1a; 1. 下载wproxy IMFirewall, …

d3dx9_30.dll如何修复,分享几种一键修复方法

d3dx9_30.dll是DirectX 的一个动态链接库文件&#xff0c;它包含了一些用于图形和游戏的函数和资源。在了解d3dx9_30.dll的解决方法和丢失原因之前&#xff0c;我们先来了解一下DirectX。DirectX是一套由微软开发的多媒体和游戏编程接口&#xff08;API&#xff09;集合。它提供…

0802|IO进程线程 day5 进程概念

一、进程的基础 1.1 什么是进程 1&#xff09;进程是程序的一次执行过程 程序&#xff1a;是静态的&#xff0c;它是存储在外存上的可执行二进制文件&#xff1b;进程&#xff1a;动态的概念&#xff0c;它是程序的一次执行过程&#xff0c;包括了进程的创建&#xff0c;调度、…

c语言——计算两个正整数的最大公倍数

//计算两个正整数的最大公倍数 //例如40和60的最大公约数为20. //计算两个正整数的最大公倍数 //例如40和60的最大公约数为20. #include<stdio.h> int main() {int a,b,temp,i;printf("Input a & b:");scanf("%d%d",&a,&b);if(a<b){…

Cat.1如何成为物联网业务加速器?

随着Cat.1芯片及模组在功耗和成本上的不断优化&#xff0c;在窄带物联网领域&#xff0c;越来越多的终端客户把Cat.1当做与NB-IoT相比较的第二选择。越来越多的表计、烟感、市政等行业终端将Cat.1模组应用于非集中化部署的上报类终端业务中&#xff0c;Cat.1这只“网红猫”仍保…

UIKit相关

CALayer和UIView 区别 UIView继承自UIResponder&#xff0c;主要负责事件传递、事件响应&#xff0c;属于基于UIKit框架 CALayer继承自NSObject&#xff0c;负责图像渲染&#xff0c;动画和视图的显示&#xff0c;属于QuartzCore框架 而且这两大内容都符合单一职责原则&#…

【开发心得】黑客是如何攻击你的web应用的?

本文记录一次黑客利用sql注入漏洞攻击应用系统的全过程。 由于涉及到隐私&#xff0c;所以就不能上图了&#xff0c;尽量把过程描述的详细一下&#xff0c;希望能够给开发人员提个醒&#xff0c;有些漏洞&#xff0c;其实修补很简单。好在现在有了chatGPT&#xff0c;把你的代…

调度:setTimeout 和 setInterval

有时一个函数并不需要立刻执行&#xff0c;而是等待特定一段时间之后再执行。这就是所谓的“计划调用&#xff08;scheduling a call&#xff09; setTimeout() 是延时器&#xff0c;setInterval() 是定时器 setTimeout 允许我们将函数推迟到一段时间间隔之后再执行。setInte…

mongodb docker 及常用命令

MongoDB属于非关系型数据库&#xff0c;它是由C编写的分布式文档数据库。内部使用类似于Json的bson二进制格式。 中文手册 https://www.w3cschool.cn/mongodb/ 安装 https://www.mongodb.com/try/download/community 二进制安装可见另一篇&#xff1a; centos7 mongodb 4.0.28…

el-tooltip设置文字溢出时展示否则不展示

改写el-tooltip使其支持文字溢出时展示否则不展示&#xff0c;而不是需要使用js设置单独控制 新建 src/utils/rewriteElTooltip.js &#xff08;一模一样 cv就行&#xff09; export default function rewriteElTooltip(el) {el.props {...el.props,overflow: Boolea…

docker: Error response from daemon: No command specified.

执行 docker run -it -d -v /home/dell/workspace/workspace/test_192.168.1.202_pipeline:/home/workspace1 --name test_192.168.1.202_pipeline_10 qnx:7.1报错 问题定位&#xff1a;export导入的镜像需要带上command&#xff0c;以下命令查看command信息 docker ps --no…

计算机二级Python基本操作题-序号44

1. # 使用turtle库的turtle.fd()函数和turtle.seth()函数绘制一个边长为100的三角形 import turtle for i in range(3): #绘制三条边turtle.seth(i * 120) #底边行进角度为0&#xff1b;右斜边行进角度为120(按逆时针);左斜边行进角度为240(按逆时针)turtle.fd(100) #边长为100…

甜椒叶病害数据集

1.数据集分为训练集和测试集 2.训练集如下所示 第一个文件夹是细菌斑叶&#xff08;449张&#xff09; 第二个是健康叶子&#xff08;4014张&#xff09; 测试集 细菌斑叶 11张 健康叶子10张 import numpy as np import os import matplotlib.pyplot as plt import cv2impor…

创建个人博客(在文章的列表页,根据文章标题和文章内容实现搜索)

1. 在视图文件增加搜索表单&#xff1a; 在文章列表页的视图文件中&#xff0c;增加一个搜索表单&#xff0c;包含一个文本搜索框和一个提交按钮 <% form_tag articles_path, method: :get do %><% text_field_tag :title, params[:title], placeholder: "搜索…

关于拓扑排序

又重新学了一下拓扑排序&#xff0c;这次发现就十分简单了&#xff0c;拓扑排序的步骤 1.他必须是一个有向无环图&#xff0c;起点我们就是入度为0的点 2.我们首先要输出的就是入度为0的点&#xff0c;然后依次删除这些点连向的点&#xff0c;使这些点的入度-1&#xff0c;如果…

Java POI 基于模板导出列表数据

目录 1、基于POI模板导出列表数据 &#x1f4da;1.1、需求 &#x1f4dd;1.2、思路 &#x1f331;1.3、实现 &#x1f3e1; 2、导出用户详细数据 &#x1f64e;2.1、需求 &#x1f4bc;2.2、思路 &#x1f468;‍&#x1f4bb;2.3、实现 &#x1f46d; 3、导出数据带图片、公式…

基于STM32设计的数显热水器

一、项目介绍 当前介绍的项目是基于 STM32F103ZET6 系列 MCU 设计的数显热水器&#xff0c;通过显示屏来显示热水器的温度及其工作状态&#xff0c;通过 PT100 传感器来检测热水器的温度变化&#xff0c;并通过电加热片实现加热过程&#xff0c;以达到控制热水器温度的目的。 …

虚拟机之间配置免密登录

目录 一、配置主机名映射 二、虚拟机配置SSH免密登录 三、验证 一、配置主机名映射 即修改/etc/hosts文件&#xff0c;将几台服务器和主机名进行映射。 注意每台服务器都要进行同样的配置。这样在各自服务器下&#xff0c;我们就可以通过主机名访问对应的ip地址了。 当然&…