Python面向对象三大特征(封装、继承、多态)

面向对象编程的三大特征:封装、继承和多态。

注意:在python面向对象编程中,子类对象可以传递给父类类型

一、封装

        在Python中,封装是面向对象编程中的一种重要概念,它可以帮助我们实现数据隐藏、信息保护和代码复用。在Python中,通过使用访问控制修饰符(属性和方法前加上两个下划线)来实现封装。

        封装就是:我写了一个类,我将一个类的属性、方法全部包装到了一个类中。我对类中某些方法和属性进行了隐藏,(外部实例化之后,无法通过对象.方法或对象.属性来进行直接调用)。因为我不想让外部了解我的实现机理或属性,但是会留出一些公有的方法来供外部间接调用这些“封装”好的属性和方法!这就是封装!!!

下面是Python中常用的封装方式:

公有成员:默认情况下,Python中的所有成员(属性和方法)都是公有的,可以被外部访问。例如:

class MyClass:def __init__(self):self.public_var = 10def public_method(self):return "This is a public method."obj = MyClass()
print(obj.public_var) # 10
print(obj.public_method()) # This is a public method.

私有成员:在成员名字前面加上两个下划线 __,可以将其定义为私有成员,外部无法直接访问。(这种前面加两个下划线的私有成员被称为伪私有成员)例如: 

class MyClass:def __init__(self):self.__private_var = 20def __private_method(self):return "This is a private method."obj = MyClass()
# 尝试访问私有属性和方法
print(obj.__private_var)  # 会报错
print(obj.__private_method())  # 会报错

上述代码会报错,原因是在类外部试图访问私有成员(私有属性、私有方法) 。

访问类中的私有成员 

        那么我们该如何在类外访问类中的私有成员呢?答案是:我们可以通过类中的公有方法来访问类中的私有成员。

class MyClass:def __init__(self):self.__private_var = 20def __private_method(self):return "This is a private method."# 访问私有属性 __private_vardef public_method(self):return self.__private_var# 访问私有方法 __private_methoddef get_private_method(self):return self.__private_method()obj = MyClass()
# 尝试访问私有属性和方法
print(obj.__private_var)  # 会报错
print(obj.__private_method())  # 会报错
print(obj.public_method()) # 20
print(obj.get_private_method()) # This is a private method.

        根据上面的代码,我们可以看到, 当直接在类外访问私有属性或私有方法时,程序会报错。我们在类中写了两个公有方法,分别访问类中的私有属性和私有方法,运行程序,访问成功。

        通过封装,我们可以隐藏类的内部实现细节,提高代码的安全性和可维护性。同时,封装也有助于减少代码的耦合度,使代码更易于理解和调试。

细节:由于python语言的动态特性,会出现伪私有属性的情况

其他博客看到的: 

        在Python中,可以通过在属性名前加上__实现伪私有属性,但这并不是真正的私有,只是一种变形,实际上,Python并没有真正意义上的私有属性。

        伪私有属性会被重命名为_类名__属性名。这种重命名是由Python内部的机制在编译时自动完成的。

这种做法的目的是防止子类重写该属性。

例如,定义一个类并使用伪私有属性:

        在这个示例中,__pseudo_private_var 是一个伪私有属性,虽然我们在类的外部尝试直接访问它会报错,但实际上它的名称已经被改写成了 _MyClass__pseudo_private_var,我们可以通过这个改写后的名称来访问伪私有属性。另外,我们也可以通过定义公有方法来间接地访问这个伪私有属性。   

封装练习

●定义Account类
1)Account类要求具有属性:姓名(长度为2-4位)、余额(必须>20)、密码(必须是六位),如果不满足,则给出提示信息,并给默认值(程序员自己定)
2)通过set_xxx的方法给Account的属性赋值。
3)编写方法query_info()接收姓名和密码,如果姓名和密码正确,返回该账号信息

# 分析如下:
# 类名:Account
# 私有属性:姓名(长度为2-4位)、余额(必须>20)、密码(必须为6位)
# 构造器: 无,默认是一个无参的构造器
# 方法:set_xxx(self, 属性名) 进行赋值,并且对各个接收到的数据进行校验
# 方法query_info(self, name, pwd) 而且需要验证,才返回响应信息
class Account:__name = None__balance = None__pwd = Nonedef set_name(self, name):# 2-4位if 2<= len(name) <=4:self.__name = nameelse:print("名字的长度不在2-4位之间!")def set_balance(self, balance):# 余额(必须>20)if balance > 20:self.__balance = balanceelse:print("余额必须大于20!")def set_pwd(self, pwd):# 密码必须是6位if len(pwd) == 6:self.__pwd = pwdelse:print("密码必须设置为6位!")def query_info(self, name, pwd):if name == self.__name and pwd == self.__pwd:return f"账户信息如下: \n账户名: {self.__name}, 账户余额: {self.__balance}"else:return "请输入正确的账户名和密码"account = Account()
account.set_name("tim")
account.set_pwd("000000")
account.set_balance(10000)
print(account.query_info("tim", "000000"))

输出结果: 

账户信息如下: 
账户名: tim, 账户余额: 10000

部分参考自:

https://www.cnblogs.com/blackmatrix/p/5600830.html 

二、继承

2.1 什么是继承?

        在Python中,继承是面向对象编程中的一个重要概念,它允许一个类(称为子类)继承另一个类(称为父类)的属性和方法。通过继承,子类可以复用父类的代码,并且可以在不改变原有代码的情况下添加新的功能或修改已有功能。字面意思就是,一个类是另一个类的子类,那么这个类就可以拥有和父类一样的属性、方法。这就好比是现实当中,儿子会遗传父亲的性格、长相等。

2.2 为什么需要继承?

 我们编写了两个类,一个是Pupil类(小学生),一个是Graduate(大学毕业生)。问题:两个类的属性和方法有很多是相同的,怎么办?这就需要我们的继承特性。

我们先来看看没有继承的代码,如下所示。

class Pupil:name = Noneage = None__score = Nonedef __init__(self, name, age):self.name = nameself.age = agedef show_info(self):print(f"name={self.name} age={self.age} score={self.__score}")def set_score(self, score):self.__score = scoredef testing(self):print(f"小学生在考小学数学")class Graduate:name = Noneage = None__score = Nonedef __init__(self, name, age):self.name = nameself.age = agedef show_info(self):print(f"name={self.name} age={self.age} score={self.__score}")def set_score(self, score):self.__score = scoredef testing(self):print(f"大学生在考高等数学")student1 = Pupil("小白", 10)
student1.testing()
student1.set_score(70)
student1.show_info()print("-----------------")
student2 = Graduate("小黑", 20)
student2.testing()
student2.set_score(80)
student2.show_info()

输出结果: 

小学生在考小学数学
name=小白 age=10 score=70
-----------------
大学生在考高等数学
name=小黑 age=20 score=80

        分析上述代码我们可知,我们创建了两个类,Pupil类和Graduate类,Pubil类中有name、age、_score属性,有显示信息的方法show_info(),有设置分数的方法set_score(),有测试的方法testing();Graduate类中也有name、age、_score属性,有显示信息的方法show_info(),有设置分数的方法set_score(),有测试的方法testing()。

        我们可以看到,除了testing()方法执行的功能不一样外,属性和其余的方法执行的功能均一样。那么我们可以创建一个新类Student,将这两个类共有的属性和方法存放在新类中,随后使得这两个类与新类构成继承关系。修改后的代码如下。

# 父类
class Student:name = Noneage = None__score = Nonedef __init__(self, name, age):self.name = nameself.age = agedef show_info(self):print(f"name={self.name} age={self.age} score={self.__score}")def set_score(self, score):self.__score = scoreclass Pupil(Student):def testing(self):print(f"小学生在考小学数学")class Graduate(Student):def testing(self):print(f"大学生在考高等数学")student1 = Pupil("小白", 10)
student1.testing()
student1.set_score(70)
student1.show_info()print("-----------------")
student2 = Graduate("小黑", 20)
student2.testing()
student2.set_score(80)
student2.show_info()

 输出结果:

小学生在考小学数学
name=小白 age=10 score=70
-----------------
大学生在考高等数学
name=小黑 age=20 score=80

2.3 注意细节

1、子类继承了所有的属性和方法,非私有的属性和方法可以在子类直接访问,但是私有属性和方法不能在子类直接访问,要通过父类提供公共的方法去访问

class Base:# 公共属性n1 = "public attribute"# 私有属性__n2 = "private attribute"# 公共方法def public_method(self):return "public_method"# 私有方法def __private_method(self):return "private_method"class DerivedBase(Base):# 访问公有成员def visit_public(self):print(self.n1)print(self.public_method())def visit_private(self):print(self.__n2)print(self.__private_method)A = DerivedBase()
A.visit_public() # public attribute# public_methodA.visit_private() # 报错

        在子类中通过访问父类的公有方法进一步访问父类的私有成员。 代码如下所示。

class Base:# 公共属性n1 = "public attribute"# 私有属性__n2 = "private attribute"# 公共方法def public_method(self):return "public_method"# 私有方法def __private_method(self):return "private_method"# 提供公共方法,返回私有成员def method(self):print("属性", self.n1, self.__n2)print(self.__private_method())class DerivedBase(Base):# 通过父类的公有方法,访问父类的私有成员def visit(self):self.method()A = DerivedBase()
A.visit()

输出结果: 

属性 public attribute private attribute
private_method

2、python编程语言中,object类是所有类的一个基类

        我们将光标停在如下红框位置,随后按下ctrl+H,得到右栏内容,可以清晰地看到,object类是所有类的一个基类。

3、python支持多重继承

语法格式:

class DerivedClassName(Base1,Base2,Base3....):.....

 示例代码

class A:n1 = 100def sing(self):print("A sing()...", self.n1)class B:n2 = 200def dance(self):print("B dance()...", self.n2)class C(A, B):def visit_AB(self):self.sing()self.dance()return self.n1, self.n2c = C()
print(c.visit_AB())

输出结果:

A sing()... 100
B dance()... 200
(100, 200)

4、在多重继承中,如果有同名的成员,遵守从左到右的继承优先级(即:写左边的父类优先级高,写在右边的父类优先级低)

class A:n1 = 100class B:n1 = 20class C(A, B):passc = C()
print(c.n1) # 100
class A:n1 = 100class B:n1 = 20class C(B, A):passc = C()
print(c.n1) # 20

继承练习题目

编写Computer类,包含CPU、内存、硬盘等属性
1) get_details方法用于返回Computer的详细信息
2)编写PC子类,继承Computer类,添加特有属性【品牌brand】
3)编写NotePad子类,继承Computer类,添加特有属性【color】
4)完成测试,创建PC和NotePad对象,分别给对象中特有的属性赋值,以及从Computer类继承的属性赋值,并使用方法打印输出信息

思路分析
1.父类:Computer
2.公共属性:CPU(cpu)、内存(memory)、硬盘(disk)
3.构造器:__init__(self, cpu , memory,disk)
4.方法: get_details(self)
5.子类:PC(Computer)
6.公共属性:brand
7.构造器: __init__(self,cpu , memory,disk , brand),有一个新的知识点
8.方法: print_info(self)  完成功能:输出pc对象的信息(即属性的信息)
 

class Computer:cpu = Nonememory = Nonedisk = Nonedef __init__(self, cpu, memory, disk):self.cpu = cpuself.memory = memoryself.disk = diskdef get_details(self):return f"cpu: {self.cpu}\t内存: {self.memory}\t硬盘: {self.disk}"class PC(Computer):brand = Nonedef __init__(self, cpu, memory, disk, brand):# 通过super().xx 方式可以去调用父类的方法# 这里,我们通过super().__init__(cpu, memory, disk)去调用父类的构造器,完成对父类属性的初始化任务# self.brand = brand 表示子类特有属性,由子类的构造器完成初始化任务self.brand = brandsuper().__init__(cpu, memory, disk)def print_info(self):# 完成打印当前对象的信息print(f"品牌:{self.brand}\t{self.get_details()}")pc = PC("intel", 32, 1000, "戴尔")
pc.print_info()

输出结果: 

品牌:戴尔	cpu: intel	内存: 32	硬盘: 1000

5. 调用父类成员细节问题

        在Python中,super() 函数是一个内置函数,通常用于调用父类的方法。通过 super() 方法,子类可以直接调用父类中的方法,而不需要显式指定父类的名称。super() 函数通常用在子类中的构造函数中,以便在子类中扩展父类的功能。

如果子类和父类出现同名成员,可以通过父类名或super()访问父类的成员

基本语法
1)访问父类成员方式1
-访问成员变量:父类名,成员变量
-访问成员方法:父类名,成员方法(self)
2)访问父类成员方式2
-访问成员变量: super().成员变量
-访问成员方法:super().成员方法()

代码如下:

class A:n1 = 100def run(self):print("A-run()...")class B(A):n1 = 200def say(self):print(f"父类的n1:{A.n1} 本类的n1:{self.n1}") # 父类的n1:100 本类的n1:200# 调用父类的runA.run(self) # A-run()...# 调用本类的runself.run() # B-run()...def hi(self):print(f"父类的n1 {super().n1}") # 父类的n1 100# 调用父类的runsuper().run() # A-run()...def run(self):print(f"B-run()...")b = B()
b.say()
b.hi()

6、访问不限于直接父类,而是建立从子类向上级父类的查找关系

 重写(override)

        重写又称覆盖(override),指子类定义了与父类同名的属性和方法,从而覆盖了父类中的属性和方法。当子类对象调用这个属性和方法时,将执行子类中的属性和方法,而不是父类中的属性和方法。

class A:n1 = 100def run(self):print(f"A-run...")class B(A):# 重写A类中的n1属性n1 = 10# 重写A类中的run方法def run(self):print(f"B-run...")b = B()
print(b.n1) # 10
b.run() # B-run...

        方法的覆盖允许子类在不改变方法名称的情况下重写父类的方法实现,从而实现特定于子类的行为。在实际开发中,方法的覆盖是面向对象编程中常用的技术,可以根据需要在子类中定制特定的行为。

        需要注意的是,当子类覆盖父类的方法时,建议遵循相同的方法签名(参数列表和返回类型),以确保代码的一致性和易维护性。

例题练习 

●编程题
1)编写一个Person类,包括属性(name、age),构造方法、say方法(返回Person自我介绍的字符串)
2)编写一个Student类,继承Person类,增加属性(id、score),以及构造方法,重写say方法(返回Student自我介绍的信息)
3)分别创建Person和Student对象调用say方法输出自我介绍,体会里与的作用
 

class Person:name = Noneage = Nonedef __init__(self, name, age):self.name = nameself.age = agedef say(self):return f"name:{self.name}\tage:{self.age}"class Student(Person):id = Nonescore = Nonedef __init__(self, id, score, name, age):# 子类的特有的属性,我们自己完成初始化self.id = idself.score = score# 调用父类的构造器完成继承父类的属性的初始化super().__init__(name, age)def say(self):return f"id:{self.id}\tscore:{self.score}\t{super().say()}"person = Person("小白", 20)
student = Student(1, 100, "小黑", 30)print(person.say()) # name:小白	age:20
print(student.say()) # id:1	score:100	name:小黑	age:30

三、多态  

3.1 什么是多态?


        举一个现实中的例子,同样的一件事情,不同的人处理起来,他们的实现过程是完全不同的,会表现出不同的形态。比如:都是吃饭这个事情,中国人表现的是用筷子吃饭,而美国人表现的是用叉刀吃饭。这个就是相同的事情,表现出了不同的“形态”。
(1)多态通常作用在继承的关系上。
(2)多态指的是方法的多态,多态与属性无关。
(3)多态顾名思义是多种状态,不同的对象调用相同的方法,表现出不同的状态,称为多态

先看一个问题
请编写一个程序,Master类中有一个feed(喂食)方法,可以完成主人给动物喂食物的信息

使用传统的方法(不使用多态)来解决上面这个问题,如下所示。

# 不涉及多态
class Food:name = Nonedef __init__(self, name):self.name = nameclass Fish(Food):# 特有的属性和方法passclass Bone(Food):# 特有的属性和方法passclass Animal:name = Nonedef __init__(self, name):self.name = nameclass Dog(Animal):passclass Cat(Animal):passclass Master:name = Nonedef __init__(self, name):self.name = name# 给猫猫喂鱼def feed_cat(self, cat: Cat, fish: Fish):print(f"主人{self.name}给动物{cat.name}喂的食物是{fish.name}")# 给小狗喂骨头def feed_dog(self, dog: Dog, bone: Bone):print(f"主人{self.name}给动物{dog.name}喂的食物是{bone.name}")master = Master("小白")
cat = Cat("小花猫")
fish = Fish("黄花鱼")
dog = Dog("大黄狗")
bone = Bone("大棒骨")master.feed_cat(cat, fish)# 主人小白给动物小花猫喂的食物是黄花鱼master.feed_dog(dog, bone)# 主人小白给动物大黄狗喂的食物是大棒骨

传统方法带来的问题是什么?如何解决?
问题是:代码的复用性不高,而且不利于代码维护和功能拓展
解决方案:使用多态

使用多态


class Animal:def cry(self):passclass Cat(Animal):def cry(self):print("小猫 喵喵叫...")class Dog(Animal):def cry(self):print("小狗 汪汪叫...")class Pig(Animal):def cry(self):print("小猪 哼哼叫...")# 在python面向对象编程中,子类对象可以传递给父类类型
def func(animal: Animal):print(f"animal 类型是{type(animal)}")animal.cry()dog = Dog()
pig = Pig()
cat = Cat()
func(dog) # animal 类型是<class '__main__.Dog'># 小狗 汪汪叫...
func(pig) # animal 类型是<class '__main__.Pig'># 小猪 哼哼叫...
func(cat) # animal 类型是<class '__main__.Cat'># 小猫 喵喵叫...

●多态的好处
1)增加了程序的灵活性,以不变应万变,不论对象千变万化,使用者都是同一种形式去调用,如func(animal),上述代码说明
2)增加了程序的可扩展性,通过继承Animal类创建了一个新的类,使用者无需更改自己的代码,还是用func(animal)去调用
 

使用多态优化主人喂动物问题

# 不涉及多态
class Food:name = Nonedef __init__(self, name):self.name = nameclass Fish(Food):# 特有的属性和方法passclass Bone(Food):# 特有的属性和方法passclass Animal:name = Nonedef __init__(self, name):self.name = nameclass Dog(Animal):passclass Cat(Animal):passclass Master:name = Nonedef __init__(self, name):self.name = name# 给动物喂食物def feed(self, animal: Animal, food: Food):print(f"主人{self.name}给动物{animal.name}喂的食物是{food.name}")master = Master("小白")
cat = Cat("小花猫")
fish = Fish("黄花鱼")
dog = Dog("大黄狗")
bone = Bone("大棒骨")master.feed(cat, fish)# 主人小白给动物小花猫喂的食物是黄花鱼master.feed(dog, bone)# 主人小白给动物大黄狗喂的食物是大棒骨

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

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

相关文章

阻止默认行为 e.preventDefault()搭配passive:false才有效

正确情况 如果想阻止默认行为,那么 e.preventDefault()搭配passive:false才是正解 document.addEventListener(touchmove,(e)>{ e.preventDefault() console.log(123,123);},{passive:false}) 如果搭配 passive:false,则会报警告 e.preventDefault()搭配passive:true会报…

蓝桥杯-礼物-二分查找

题目 思路 --刚开始想到暴力尝试的方法&#xff0c;但是N太大了&#xff0c;第一个测试点都超时。题目中说前k个石头的和还有后k个石头的和要小于s&#xff0c;在这里要能想到开一个数组来求前n个石头的总重&#xff0c;然后求前k个的直接将sum[i]-sum[i-k-1]就行了&#xff0…

软考中高级案例分析通用答题方法

在软考高级信息系统项目管理师和中级系统集成项目管理工程师考试中&#xff0c;案例分析是一个重要的题型。下面分享几种通用答题方法和个人经验&#xff0c;希望能对大家有所帮助。 历年考试中经常考察的内容 首先&#xff0c;范围管理、进度管理、成本管理、质量管理这四大管…

C++ 子序列

目录 最长递增子序列 摆动序列 最长递增子序列的个数 最长数对链 最长定差子序列 最长的斐波那契子序列的长度 最长等差数列 等差数列划分 II - 子序列 最长递增子序列 300. 最长递增子序列 子数组是连续的&#xff0c;子序列可以不连续&#xff0c;那么就要去[0, i - 1]…

【CKA模拟题】掌握Pod日志输出的秘密

题干 For this question, please set this context (In exam, diff cluster name) 对于这个问题&#xff0c;请设置这个上下文(在考试中&#xff0c;diff cluster name) kubectl config use-context kubernetes-adminkubernetes product pod is running. when you access log…

【算法刷题day1】Leetcode:704. 二分查找、27. 移除元素

Leetcode 704&#xff1a;标准二分查找 文档讲解&#xff1a;代码随想录 题目链接&#xff1a;704.二分查找 状态&#xff1a;稳定输出 题目&#xff1a; 给定一个 n 个元素有序的&#xff08;升序&#xff09;整型数组 nums 和一个目标值 target &#xff0c;写一个函数搜索 n…

在Linux环境底下 用C语言执行Python程序

在Linux环境底下 用C语言执行Python程序 文章目录 在Linux环境底下 用C语言执行Python程序1、环境安装&检测2、C语言调用Python语句2.1 直接调用python语句2.2 调用无参python函数2.3 调用有参python函数 1、环境安装&检测 通过C语言调用Python代码&#xff0c;需要先安…

springboot企业级抽奖项目业务二(用户模块)

书接上回&#xff0c;梅开二度 开发流程 该业务基于rouyi生成好了mapper和service的代码&#xff0c;现在需要在controller层写接口 实际操作流程&#xff1a; 看接口文档一>controller里定义函数一>看给出的工具类一>补全controller里的函数一>运行测试 接口…

【数据结构】堆和树详解堆和二叉树的实现堆的top-k问题

主页&#xff1a;醋溜马桶圈-CSDN博客 专栏&#xff1a;数据结构_醋溜马桶圈的博客-CSDN博客 gitee&#xff1a;mnxcc (mnxcc) - Gitee.com 目录 1.树概念及结构 1.1 树的概念 2.2 树的相关概念 1.3 树的表示 1.4 树在实际中的运用 2.二叉树的概念及结构 2.1 二叉树的概念…

vue前端解析jwt

vue前端解析jwt 我们可以用在线解析看解析的结果&#xff1a;https://www.lddgo.net/encrypt/jwt-decrypt 但是如果在前端需要解析token&#xff0c;拿到其中的权限信息&#xff0c;可以这样解决。 在线的&#xff1a; 完美解决&#xff1a; 代码&#xff1a; function par…

MySQL | 表的约束

目录 1. 空属性 NULL 2. 默认值 DEFAULT 3. 列描述comment 4. zerofill 5. 主键 PRIMARY KEY 6. 自增长AUTO_INCREMENT 7. 唯一键UNIQUE 8. 外键 真正约束字段的是数据类型&#xff0c;但是数据类型约束很单一&#xff0c;需要有一些额外的约束&#xff0c;更好的保证数…

web前端常用标签(html)

1.定义 1.1标签 语法规范&#xff1a;<标签名 属性名"属性值">标签名</标签名> 标签之间可以嵌套 1.2属性 定制元素的行为的。属性是不通用的&#xff0c;每一个标签存在自身的属性。当属性名属性值时&#xff0c;可以只写属性值 2.HTML常用标签 2…

面试笔记——Redis(分布式锁的使用场景及实现原理)

分布式锁的使用场景 资源竞争控制&#xff1a;多个客户端同时访问共享资源时&#xff0c;可以使用分布式锁来控制资源的并发访问&#xff0c;防止多个客户端同时对同一资源进行修改造成数据不一致的问题。 避免重复操作&#xff1a;在分布式环境中&#xff0c;可能会出现多个客…

如何实现手机遥控端关机按钮同时关闭TV端和手机端界面

目前家庭电视机主要通过其自带的遥控器进行操控&#xff0c;实现的功能较为单一。例如&#xff0c;当我们要在TV端搜索节目时&#xff0c;电视机在遥控器的操控下往往只能完成一些字母或数字的输入&#xff0c;而无法输入其他复杂的内容。分布式遥控器将手机的输入能力和电视遥…

基于springboot+vue的智慧生活商城系统

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

Pytest自动化测试执行环境切换的两种解决方案(超详细)

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 痛点分析 在实际企业的项目中&#xff0c;自动化测试的代码往往需要在不同的环境中进行切换&am…

【STL基础】vector、stack、queue、list、pair、map、unordered_map、set、unordered_set(详细讲解)

vector、list、pair、unordered_map、unordered_set、stack、queue 参考文章&#xff1a; &#xff08;1&#xff09;【apollo】泛型编程 与 STL &#xff08;2&#xff09;c stack用法 入门必看 超详细 &#xff08;3&#xff09;C中queue的用法&#xff08;超详细&#xff0c…

C语言关于void类型的指针作为函数形参在使用时需要注意的坑

目录 前言 一、void*指针使用时不同编译器下的处理结果 二、void*指针传递的指针变量进行位运算时&#xff0c;一定要注意强制转换的类型&#xff0c;和值的取值范围 总结 前言 众所周知&#xff0c;void* 指针作为函数形参时&#xff0c;表示可以接受任意类型的参数&#xf…

C语言基础知识点(十七)结构体中只用指针来存储字符串

// 如果需要用结构存储字符串&#xff0c;用字符数组作为成员会比较简单 // 如果需要使用指向char的指针来进行存储&#xff0c;那么需要请求malloc来 // 为字符串分配合适的存储空间#include <stdio.h> #include <string.h> //提供strcpy()\strlen()的原型 #i…

基于FFmpeg混流及录制rtmp直播流

1、什么是混流&#xff1f; 混流就是把多路音视频流合成单流。准确的说&#xff0c;混流应该叫做混音&#xff08;音频流&#xff09;混画面&#xff08;视频流&#xff09; 混流的过程包括解码、混流、编码和推流四个部分。混流这个环节包括做抖动缓冲&#xff0c;目的是把多…