面向对象详解,面向对象的三大特征:封装、继承、多态
文章目录
- 一、面向对象与面向过程
- 1、什么是面向过程?
- 2、什么是面向对象?
- 二、类与对象
- 1. 初识对象
- 2. 类的成员方法
- 2.1 类的定义和使用
- 2.2 成员方法
- 3. 类和对象
- 4. 魔法方法
- 1. _ _ inint _ _ 构造方法
- 2. _ _ str _ _ 字符串方法
- 3. _ _ lt _ _ 小于符号比较方法
- 4. _ _ le _ _ 小于等于比较符号方法
- 5. _ _ eq _ _ 相等比较方法
- 三、面向对象的三大特征:封装、继承、多态
- 1. 封装
- 2. 继承
- 3. 多态
- 四、类型注解
- 1. 变量的类型注解
- 2. 基础容器类型注解
- 3. 类对象类型注解
- 4. 函数形参和返回值的类型注解
- 5. Union类型联合类型注解
一、面向对象与面向过程
面向对象编程(Object-Oriented Programming,简称OOP)和面向过程编程(Procedural Programming,简称PP)是两种不同的编程范式。
面向对象编程强调把问题分解成对象,通过封装、继承和多态等机制,来处理对象之间的关系。每个对象都可以独立地处理自己的数据和行为,而不需要依赖其他对象。面向对象编程更加注重代码的重用性、可维护性和可扩展性,适用于大型、复杂的软件系统开发。
而面向过程编程则是一种以过程为中心的编程方式,它将问题分解成一系列的步骤,然后按照顺序执行这些步骤,以达到求解问题的目的。在面向过程编程中,数据和操作是分离的,函数是处理数据的主要手段。面向过程编程更加注重效率和速度,适用于小型、简单的程序或者性能要求较高的场景。
1、什么是面向过程?
面向过程:问题分解成一系列的步骤,然后按照顺序执行这些步骤
举个简单的例子
相信大家都被问过这样一个问题: 把大象装入冰箱需要几步?
按照面向过程的思想:需要三步
第一步:打开冰箱
第二步:把大象塞进去
第三步:关上冰箱
从这里就可以看出:面向过程就是把一件事按步骤一步一步来实现
代码实现:
# 第一步:打开冰箱门
def open_door():print("打开冰箱门")# 第二步:把大象放进去
def put_elephant():print("把大象放进去")# 第三步:关闭冰箱门
def close_door():print("关闭冰箱门")# 完成三个步骤
def put_elephant_in_fridge():open_door()put_elephant()close_door()# 测试程序
put_elephant_in_fridge()
这就是面向过程代码的具体实现啦
2、什么是面向对象?
对象:就是对问题中的事物的抽象
对象可以说是对现实事物的一种抽象映射
。
面向对象:就是把现实中的事物都抽象为“对象”。每个对象是唯一的,且都可以拥有它的属性与行为。我们就可以通过调用这些对象的方法、属性去解决问题。
按照面向对象的思想
在这个例子中:
我们可以把大象看作一个对象,冰箱看作一个对象。
冰箱的一些功能:开门、装物体、关门
class Elephant: # 大象类def Eat(self): # 吃print('吃')class Fridge: # 冰箱类def open_door(self): # 打开冰箱门print('打开冰箱门')def Put_In(self): # 放入东西print('放入东西')def close_door(self): # 关闭冰箱门print('关闭冰箱门')
在面向对象中,每个对象是独立的,有属于它自己的功能,只需要专心实现自己的功能就好。所以在建立对象模型阶段,仅仅关注对象有什么的功能,但不考虑如何实现这些功能。
面向对象对象的特点:有很好的延展性,比如我给大象赋予了一个吃的功能,它通过调用就可以在冰箱里去吃东西。面向对象就是把现实问题抽象为对象,通过调用每个对象的属性或功能去解决问题。
二、类与对象
1. 初识对象
什么是对象?
对象是面向对象编程中的一个概念,它是类的一个实例化(即具体化)的结果。对象是具体的、实际存在的,可以在程序中被创建、操作和销毁。
面向对象编程中,对象是由属性 和方法组成的。属性表示对象的状态和特征,方法表示对象可以执行的操作和行为
。
每个对象都属于某个类,类是对象的抽象,它定义了对象所具有的属性和方法的结构和行为。对象通过实例化类来创建,并且可以根据类的定义进行属性和方法的访问和调用。
以下是一个简单的示例:
class Person:def __init__(self, name, age):self.name = nameself.age = agedef say_hello(self):print(f"Hello, 我叫 {self.name}.")# 创建两个Person对象
person1 = Person("张三", 25)
person2 = Person("李四", 30)# 调用对象的方法
person1.say_hello() # 输出: Hello, 我叫张三.
person2.say_hello() # 输出: Hello, 我叫李四.
通过创建对象,我们可以根据类的定义来操作和管理数据,并执行对象所具有的行为。
2. 类的成员方法
2.1 类的定义和使用
在python中,用关键字class
来定义类
# 定义一个带有成员方法的类
class Student:# 成员变量name = None # 学生的姓名# 定义方法def say_hi1(self):print(f'大家好,我叫{self.name}') # 成员方法中访问成员变量必须要用self关键字!def say_hi2(self, msg):print(f'大家好,我是{self.name},{msg}') # msg为外部传入的不需要用self!stu1 = Student()
stu1.name = '张三'
stu1.say_hi1()
stu2 = Student()
stu2.name = '李四'
stu2.say_hi2('请多多关照')
运行结果:
可以看出,在类中:
- 不仅可以定义属性用来记录数据
- 也可以定义函数,用来记录行为
其中:
- 类中定义的属性(变量),我们称之为:成员变量
- 类中定义的行为(函数),我们称之为:成员方法
2.2 成员方法
语法:
在类中定义成员方法和定义函数基本一致,只存在细微区别:
注意:self关键字是成员方法定义的时候,必须填写的。
- 它用来表示类对象自身的意思
- 当我们使用类对象调用方法的是,self会自动被python传入
- self出现在形参列表中,但是不占用参数位置,无需理会
- 在方法内部,想要访问类的成员变量,必须使用self
例如:
class Student:# 成员变量name = None # 学生的姓名# 定义方法def say_hi(self):print(f'大家好,我叫{self.name}')
class Student:# 成员变量name = None # 学生的姓名def say_hi(self, msg):print(f'大家好,{msg}') # msg为外部传入的不需要用self!stu = Student()
stu.say_hi('请多多关照')
可以看到,在传入参数的时候,没有传入self,但也没有报错。
3. 类和对象
基于类创建对象的语法:
对象名 = 类名称()
为什么非要创建对象才能使用呢?
类只是一种程序内的“设计图纸”或者摸具,需要基于图纸或摸具生产实体(对象),才能正常工作这种套路,称之为:面向对象编程
举一个简单的例子:
类就相当于是闹钟的设计图纸,而对象就相当于按照闹钟的设计图纸所生产出来的闹钟。
从上面可以看出,设计出来的类包含编号和价格,具有响铃的功能。而基于类所创建的对象也有对应的编号和价格
所以面向对象编程就是设计类,基于类创建对象,由对象做具体的工作。
4. 魔法方法
内置的类方法,各自有各自特殊的功能,这些内置方法我们称之为:魔术方法
常见的魔法方法:
魔法方法 | 描述 |
---|---|
_ _ init _ _(self, …) | 初始化方法,用于初始化对象的属性,在对象创建时调用。 |
_ _ str _ _(self) | 将对象转换为字符串的方法,可以通过str(obj)或print(obj)来触发,返回对象的可读性好的字符串表示。 |
_ _ repr _ _(self) | 将对象转换为供解释器读取的形式的字符串,通常用于调试和开发,可以通过repr(obj)来触发。 |
_ _ len _ _(self) | 返回对象的长度,可以通过len(obj)来调用。 |
_ _ getitem _ _(self, key) | 获取对象的索引值,用于支持索引操作,如obj[key]。 |
_ _ setitem _ _(self, key, value) | 设置对象的索引值,用于支持赋值操作,如obj[key] = value。 |
_ _ delitem _ _(self, key) | 删除对象的索引值,用于支持删除操作,如del obj[key]。 |
_ _ iter _ _(self) | 返回一个迭代器,用于支持对象的迭代功能,如在for循环中使用。 |
_ _ next _ _(self) | 用于迭代器,返回迭代对象的下一个元素。 |
_ _ eq _ _(self, other) | 定义对象相等的比较方式,通常用于==操作符的比较。 |
_ _ lt _ _(self, other) | 定义对象小于的比较方式,通常用于<操作符的比较。 |
_ _ add _ _(self, other) | 定义对象相加的方式,通常用于+操作符的运算。 |
_ _ sub _ _(self, other) | 定义对象相减的方式,通常用于-操作符的运算。 |
_ _ mul _ _(self, other) | 定义对象相乘的方式,通常用于*操作符的运算。 |
_ _ div _ _(self, other) | 定义对象相除的方式,通常用于/操作符的运算。 |
上述表格因为语法限制,把下面的下划线之间都空了一格,实际上两条下划线之间并没有空格!
常见的魔法方法
1. _ _ inint _ _ 构造方法
class Student:name = None # 姓名age = None # 年龄tel = None # 手机号stu1 = Student()
stu1.name = '张三'
stu1.age = 18
stu1.tel = "1686400001"
stu2 = Student()
stu2.name = '李四'
stu2.age = 19
stu2.tel = "163200002"
上面代码中,为对象的属性赋值需要依次进行,略显繁琐。可不可以像函数传参那样直接一次性对属性进行赋值呢?
答案是肯定的,需要使用构造方法:_ _ init _ _()
Python类可以使用:_ _ init _ _() 方法,称之为构造方法。
可以实现:
- 在创建类对象(构造类)的时候,会自动执行。
- 在创建类对象(构造类)的时候,将传入参数自动传递给__init__方法使用。
class Student:# 成员对象"""__init__构造方法里对成员变量进行了声明并赋值所以成员对象这里可省略"""name = Noneage = Nonetel = Nonedef __init__(self, name, age, tel):self.name = nameself.age = ageself.tel = telprint('Student类创建了一个类对象') # 输出:Student类创建了一个类对象stu1 = Student('张三', '18', '13066660')
print(stu1.name) # 输出:张三
print(stu1.age) # 输出:18
print(stu1.tel) # 输出:13066660
注意:
在构造方法内定义成员变量,需要使用self关键字
这是因为:变量是定义在构造方法内部,如果要成为成员变量,需要用self来表示。
2. _ _ str _ _ 字符串方法
- 方法名:_ _ str _ _
- 返回值:字符串
- 内容:自行定义
class Student:def __init__(self, name, age):self.name = nameself.age = agestu1 = Student('张三', 18)
print(stu1) # 输出:<__main__.Student object at 0x000001EDFFB09FD0>
print(str(stu1)) # 输出:<__main__.Student object at 0x000001EDFFB09FD0>
当类对象需要被转换为字符串之时,会输出如上结果(内存地址)
内存地址没有多大作用,我们可以通过 _ _ str _ _ 方法,控制类转换为字符串的行为。
class Student:def __init__(self, name, age):self.name = nameself.age = agedef __str__(self):return f'name:{self.name}, age:{self.age}'stu1 = Student('张三', 18)
print(stu1) # 输出:name:张三, age:18
print(str(stu1)) # 输出:name:张三, age:18
3. _ _ lt _ _ 小于符号比较方法
- 方法名:_ _ lt _ _
- 传入参数:other,另一个类对象
- 返回值:True 或 False
- 内容:自行定义
class Student:def __init__(self, name, age):self.name = nameself.age = agestu1 = Student('张三', 18)
stu2 = Student('李四', 19)
print(stu1 < stu2)
print(stu1 > stu2)
像这样直接对2个对象进行比较是不可以的
在类中实现 _ _ lt _ _ 方法,可同时完成:小于符号和大于符号2种比较。
- 方法名:_ _ lt _ _
- 传入参数:other,另一个类对象
- 返回值:True 或 False
- 内容:自行定义
class Student:def __init__(self, name, age):self.name = nameself.age = age# __lt__魔法方法: 两个类对象进行大于或小于的比较def __lt__(self, other):return self.age < other.agestu1 = Student('张三', 18)
stu2 = Student('李四', 19)
print(stu1 < stu2) # 输出:True
print(stu1 > stu2) # 输出:False
比较大于符号的魔术方法是:_ _ gt _ _, 方法和 _ _ lt _ _ 一样,所以实现了 _ _ lt _ _ ,_ _gt _ _ 就没必要实现了。
4. _ _ le _ _ 小于等于比较符号方法
这个和 _ _ lt _ _ 一样,唯一不同的是 _ _ lt _ _ 是比较大于或小于,而 _ _ le _ _ 则是比较大于等于和小于等于。
- 方法名:_ _ le _ _
- 传入参数:other,另一个类对象
- 返回值:True 或 False
- 内容:自行定义
class Student:def __init__(self, name, age):self.name = nameself.age = age# __lt__魔法方法: 两个类对象进行大于或小于的比较def __lt__(self, other):return self.age < other.agestu1 = Student('张三', 18)
stu2 = Student('李四', 19)
print(stu1 <= stu2)
print(stu1 >= stu2)
class Student:def __init__(self, name, age):self.name = nameself.age = age# __lt__魔法方法: 两个类对象进行大于或小于的比较def __lt__(self, other):return self.age < other.age# __le__魔法方法: 两个类对象进行大于等于或小于等于的比较def __le__(self, other):return self.age <= other.agestu1 = Student('张三', 18)
stu2 = Student('李四', 19)
print(stu1 <= stu2) # 输出:True
print(stu1 >= stu2) # 输出:False
5. _ _ eq _ _ 相等比较方法
- 方法名:eq
- 传入参数:other,另一个类对象
- 返回值:True 或 False
- 内容:自行定义
class Student:def __init__(self, name, age):self.name = nameself.age = age
stu1 = Student('张三', 18)
stu2 = Student('李四', 19)
print(stu1 == stu2) # 输出:False
不实现 _ _ eq _ _ 方法,对象之间也可以进行比较,但是是比较内存地址,也即是:不同对象==比较一定是False结果。
class Student:def __init__(self, name, age):self.name = nameself.age = age# __eq__魔法方法: 两个类对象进行相等的比较def __eq__(self, other):return self.age == other.age
stu1 = Student('张三', 18)
stu2 = Student('李四', 18)
print(stu1 == stu2) # 输出:True
实现了 _ _ eq _ _ 方法,就可以按照自己的想法来决定2个对象是否相等了。
三、面向对象的三大特征:封装、继承、多态
1. 封装
封装(Encapsulation):将数据和操作封装在对象中,使其成为一个独立的实体,外界只能通过对象提供的接口访问和操作内部数据。
对用户隐藏的属性和行为
现实世界中的事物,有属性和行为。但是不代表这些属性和行为都是开放给用户使用的。
私有成员
既然现实事物有不公开的属性和行为,那么作为现实事物在程序中映射的类,也应该支持。
类中提供了私有成员的形式来支持。
- 私有成员变量
- 私有成员方法
定义私有成员的方式非常简单,只需要:
- 私有成员变量:变量名以__开头(2个下划线)
- 私有成员方法:方法名以__开头(2个下划线)
class Phone:IMEI = None # 序列号producer = None # 厂商# 私有成员变量__current_voltage = None # 当前电压def call_by_5g(self):print('5g通话已开启')# 私有成员方法def __keep_5g(self):print('保持5g')
私有方法无法直接被类对象使用
phone = Phone()
phone.__keep_5g()
使用私有成员
class Phone:# 构造方法def __init__(self, __is_5g_enable):# 设置私有变量self.__is_5g_enable = __is_5g_enable# 设置私有方法def __check_5g(self):if self.__is_5g_enable == True: # 类内部访问私有成员要用selfprint('5G开启')else:print('5G关闭,使用4G网络')def call_by_5g(self):self.__check_5g()print('正在通话中...')phone = Phone(False)
phone.call_by_5g()
2. 继承
继承(Inheritance):继承允许一个类(子类)继承另一个类(父类)的属性和方法,子类可以重用父类的代码,并且可以在不修改原有代码的情况下进行扩展和修改。
简单来说就是一个类,继承另外一个类的成员变量和成员方法
举个简单的例子:
手机的更新换代并不是完完全全重新开始,而是在原先的基础上新添一些属性和功能。
类比到程序中,我们也可以在已经设计好的类上进行更新和修改,这就会用到继承。
继承分为:单继承和多继承
单继承语法:
class 类名(父类):类内容体
# 单继承演示
# 定义父类
class Phone:IMEI = None # 序列号producer = 'APPLE' # 厂商def call_by_4g(self):print('4g通话')# 定义子类
class Phone2022(Phone):face_id = '10001'def call_by_5g(self):print('5g通话')phone = Phone2022()
phone.call_by_4g() # 输出:4g通话
print(phone.producer) # 输出:APPLE
phone.call_by_5g() # 输出:5g通话
print(phone.face_id) # 输出:10001
通过继承可以将从父类那里继承(复制)来成员变量和成员方法(不含私有)给子类使用。
多继承语法
Python的类之间也支持多继承,即一个类,可以继承多个父类
class 类名(父类1, 父类2, 父类3, ... , 父类N):类内容体
举例:
# 多继承演示
# 定义父类
class Phone:IMEI = None # 序列号producer = 'HM' # 厂商def call_by_4g(self):print('4g通话')class NFCReader:nfc_type = '第五代'producer = 'HM'def read_card(self):print('读取NFC卡')def write_card(self):print('写入NFC卡')class RemoteControl:rc_type = '红外遥控'def control(self):print('红外遥控开启')# 定义子类
class MyPhone(Phone, NFCReader, RemoteControl):passphone = MyPhone()
print(phone.producer) # 输出:HM
print(phone.nfc_type) # 输出:第五代
phone.read_card() # 输出:读取NFC卡
phone.call_by_4g() # 输出:4g通话
phone.control() # 输出:红外遥控开启
多继承注意事项:多个父类中,如果有同名的成员,那么**默认以继承顺序(从左到右)**为优先级。即:先继承的保留,后继承的被覆盖。
pass语句
pass是占位语句,用来保证函数(方法)或类定义的完整性,表示无内容,空的意思。
复写
子类继承父类的成员属性和成员方法后,如果对其“不满意”,那么可以进行复写。
即:在子类中重新定义同名的属性或方法即可。
# 定义父类
class Phone:IMEI = None # 序列号producer = 'APPLE' # 厂商def call_by_4g(self):print('4g通话')# 定义子类
class MyPhone(Phone):producer = 'HUAWEI' # 复写父类属性def call_by_4g(self): # 复写父类方法print('可用5g通话')phone = MyPhone()
print(phone.producer) # 输出:HUAWEI
phone.call_by_4g() # 输出:可用5g通话
调用父类同名成员
一旦复写父类成员,那么类对象调用成员的时候,就会调用复写后的新成员
如果需要使用被复写的父类的成员,需要特殊的调用方式:
方式一:
- 调用父类成员
使用成员变量:父类名.成员变量
使用成员方法:父类名.成员方法(self)
方式二:
- 使用super()调用父类成员
使用成员变量:super().成员变量
使用成员方法:super().成员方法()
注意:只能在子类内调用父类的同名成员。子类的类对象直接调用会调用子类复写的成员
# 定义父类
class Phone:IMEI = None # 序列号producer = 'APPLE' # 厂商def call_by_4g(self):print('4g通话')# 定义子类
class MyPhone(Phone):producer = 'HUAWEI' # 复写父类属性def call_by_4g(self): # 复写父类方法print('可用5g通话')# 调用父类属性和方法# 方法一# print(f'调用父类属性[1]:{Phone.producer}') # 调用父类属性# Phone.call_by_4g(self) # 调用父类方法# 方法二print(f'调用父类属性[2]:{super().producer}') # 调用父类属性super().call_by_4g() # 调用父类方法phone = MyPhone()
print(phone.producer)
phone.call_by_4g()
3. 多态
多态(Polymorphism):多态使得对象可以根据上下文表现出不同的行为,同一个方法可以在不同对象上有不同的实现。这样可以提高代码的灵活性和可复用性。
也就是说:多种状态,即完成某个行为时,使用不同的对象会得到不同的状态。
如何理解?
同样的行为(函数),传入不同的对象,得到不同的状态
多态常作用在继承关系上。
比如
- 函数(方法)形参声明接收父类对象
- 实际传入父类的子类对象进行工作
即:
- 以父类做定义声明
- 以子类做实际工作
- 用以获得同一行为, 不同状态
抽象类(接口)
抽象类:含有抽象方法的类称之为抽象类
抽象方法:方法体是空实现的(pass) 称之为抽象方法
举例:
# 抽象类
# 定义父类
class AC:def cool_wind(self):"""制冷"""passdef hot_wind(self):"""制热"""passdef swing_l_r(self):"""左右摆风"""passclass Midea_AC(AC):def cool_wind(self):print('美的空调制冷')def hot_wind(self):print('美的空调制热')def swing_l_r(self):print('美的空调左右摆风')class GREE_AC(AC):def cool_wind(self):print('格力空调制冷')def hot_wind(self):print('格力空调制热')def swing_l_r(self):print('格力空调左右摆风')def cool_wind(ac: AC):ac.cool_wind()# 创建对象
midea = Midea_AC()
gree = GREE_AC()
cool_wind(midea) # 输出:美的空调制冷
cool_wind(gree) # 输出:格力空调制冷
四、类型注解
在PyCharm中编写代码,我们经常能够见到如下提示:
为什么PyCharm工具能够做到这一点?
因为:PyCharm确定这个对象,是list类型
同样,我们换一份代码:定义一个函数func,接收一个参数data,你会发现,PyCharm不会在做出任何提示了
为什么PyCharm工具无法提示了?
这是因为PyCharm不确定这个对象是什么类型
PyCharm无法通过代码确定应传入什么类型,我们需要使用类型注解
1. 变量的类型注解
基础语法: 变量: 类型
为变量设置注解,显示的变量定义,一般无需注解
# 变量的类型注
var1: int = 10
var2: str = '张三'
var3: bool = True
像上面这样:就算不写注解,也明确的知晓变量的类型
2. 基础容器类型注解
# 基础容器类型注解
my_list: list = [1, 2, 3]
my_tuple: tuple = (1, 2, 3)
my_dict: dict = {"name": "张三"}# 容器类型详细注解
my_list1: list[int] = [1, 2, 3]
my_tuple1: tuple[int, str, bool] = (1, "张三", True)
my_dict1: dict[str, str] = {"name": "张三"}
注意:
- 元组类型设置类型详细注解,需要将每一个元素都标记出来
- 字典类型设置类型详细注解,需要2个类型,第一个是key第二个是value
3. 类对象类型注解
# 类对象类型注解
class Student:passstu: Student = Student()
4. 函数形参和返回值的类型注解
函数和方法的形参类型注解语法:
def 函数名(形参1: 类型, 形参2: 类型, ..., 形参n: 类型):pass
# 函数形参的类型注解
def add(x: int, y: int):return x + y
返回值注解
语法:
def 函数名(形参1: 类型, 形参2: 类型, ..., 形参n: 类型) -> 返回值类型:pass
# 函数形参和返回值的类型注解
def fnuc(data: list) -> list:return data
除了使用 变量: 类型, 这种语法做注解外,也可以在注释中进行类型注解。
语法:# type: 类型
# 在注释中进行类型注解
var_1: random.randint(1, 10) # type: int
var_2: json.loads('{"name": "张三"}') # type: dict
5. Union类型联合类型注解
Union 类型用于指定一个变量可以是多种类型中的一种。
Union联合类型注解,在变量注解、函数(方法)形参和返回值注解中,均可使用。
Union的使用方式
导包:from typing import Union
语法:Union[类型, …, 类型]
# 使用Union类型,必须先导包
from typing import Unionmy_list: list[Union[int, str, dict]] = [1, 2, 'name', {"age": 18}]
my_dict: dict[str, Union[int, str, list]] = {"name": "张三", "age": 18, "grade": [98, 97]}
my_list1: list[Union[int, str, dict[Union[str, int]]]] = [1, 2, 'name', {"age": 18}]# 函数的Union类型
def func(data: Union[int, str]) -> Union[int, str]:return data
相关文章:

面向对象详解,面向对象的三大特征:封装、继承、多态
文章目录 一、面向对象与面向过程1、什么是面向过程?2、什么是面向对象? 二、类与对象1. 初识对象2. 类的成员方法2.1 类的定义和使用2.2 成员方法 3. 类和对象4. 魔法方法1. _ _ inint _ _ 构造方法2. _ _ str _ _ 字符串方法3. _ _ lt _ _ 小于符号比较…...

【阿里云服务器的一些使用坑】都是无知的泪水呀
发生了什么? 我想学习一下关于Java的MySQL、Nginx 相关的知识。然后就用首次优惠注册的阿里云,都没有搞清楚实例,镜像,带宽,磁盘。然后。因为一不小心——我想去换一个Ubuntu的镜像而不是CentOS。就把实例给释放啊。之…...

Docker的常用命令||Docker是个流行的容器化平台,它允许你打包、分发和运行应用程序。
Docker是一个流行的容器化平台,它允许你打包、分发和运行应用程序。以下是一些常用的Docker命令及其示例用法: 1. **docker run**: 用于运行一个新的容器实例。 docker run <image_name> 例如,运行一个Nginx容器: docker ru…...

汽车电子论文学习--电动汽车电机驱动系统动力学特性分析
关键重点: 1. 汽车的低速转矩存在最大限制,受附着力限制,因路面不同而变化。 2. 起步加速至规定转速的时间可以计算得到: 3. 电机额定功率的计算方式: 可以采取最高设计车速90%或120km/h匀速行驶的功率作为电机额定功…...

c++的一些陌生用法记录
c的一些陌生用法记录 1. 完美转发std::forward<decltype(PH1)>(PH1)static的用法 1. 完美转发std::forward<decltype(PH1)>(PH1) static的用法 static函数与普通函数的区别: 用static修饰的函数,本限定在本源码文件中,不能被本源…...

Vue | (三)使用Vue脚手架(中)| 尚硅谷Vue2.0+Vue3.0全套教程
文章目录 📚Todo-list 案例🐇组件化编码流程(通用)🐇实现静态组件🐇展示动态数据🐇交互⭐️添加一个todo⭐️todo勾选实现⭐️删除功能实现⭐️底部统计功能实现⭐️底部全选功能实现⭐️底部一…...

TenorFlow多层感知机识别手写体
文章目录 数据准备建立模型建立输入层 x建立隐藏层h1建立隐藏层h2建立输出层 定义训练方式建立训练数据label真实值 placeholder定义loss function选择optimizer 定义评估模型的准确率计算每一项数据是否正确预测将计算预测正确结果,加总平均 开始训练画出误差执行结…...

Java基础(二十六):Java8 Stream流及Optional类
Java基础系列文章 Java基础(一):语言概述 Java基础(二):原码、反码、补码及进制之间的运算 Java基础(三):数据类型与进制 Java基础(四):逻辑运算符和位运算符 Java基础(五):流程控制语句 Java基础(六)࿱…...

qt - 19种精美软件样式
qt - 19种精美软件样式 一、效果演示二、核心程序三、下载链接 一、效果演示 二、核心程序 #include "mainwindow.h"#include <QtAdvancedStylesheet.h> #include <QmlStyleUrlInterceptor.h>#include "ui_mainwindow.h" #include <QDir&g…...

vue 使用docx库生成word表格文档
在Vue.js中生成Word表格文档,可以通过前端库来实现。这些库可以帮助我们轻松地将HTML表格转换为Word文档(通常是.docx格式)。以下是一些流行的前端库,它们可以用于在Vue项目中生成Word表格文档: docx…...

ElementUI table表格组件实现双击编辑单元格失去焦点还原,支持多单元格
在使用ElementUI table表格组件时有时需要双击单元格显示编辑状态,失去焦点时还原表格显示。 实现思路: 在数据中增加isFocus:false.控制是否显示在table中用cell-dblclick双击方法 先看效果: 上源码:在表格模板中用scope.row…...

Java基于SpringBoot+Vue的图书管理系统
博主介绍:✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇…...

【云安全】Hypervisor与虚拟机
Hypervisor 也被称为虚拟机监视器(Virtual Machine Monitor,VMM),主要作用是让多个操作系统可以在同一台物理机上运行。 Type-1 Hypervisor 与 Typer-2 Hypervisor Type-1 Hypervisor 直接安装在物理服务器上,不依赖…...

JS文本加密方法探究
在前端开发中,有时候我们需要对敏感文本进行简单的加密,以提高安全性。本文将介绍一种基于 JavaScript 实现的文本加密方法,使用了 Base64、Unicode 和 ROT13 编码。 示例代码 function encodeText(text) {// Base64编码var base64Encoded …...

推荐彩虹知识付费商城免授权7.0源码
彩虹知识付费商城免授权7.0源码,最低配置环境 PHP7.2 1、上传源码到网站根目录,导入数据库文件:xydai.sql 2、修改数据库配置文件:/config.php 3、后台:/admin 账号:admin 密码:123456 4、前…...

【天衍系列 04】深入理解Flink的ElasticsearchSink组件:实时数据流如何无缝地流向Elasticsearch
文章目录 01 Elasticsearch Sink 基础概念02 Elasticsearch Sink 工作原理03 Elasticsearch Sink 核心组件04 Elasticsearch Sink 配置参数05 Elasticsearch Sink 依赖管理06 Elasticsearch Sink 初阶实战07 Elasticsearch Sink 进阶实战7.1 包结构 & 项目配置项目配置appl…...

一、ActiveMQ介绍
ActiveMQ介绍 一、JMS1.jms介绍2.jms消息传递模式3.JMS编码总体架构 二、消息中间件三、ActiveMQ介绍1.引入的原因1.1 原因1.2 遇到的问题1.3 解决思路 2.定义3.特点3.1 异步处理3.2 应用系统之间解耦3.3 实际-整体架构 4.作用 一、JMS 1.jms介绍 jms是java消息服务接口规范&…...

【牛客】寒假训练营1 I-It‘s bertrand paradox. Again! 题解
传送门:It’s bertrand paradox. Again! 标签:随机 题目大意 有两个人分别用两种方式在二维平面上随机生成1e5个圆,每个圆上的每一个点(x,y)都满足-100<x<100且-100<y<100,现在将某个人生成的1e5个圆的圆心和半径告…...

各种手型都合适,功能高度可定制,雷柏VT9PRO mini和VT9PRO游戏鼠标上手
去年雷柏推出了一系列支持4KHz回报率的鼠标,有着非常敏捷的反应速度,在游戏中操作体验十分出色。尤其是这系列4K鼠标不仅型号丰富,而且对玩家的操作习惯、手型适应也很好,像是VT9系列就主打轻巧,还有专门针对小手用户的…...

sql建库,建表基础操作
当涉及到SQL建库和建表操作时,以下是一个简单的示例: 1. 建库(创建数据库) sql复制代码 CREATE DATABASE mydatabase; 上述语句将创建一个名为mydatabase的数据库。 2. 选择数据库 在创建表之前,需要选择要在其中…...

算法训练营day32,贪心算法6
import "strconv" //738. 单调递增的数字 func monotoneIncreasingDigits(n int) int { str : strconv.Itoa(n) nums : []byte(str) length : len(nums) if length < 1 { return n } for i : length - 1; i > 0; i-- { //如果前一个数字比当前值大࿰…...

CTR之行为序列建模用户兴趣:DIN
在前面的文章中,已经介绍了很多关于推荐系统中CTR预估的相关技术,今天这篇文章也是延续这个主题。但不同的,重点是关于用户行为序列建模,阿里出品。 概要 论文:Deep Interest Network for Click-Through Rate Predict…...

Java使用Redis实现分页功能
分页功能实现应该是比较常见的,对于redis来说,近期刷题就发现了lrange、zrange这些指令,这个指令怎么使用呢? 我们接下来就来讲解下。 目录 指令简介lrangezrange Java实现Redis实现分页功能 指令简介 lrange lrange 是 Redis 中…...

Qt标准对话框设置
Qt标准对话框设置,设置字体、调色板、进度条等。 #include "mainwindow.h" #include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow) {ui->setupUi(this); }MainWindow::~MainWi…...

如何让Obsidian实现电脑端和安卓端同步
Obsidian是一款知名的笔记软件,支持Markdown语法,它允许用户在多个设备之间同步文件。要在安卓设备上实现同步,可以使用remote save插件,以下是具体操作步骤: 首先是安装电脑端的obsidian,然后依次下载obs…...

windows系统中jenkins构建报错提示“拒绝访问”
一.背景 之前徒弟在windows中安装的jenkins,运行的时候用的是java -jar jenkins.war来运行的。服务器只有1个盘符C盘。今天说构建错误了,问我修改了啥,我年前是修改过构建思路的。 二.问题分析 先看jenkins构建任务的日志,大概是xcopy命令执…...

服务器防火墙的应用技术有哪些?
随着互联网的发展,网络安全问题更加严峻。服务器防火墙技术作为一种基础的网络安全技术,对于保障我们的网络安全至关重要。本文将介绍服务器防火墙的概念和作用,以及主要的服务器防火墙技术,包括数据包过滤、状态检测、代理服务、…...

力扣:40. 组合总和 II
回溯: 1.先声明好大集合和小集合,在调用回溯函数,终止条件为sumtarget,要进行剪枝操作减少遍历的次数,去重操作防止数组中有两个相同的值来组成的集合相同。 class Solution {List<List<Integer>> li1ne…...

Java设计模式——责任链模式
当一个请求需要在多个对象之间传递,每个对象都可能处理该请求或将其传递给下一个对象。在这种情况下,需要避免将发送者与接收者之间的耦合,以及确定请求的处理方式。此时可使用责任链模式,它的优点有降低耦合度(无需关…...

c++面试
c基础 面试题 1:变量的声明和定义有什么区别 1.定义:为变量分配地址和存储空间,声明:不分配地址。 2.一个变量可以在多个地方声明,但是只在一个地方定义。 3.加入 extern 修饰的是变量的声明,说明此变量将在文件以外或在文件后…...