python进阶篇-day03-学生管理系统与深浅拷贝

news2024/9/20 13:17:48

day03-学生管理系统-面向对象

魔术方法: __ dict __将对象的属性和属性值封装为字典

用字典的值实例化对象: 对象名(**字典) => 拆包

student.py

"""
该文件记录的是: 学生类的信息.
​
学生的属性如下:
    姓名, 性别, 年龄, 联系方式, 描述信息
"""
​
# 1. 定义学生类.
class Student(object):
    # 2. 初始化学生信息
    def __init__(self, name, gender, age, mobile, des):
        """
        该魔法方法用于 初始化 学生的属性信息.
        :param name: 姓名
        :param gender: 性别
        :param age: 年龄
        :param mobile: 手机号
        :param des: 描述信息
        """
        self.name = name
        self.gender = gender
        self.age = age
        self.mobile = mobile
        self.des = des
​
    # 3. 打印学生信息.
    def __str__(self):
        # print(__name__)
        return f'姓名: {self.name}, 性别: {self.gender}, 年龄: {self.age}, 手机号: {self.mobile}, 描述信息: {self.des}'
        # return '姓名: %s, 性别: %s, 年龄: %d, 手机号: %s, 描述信息: %s' % (self.name, self.gender, self.age, self.mobile, self.des)
​
​
# 4. 记得在main函数中测试, 否则别人导入这个模块的时候, 会自动执行如下的测试代码.
if __name__ == '__main__':
    # 5. 创建学生对象.
    s = Student('乔峰', '男', 39, '13112345678', '丐帮帮主')
    # 6. 打印学生信息.
    print(s)

student_cms.py

"""
该文件记录的是: 学生管理系统类的信息.
​
名词 cms 解释:
    全称叫: Content Management System, 内容管理系统.
​
学生管理系统类 StudentCms
    属性:
        stu_info = [{学生信息}, {学生信息}...]
        即: stu_info = [学生对象, 学生对象...]
    行为: 函数
        __init__()      # 初始化属性信息
        show_view()     # 打印提示信息, 无需使用self对象, 所以设置为: 静态方法.
        add_student()   # 添加学生信息
        del_student()   # 删除学生信息
        update_student()   # 修改学生信息
        search_one_student()   # 查询单个学生信息
        search_all_student()   # 查询所有学生信息
        save_student()   # 保存学生信息 => 文件中, 存档.
        load_student()   # 从文件中 => 学生信息, 读档.
        start()   # 表示整体的业务逻辑 => 框架
"""
# 导包
import time
import os  # Operating System: 系统模块.
from student import Student
​
​
# 1. 定义学生管理系统类.
class StudentCms(object):
    # 2. 定义初始化属性.
    def __init__(self):
        # 格式: [{学生信息}, {学生信息}...],   即: [学生对象, 学生对象...]
        self.stu_info = []
​
        # 为了提高效率, 准备的测试数据
        # s1 = Student('乔峰', '男', 39, '131', '丐帮帮主')
        # s2 = Student('阿朱', '女', 35, '151', '丐帮帮主夫人')
        # s3 = Student('虚竹', '男', 31, '161', '灵鹫宫宫主')
        # s4 = Student('李清露', '女', 25, '171', '灵鹫宫宫主夫人')
        # self.stu_info = [s1, s2, s3, s4]
​
    # 3. show_view()     # 打印提示信息, 设置为: 静态方法.
    @staticmethod
    def show_view():
        print("*" * 21)
        print("欢迎使用学生管理系统V2.0")
        print("\t1. 添加学生信息")
        print("\t2. 修改学生信息")
        print("\t3. 删除学生信息")
        print("\t4. 查询单个学生信息")
        print("\t5. 查询所有学生信息")
        print("\t6. 保存学生信息")
        print("\t7. 退出系统")
        print("*" * 21)
​
    # 4. add_student()   # 添加学生信息
    def add_student(self):
        # 4.1 提示用户录入学生信息 并接收.
        name = input('请录入学生的姓名: ')
        gender = input('请录入学生的性别: ')
        age = input('请录入学生的年龄: ')
        mobile = input('请录入学生的手机号: ')
        des = input('请录入学生的描述信息: ')
        # 4.2 将上述的信息封装成 学生对象.
        new_stu = Student(name, gender, age, mobile, des)
        # 4.3 将学生对象添加到列表中.
        self.stu_info.append(new_stu)
        # 4.4 打印提示信息.
        print(f"添加学生 {name} 的信息成功!\n")
​
    # 5. del_student()   # 删除学生信息
    def del_student(self):
        # 5.1 提示用户录入要删除的学生 姓名.      扩展: 假设存在重名学生, 都要删掉, 自己代码实现.
        del_name = input('请录入要删除的学生姓名: ')
        # 5.2 遍历学生列表, 获取每个学生信息.
        for stu in self.stu_info:
            # stu: 就是具体的每个学生对象.
            # 5.3 判断当前学生信息, 是否是 要删除的学生.
            if stu.name == del_name:
                # 5.4 走这里, 删除该学生对象即可.
                self.stu_info.remove(stu)
                print(f"删除学生 {del_name} 的信息成功!\n")
                break
        else:
            # 5.5 走这里, 说明没有找到要删除的学生.
            print(f'未找到 {del_name} 学生信息, 请校验后重新操作!\n')
​
    # 6. update_student()   # 修改学生信息
    def update_student(self):
        # 6.1 提示用户录入要修改的学生 姓名, 并接收.
        update_name = input('请录入要修改的学生姓名: ')
        # 6.2 遍历学生列表, 获取每个学生的信息.
        for stu in self.stu_info:
            # stu: 就是具体的每个学生对象.
            # 6.3 判断当前学生信息, 是否是 要修改的学生.
            if stu.name == update_name:
                # 6.4 走这里, 提示用户, 录入要修改的信息, 并修改当前学生的信息.
                stu.gender = input('请录入新的性别: ')
                stu.age = input('请录入新的年龄: ')
                stu.mobile = input('请录入新的手机号: ')
                stu.des = input('请录入新的描述信息: ')
                # 6.5 提示, 并结束.
                print(f"修改 {update_name} 的信息成功!\n")
                break
        else:
            # 6.6 走这里, 说明没有找到要修改的学生.
            print(f'未找到 {update_name} 学生信息, 请重新操作!\n')
​
    # 7. search_one_student()   # 查询单个学生信息
    def search_one_student(self):
        # 7.1 提示用户录入要查询的学生 姓名, 并接收.
        search_name = input('请录入要查询的学生姓名: ')
        # 7.2 遍历学生列表, 获取每个学生的信息.
        for stu in self.stu_info:
            # stu: 就是具体的每个学生对象.
            # 7.3 判断当前学生信息, 是否是 要查询的学生.
            if stu.name == search_name:
                # 7.4 走这里, 说明找到了, 打印即可.
                # print(stu, '\n')
                print(stu, end='\n\n')
                break
        else:
            # 7.5 走这里, 说明没有找到要修改的学生.
            print(f'未找到 {search_name} 学生信息, 请重新操作!\n')
​
    # 8. search_all_student()   # 查询所有学生信息
    def search_all_student(self):
        # 8.1 判断列表中是否有 学生信息.
        if len(self.stu_info) <= 0:
            # 8.2 走这里, 说明暂无学生信息.
            print('暂无学生信息, 请添加后重新查询!\n')
        else:
            # 8.3 走这里, 说明有学生信息, 遍历打印即可.
            for stu in self.stu_info:
                print(stu)
            print()  # 换行, 让格式更加好看.
​
    # 9. save_student()   # 保存学生信息 => 文件中, 存档.
    def save_student(self):
        # 9.1 把 学生对象列表 => 列表嵌套字典的形式, 即:  [学生对象, 学生对象...]    =>  [{学生信息}, {学生信息}...]
        stu_dict_list = [stu.__dict__ for stu in self.stu_info]
        # 9.2 把上述的学生信息(列表嵌套字典), 写到目的地文件 student.data 文件中.
        with open('./student.data', 'w', encoding='utf-8') as dest_f:  # dest: 目的地
            # 9.3 具体的写的动作.
            # 先把 列表嵌套字典, 转换成 字符串, 再写入到目的地文件中.
            dest_f.write(str(stu_dict_list))
            # 9.4 提示即可.
            print('学生信息存档成功!\n')
​
    # 10. load_student()   # 从文件中 => 学生信息, 读档.
    def load_student(self):
        # 10.1 判断数据源文件是否存在.
        if os.path.isfile('./student.data'):  # 判断 student.data 必须是 存在的 文件才行.
            # 10.2 走到这里, 说明源文件存在, 读取文件信息即可.
            with open('./student.data', 'r', encoding='utf-8') as src_f:
                # 10.3 具体的读取文件数据的操作.
                # 格式为:  "[{'name': '乔峰', 'gender': '男', 'age': 39, 'mobile': '131', 'des': '丐帮帮主'}, {学生信息}, {学生信息}...]"
                str_list_data = src_f.read()
                # 10.4 判断 字符串的长度是否合法, 如果不合法, 给个默认值.
                if len(str_list_data) <= 0:
                    str_list_data = '[]'
                # 10.5 把上述的 字符串形式的 列表嵌套字典 => 列表嵌套字典 的格式.
                # 格式为: [{'name': '乔峰', 'gender': '男', 'age': 39, 'mobile': '131', 'des': '丐帮帮主'}, {学生信息}, {学生信息}...]
                list_data = eval(str_list_data)  # eval(): 去掉最外边的那组引号, 剩下的是啥就转成什么类型.
                # 10.6 把上述的列表嵌套字典形式的 学生数据 => 学生列表对象, 即: [学生对象, 学生对象...]
                self.stu_info = [Student(**stu_dict) for stu_dict in list_data]
        else:
            # 10.7 走这里, 说明文件不存在, 创建即可.
            # src_f = open('./student.data', 'w', encoding='utf-8')
            # src_f.close()
​
            # 扩展: 你去查一下 os模块中是否有直接创建文件的函数, 有可以直接使用它来完成需求.
            os.open('./student.data', flags=os.O_CREAT)  # 效果同上.
​
    # 11. start()   # 表示整体的业务逻辑 => 框架
    def start(self):
        # 11.0 加载学生的信息, 类似于: 读档.
        self.load_student()
​
        # 11.1 因为是重复操作的, 所以用 while(True) 死循环.
        while True:
            # 11.2 模拟用户等待
            time.sleep(1)  # 1秒
            # 11.3 打印提示信息
            # self.show_view()      # 静态方法, 调用方式1: 对象名.   可以, 但是不推荐.
            StudentCms.show_view()  # 静态方法, 调用方式1: 类名.     推荐
​
            # 11.4 提示用户录入他/她要操作的编号, 并接收.
            num = input('请录入您要操作的编号: ')
            # 11.5 基于用户录入的编号, 判断, 并进行对应的操作.
            if num == '1':
                # print("1. 添加学生信息")
                self.add_student()
            elif num == '2':
                # print("2. 修改学生信息")
                self.update_student()
            elif num == '3':
                # print("3. 删除学生信息")
                self.del_student()
            elif num == '4':
                # print("4. 查询单个学生信息")
                self.search_one_student()
            elif num == '5':
                # print("5. 查询所有学生信息")
                self.search_all_student()
            elif num == '6':
                # print("6. 保存学生信息")
                self.save_student()
            elif num == '7':
                # 细节: 退出系统, 给一个提示信息.
                result = input('您确定要退出吗, y(退出), 其它(继续) => ')
                if result.lower() == 'y':  # lower()函数: 把字母转成其对应的 小写形式.
                    time.sleep(2)
                    # 细节: 也可以考虑, 在退出之前(就是这里), 再次保存下学生信息.
                    # self.save_student()
                    print('感谢您的使用, 再见!')
                    break
            else:
                print('录入有误, 请重新录入!\n')
​
​
# 12. 在main方法中测试.
if __name__ == '__main__':
    stu_cms = StudentCms()
    stu_cms.start()

main.py

"""
该文件记录的是: 学生管理系统的主入口
​
目前的文件
    student.py      => 存放 Student 学生类信息的
    student_cms.py  => 存放 StudentCms 学生管理系统类 信息的.
"""
​
# 导包
from student_cms import StudentCms
​
# 1. 制定程序的主入口
if __name__ == '__main__':
    # 2. 创建学生管理系统类 对象
    stu_cms = StudentCms()
    # 3. 启动程序.
    stu_cms.start()

深浅拷贝

回顾可变与不可变类型

划分依据

在不改变地址值的情况下, 是否可以修改内容, 可以 => 可变类型, 不可以 => 不可变类型.

代码

# 需求1: 演示不可变类型.
a = 10
print(f'a的值: {a}')           # 10
print(f'a的地址: {id(a)}')     # 0x01
# 修改不可变类型
a = 20
print(f'a的值: {a}')           # 20
print(f'a的地址: {id(a)}')     # 0x02
print('-' * 21)
​
​
# 需求2: 演示可变类型.
list1 = [1, 2, 3]
print(f'list1的值: {list1}')          # [1, 2, 3]
print(f'list1的地址: {id(list1)}')    # 0x03
# 修改可变类型
list1[1] = 200
print(f'list1的值: {list1}')          # [1, 200, 3]
print(f'list1的地址: {id(list1)}')    # 0x03
​

深浅拷贝介绍

  1. 所谓的深浅拷贝, 指的是: 拷贝的多与少. 深拷贝拷贝的多, 浅拷贝拷贝的少.

  2. 深浅拷贝都可以操作可变 和 不可变类型, 但是深浅拷贝一般不会操作不可变类型, 且你遇到的面试题几乎都是: 深浅拷贝操作可变类型.

  3. 回顾可变和不可变类型, 划分依据: 在不改变地址值的情况下, 是否可以修改内容, 可以 => 可变类型, 不可以 => 不可变类型.可变类型: 列表, 字典, 集合不可变类型: 字符串, 整数, 浮点型, 元组, 布尔...

  4. 所谓的深浅拷贝, 指的就是 copy 模块的不同函数.浅拷贝: copy.copy()深拷贝: copy.deepcopy()

代码演示

# 导包
import copy
​
# python的赋值操作属于引用赋值(eg:b是a的别名, 形参是实参的别名)
def dm01_普通赋值():
​
    # 1 python中的赋值操作, 属于引用赋值 (把a的地址赋值给b)
    # 2 b是a的别名, b和a都指向相同的内存空间
    a = 10
    b = a
    print('id(a)-->', id(a))    # 0x01
    print('id(b)-->', id(b))    # 0x01
    print('id(10)-->', id(10))  # 0x01
​
    # 3 也是引用赋值 c和d指向相同的内存空间
    a = [1, 2, 3]
    b = [11, 22, 33]
    c = [a, b]
    d = c
    print('id(c)-->', id(c))    # 0x03
    print('id(d)-->', id(d))    # 0x03
​
    # 4 值的方式赋值 a 指向一块内存空间、b 也指向一块内存空间
    # b = a python中不支持, 这样做传参效率高
​
​
# 浅拷贝可变类型: 只拷贝第1层数据, 深层次数据不拷贝
def dm02_浅拷贝可变类型():
    a = [1, 2, 3]
    b = [11, 22, 33]
    c = [6, 7, a, b]
​
    # 测试1 id(c)和id(d)
    d = copy.copy(c)        # 浅拷贝 = 只会拷贝 可变类型的 第1层数据.
    print('id(c)-->', id(c))    # 0x03
    print('id(d)-->', id(d))    # 0x04
    print("id(c)和id(d)值不一样, 说明浅拷贝第1层(最外面一层的数据)")
​
    # 测试2
    print(id(c[2]))     # 0x01
    print(id(a))        # 0x01
    print("id(c[2])和id(a)值一样, 说明浅拷贝第2层的数据")
​
    # 修改a[2] = 22
    a[2] = 22
    # c[0] = 100
    print('c->', c)     # [6, 7, [1, 2, 22], [11, 22, 33]]
    print('d->', d)     # [6, 7, [1, 2, 22], [11, 22, 33]]
​
​
# 浅拷贝不可变类型: 不会给拷贝的对象c开辟新的内存空间, 而只是拷贝了这个对象的引用
def dm03_浅拷贝不可变类型():
​
    # 不可变类型 a b c
    a = (1, 2, 3)
    b = (11, 22, 33)
    c = (6, 7, a, b)
​
    d = copy.copy(c)
    print('id(c)-->', id(c))    # 0x03
    print('id(d)-->', id(d))    # 0x03
    print("id(c)和id(d)值一样, 说明c和d指向相同的内存空间")
​
​
# 深拷贝可变类型: 若为可变类型开辟新的内存空间,所有层都会深拷贝
# 作用: 能保证数据的安全
def dm04_深拷贝可变类型():
    a = [1, 2, 3]
    b = [11, 22, 33]
    c = [6, 7, a, b]
​
    d = copy.deepcopy(c)
    print('id(c)-->', id(c))    # 0x03
    print('id(d)-->', id(d))    # 0x04
​
​
    a[1] = 100
    b[1] = 800
    print(f'c: {c}')    # [6, 7, [1, 100, 3], [11, 800, 33]]
    print(f'd: {d}')    # [6, 7, [1, 2, 3], [11, 22, 33]]
​
​
# 深拷贝不可变类型: 若为不可变类型直接就引用了, 不开辟新的内存空间
def dm05_深拷贝不可变类型():
    a = (1, 2, 3)
    b = (11, 22, 33)
    c = (a, b)
​
    d = copy.deepcopy(c)
    print(id(c))    # 0x03
    print(id(d))    # 0x03
    print("c/d内存空间相同, 说明c和d指向相同的内存空间")
​
​
​
​
# 在main函数中测试
if __name__ == '__main__':
    # dm01_普通赋值()
    # dm02_浅拷贝可变类型()
    # dm03_浅拷贝不可变类型()
    # dm04_深拷贝可变类型()
    dm05_深拷贝不可变类型()

图解深浅拷贝

普通赋值内存图

浅拷贝操作可变类型

浅拷贝操作不可变类型

深拷贝操作可变类型

深拷贝操作不可变类型

等同于普通赋值操作和浅拷贝操作不可变类型

总结

list1 = [1, 2, list2]

深浅拷贝操作不可变类型时相当于普通赋值操作, 即增加地址指向, 并不会重新开辟内存地址

浅拷贝操作可变类型: 拷贝第一层, 拷贝内容为:list0 = [1, 2, list2的地址指向]

修改list2的内容对拷贝后的数据直接影响, 修改list1无影响

深拷贝操作可变类型: 拷贝所有可变类型的层级, 即: 将list1拷贝, 并将list1中的list2同时拷贝一份, 修改元数据对拷贝后的数据无影响, 重新开辟内存空间

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

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

相关文章

单片机-STM32 ADC应用(五)

1.ADC模数转换 模拟数字转换器即A/D转换器&#xff0c;或简称ADC&#xff0c;通常是指一个将模拟信号转变为数字信号的电子元件。通常的模数转换器是将一个输入电压信号转换为一个输出的数字信号。由于数字信号本身不具有实际意义&#xff0c;仅仅表示一个相对大小。故任何一个…

STM32学习记录-11-RTC实时时钟

1 Unix时间戳 Unix 时间戳(Unix Timestamp)定义为从UTC/GMT的1970年1月1日0时0分0秒开始所经过的秒数,不考虑闰秒 时间戳存储在一个秒计数器中,秒计数器为32位/64位的整型变量 世界上所有时区的秒计数器相同,不同时区通过添加偏移来得到当地时间 2 UTC/GMT GMT(Green…

量化面试题:什么是朴素贝叶斯分类器?

朴素贝叶斯分类器是一种基于贝叶斯定理的简单而有效的分类算法。它的核心思想是利用特征之间的条件独立性假设来进行分类。以下是朴素贝叶斯分类器的几个关键点&#xff1a; 贝叶斯定理&#xff1a;朴素贝叶斯分类器基于贝叶斯定理&#xff0c;该定理描述了在已知某些条件下&a…

名城优企游学活动走进龙腾半导体:CRM助力构建营销服全流程体系

8月29日&#xff0c;由纷享销客主办的“数字中国 高效增长——名城优企游学系列活动之走进龙腾半导体”研讨会在西安市圆满落幕&#xff0c;来自业内众多领袖专家参与本次研讨会&#xff0c;深入分享交流半导体行业的数字化转型实践&#xff0c;探讨行业数字化、智能化转型之路…

华大智造 否极泰来

甲辰年开年至今&#xff0c;华大智造&#xff08;688114.SH&#xff09;经历了上市以来“最漫长的季节”。 仅在这半年多时间里&#xff0c;这家已经实现全球化布局且能排位在行业最前列的中国生命科技企业&#xff0c;遭遇了几乎所有能遭遇的不利局面。 宏观环境&#xff0c…

前端代码提交前的最后防线:使用Husky确保代码质量

需求背景 我们通常会引入ESLint和Prettier这样的工具来帮助我们规范本地代码的格式。然而&#xff0c;这种格式化过程仅在本地有效&#xff0c;并且依赖于我们在VSCode中手动设置自动保存功能。如果团队成员忘记进行这样的配置&#xff0c;或者在没有格式化的情况下提交了代码…

GIS地理信息+智慧巡检技术解决方案(Word原件)

1.系统概述 1.1.需求描述 1.2.需求分析 1.3.重难点分析 1.4.重难点解决措施 2.系统架构设计 2.1.系统架构图 2.2.关键技术 3.系统功能设计 3.1.功能清单列表 软件全套资料部分文档清单&#xff1a; 工作安排任务书&#xff0c;可行性分析报告&#xff0c;立项申请审批表&#x…

Datawhale X 李宏毅苹果书AI夏令营 Task1.2深度学习进阶详解

目录 一、批量梯度下降法&#xff08;Batch Gradient Descent&#xff0c;BGD&#xff09; 二、随机梯度下降法&#xff08;Stochastic Gradient Descent&#xff0c;SGD&#xff09; 三、动量法&#xff08;Momentum Method&#xff09; 四、自适应学习率的方法 五、并行…

微信小程序认证和备案

小程序备案的流程一般包括以下步骤‌&#xff1a; 准备备案所需材料‌&#xff1a;通常需要提供‌营业执照、法人的‌身份证、两个‌手机号和一个邮箱等资料。 ‌1 ‌登录‌微信公众平台‌&#xff1a;作为第一次开发微信小程序的服务商&#xff0c;需要通过微信公众平台申请…

JVM内存模型简述

JVM内存结构 虚拟机栈&#xff1a; 每个方法会在虚拟机栈中创建一个栈帧&#xff0c;存储这个方法的局部变量表&#xff0c;操作数栈&#xff0c;方法出口等信息。本地方法栈&#xff1a; 与虚拟机栈类似&#xff0c;只是虚拟机栈执行java方法&#xff0c;本地方法栈执行native…

工业园区智慧水务物联网平台建设方案

1. 项目背景与水资源现状 《工业园区智慧水务物联网平台建设方案》针对水资源分布不均、短缺严重的问题&#xff0c;提出了智慧水务物联网平台的建设方案&#xff0c;以应对漏损危害和提升水资源管理效率。 2. 水资源管理政策与目标 国家通过“水十条”和供水数据&#xff0…

基于yolov8的打架行为检测系统python源码+onnx模型+评估指标曲线+精美GUI界面

【算法介绍】 基于YOLOv8的打架行为检测系统&#xff0c;是当前公共安全领域的一项重要创新。YOLOv8作为最新的目标检测算法&#xff0c;以其高效、准确的性能&#xff0c;在各类图像和视频处理任务中表现出色。该系统利用YOLOv8的先进图像处理和机器学习算法框架&#xff0c;…

品牌知识产权维权的原因

在当今竞争激烈的商业环境中&#xff0c;品牌知识产权维权的重要性愈发凸显。品牌的价值不仅仅在于其产品或服务的质量&#xff0c;更在于其独特的标识、创新的技术以及丰富的文化内涵。而这些宝贵的资产&#xff0c;往往需要通过有效的知识产权保护来确保其安全。 品牌在发展的…

SI案例分享--考虑ESD保护二极管的差分线阻抗仿真

如下图所示&#xff0c;显示了利用CST电磁仿真软件构建的边沿耦合微带线的尺寸&#xff0c;按照 100 欧姆的差分线阻抗进行设计。由于差分线经常会通过连接器连接到电缆&#xff0c;因此极有可能发生 ESD 事件&#xff0c;该事件会在短时间内 &#xff08;< 1 ns&#xff09…

JS设计模式之“分即是合” - 建造者模式

引言 当我们在进行软件编程时&#xff0c;常常会遇到需要创建复杂对象的情况。这些对象可能有多个属性&#xff0c;属性之间存在依赖关系&#xff0c;或需要按照特定的骤来创建。在这种情况下&#xff0c;使用建造者模式&#xff08;Builder Pattern&#xff09;可以提供一种活…

搭建IPsec VPN隧道解决PLC设备与主控上位机无法使用公网IP进行通信的问题

问题描述 按照初设规定&#xff0c;每个工程点位都要安装一条具有独立公网IP的光纤专线&#xff0c;供该点位的视频监控设备、水质监测设备及PLC设备与外界进行通信。而在项目开发前期并没有意识到&#xff0c;组态软件(上位机)无法通过公网IP地址连接PLC&#xff0c;导致在交…

【网络原理】Udp 的报文结构,保姆式教学,快速入门

本篇会加入个人的所谓鱼式疯言 ❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言 而是理解过并总结出来通俗易懂的大白话, 小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的. &#x1f92d;&#x1f92d;&#x1f92d;可能说的不是那么严谨.但小编初心是能让更多人…

Tomcat 配置SSL

1、生成SSL证书&#xff1b; 2、配置Tomcat文件&#xff1b; <Connector port"8080" protocol"HTTP/1.1"SSLEnabled"true"keystoreFile"D:/hk.jks"keystorePass"123456"clientAuth"false"sslProtocol"TL…

js字符串格式的数字比较大小

1300>37 为什么是false? 在 JavaScript 中&#xff0c;当比较两个字符串时&#xff0c;比较是基于字典顺序&#xff08;也就是按字符的 Unicode 编码值进行比较&#xff09;的&#xff0c;而不是数字的实际大小。因此&#xff0c;1300 > 37 的结果是 false&#xff0c;…

Halcon提取边缘线段lines_gauss 算子

Halcon提取边缘线段lines_gauss 算子 edges_color_sub_pix和edges_sub_pix两个算子使用边缘滤波器进行边缘检测。还有一个常用的算子lines_gauss算子&#xff0c;也可以用于提取边缘线段&#xff0c;它的鲁棒性非常好&#xff0c;提取出的线段类型是亚像素精度的XLD轮廓。其原…