python中的类与对象(2)

目录

一. 类的基本语法

二. 类属性的应用场景

三. 类与类之间的依赖关系

(1)依赖关系

(2)关联关系

(3)组合关系

四. 类的继承


一. 类的基本语法

先看一段最简单的代码:

class Dog():d_type = "二哈"  # 属性,类属性,类变量def say_hi(self):  # 在类里面的函数称为方法,第一个参数必须是self,代表实例本身print("hello,i am a dog,my type is",self.d_type)dog1 = Dog()  # 生成了一个实例
dog1.say_hi()  # 实例.方法
# hello,i am a dog,my name is 二哈
print(dog1.d_type)  # 实例.属性
# 二哈

这段代码定义了一个名为Dog的类,其中有一个类属性d_type设置为"二哈",以及一个实例方法say_hi用于打印一句话。然后创建了一个名为dog1的实例,并调用了say_hi方法和打印了实例属性d_type的值。

这里d_type是Dog类的属性(类属性/类变量/公共属性),从Dog类生成的对象都自带这个属性,如果我们想要定义每条狗的实例属性/实例变量/成员变量,如姓名,年龄,主人信息等,则使用__init__方法定义私有属性。我们并没有调用__init__(self,xxxx),但它会自动执行。因为它叫初始化函数,就是在实例化的时候,用来初始化一些数据的,比如初始化实例的名字、年龄等私有属性。

这些写在__init__(self,xxxx)里name,age等实例变量,跟公共属性d_type有什么区别呢?换句话说私有属性和共有属性有什么区别?区别就是,d_type是存在Dog类自己的内存里,self.name,self.age是存在每个实例自己的内存里。

class Dog():d_type = "二哈"def __init__(self, name, age):  # __init__函数称为初始化方法,构造方法,构造函数,在创建对象时自动调用# 第一个参数必须是self,代表实例本身# 要想把私有属性name, age真正的存到实例里,就要把2个值和实例绑定self.name = name  # 绑定__init__参数值到对象self.age = agedef say_hi(self):  # 第一个参数必须是selfprint("hello,i am a dog,my name is",self.name)dog1 = Dog("zhaopeng",4)  # 实例化对象,相当于__init__(dog1, "zhaopeng", 4)
dog1.say_hi()  # 相当于类中say_hi(dog1)
print(dog1.name, dog1.d_type)  # 打印对象的公共属性和私有属性
print(id(dog1.d_type), id(Dog.d_type))  # 公共属性,对象和类共享内存
dog1.name = "zhangsan"
dog1.d_type = "藏獒"
print(dog1.name, dog1.d_type)  # 对象属性可以在类外重写

这里需要重点搞明白self什么意思,我们先搞明白实例化的过程:

step 1,d=Dog("毛毛",2,"Alex"),会申请一会内存空间,指向变量名d

step 2,__init__这个初始化方法需要把接收到参数存下来, 存到这个d的内存空间里

step 3,传给初始化方法里的name,age想绑定到d的空间里,怎么存呢?就得把d的内存空间传到这个方法里,所以self就是用来接收d的地址的。d=Dog(“毛毛”,2,"AIex”)相当于Dog(d,"毛毛",2,"Aex”),那self.name=name 也就相当于d.name =name。我们在实例时没有手动传递d到Dog类里,只写了d=Dog(“毛毛”,2,"Alex”),是Python解释器帮你自动干了这个事。

到此,我们终于明白,原来self就是代表实例本身。实例化时python会自动把这个实例本身通过self参数传进去。接下来看第二个方法:

def say_hi(self):  # 第一个参数必须是selfprint("hello,i am a dog,my name is",self.name)

这里为何也要加入self参数?那是因为,你自己也看到了, 这个类的方法其实就是函数。函数被一个实例调用时,它需要知道是谁在调用它?函数内部要用到一些实例的属性的时候去哪里取呢?比如在say_hi函数里怎么取到d.name,d.age?只能你先传递给它。所以这就是为何类下的每个方法第一个参数都要是self,因为为了接收实例这个对象本身

*注意:self在实例化时自动将对象/实例本身传给__init__的第一个参数,你也可以给他起个别的名字,但是正常人都不会这么做,因为你瞎改别人就不认识。

二. 类属性的应用场景

仍然是通过一段代码说明如何调用和修改类属性,实例属性:

class People():nationality = "CN"  # nationality是公共属性def __init__(self, name, age, sex):  # name, age, sex是私有属性self.name = nameself.age = ageself.sex = sex
# 实例化
p1 = People("zhangsan",31,"M")
p2 = People("lisi",25,"M")
p3 = People("wangwu",21,"F")
# 调用公共属性
print(People.nationality)
print(p2.nationality)
# 调用实例属性
print(p1.age)  # 实例属性不能在类中调用,只能在实例中调用
print(People.age)  # AttributeError: type object 'People' has no attribute 'age'
# 修改私有属性
p1.age = 22  # 修改私有属性
print(p1.age)
# 修改公共属性
p1.nationality = "TW"  # 修改公共属性
print(p1.nationality)  # TW
print(p2.nationality,People.nationality)  # CN CN
# 修改p1的公共属性不改变People类,实际上是因为p1.nationality = "TW" 这句相当于为p1增加了实例属性nationality

搞懂了这个我们就可以重写上一节的引子,利用类方法来写:

class Dog():life_val = 100def __init__(self, name, d_type, attack_val):self.name = nameself.d_type = d_typeself.attack_val = attack_valdef bite(self, person):person.life_val -= self.attack_valprint("狗[%s]咬了[%s]一口,人掉血[%s],剩余血量[%s]"%(self.name, person.name, self.attack_val, person.life_val))class Person():life_val = 100def __init__(self, name, age, attack_val):self.name = nameself.age = ageself.attack_val = attack_valdef beat(self, dog):dog.life_val -= self.attack_valprint("人[%s]打了狗[%s]一棒,狗掉血[%s],剩余血量[%s]"%(self.name, dog.name, self.attack_val, dog.life_val))dog1 = Dog("FWE", "二哈", 10)
person1 = Person("zhaopeng", 25, 30)
dog1.bite(person1)
# 狗[FWE]咬了[zhaopeng]一口,人掉血[10],剩余血量[90]
person1.beat(dog1)
# 人[zhaopeng]打了狗[FWE]一棒,狗掉血[30],剩余血量[70]

三. 类与类之间的依赖关系

大千世界,万物之间皆有规则和规律。类和对象是对大千世界中的所有事物进行归类,事物之间存在着相对应的关系,类与类之间也同样如此。类与类中存在以下关系:

  • 依赖关系,狗和主人的关系。
  • 关联关系,你和你的女友之间的关系就是关联关系。
  • 聚合关系,电脑的各部件组戒完整的电脑,电脑里有CPU,硬盘,内存等。每个组件有自己的生命周期,电脑挂了,CPU还是好的,还是完整的个体。
  • 组合关系,比聚合还要紧密。比如人的大脑,心脏,各个器官,这些器官组合成一个人。这时人如果挂了,其他的东西也跟着挂。
  • 继承关系,类的三大特性之一,子承父业。
(1)依赖关系
class Dog():life_val = 100def __init__(self, name, d_type, attack_val, master):self.name = nameself.d_type = d_typeself.attack_val = attack_valself.master = master  # 人作为一个对象,和狗产生依赖关系self.say_hi()def say_hi(self):print("Hello, i am a dog, my name is [%s], and my master is [%s]"%(self.name, self.master.name))class Person():life_val = 100def __init__(self, name, age, attack_val):self.name = nameself.age = ageself.attack_val = attack_valdef beat(self, dog):dog.life_val -= self.attack_valprint("人[%s]打了狗[%s]一棒,狗掉血[%s],剩余血量[%s]"%(self.name, dog.name, self.attack_val, dog.life_val))person1 = Person("zhaopeng", 25, 30)
dog1 = Dog("FWE", "二哈", 10, person1)
(2)关联关系

构造男生和女生谈恋爱的关联:如果直接加一个partner实例属性:

class Person():def __init__(self, name, age, sex, partner):self.name = nameself.age = ageself.sex = sexself.partner = partnerperson1 = Person("zhaopeng", 25, "M", person2)  # NameError: name 'person2' is not defined.
person2 = Person("wangwu", 25, "F", person1)

因为实例化person1时,需要向里传person2,而此时person2还没创建出来,所以此时会报NameError。我们可以先把self.partner初始为None,然后再建立联系:

class Person():def __init__(self, name, age, sex):self.name = nameself.age = ageself.sex = sexself.partner = Noneperson1 = Person("zhaopeng", 25, "M")  
person2 = Person("wangwu", 25, "F")
person1.partner = person2  # 建立联系
person2.partner = person1
print(person1.partner.name,person2.partner.name)  # wangwu zhaopeng

这似乎解决了问题,但是:男生和女生的恋爱关系是一个双向的过程,这种写法我们必须同时写两句,来建立或者删除联系。如何只用一条指令就同时建立和删除双方之间的联系?一种思路是,单独写一个类relationship专门处理,存储2个人的关系状态,2个人在查自己的感情状态时,都到这个单独的实例里来查:

class Relationship():def __init__(self):self.relationship = []  # 生成空列表def make_couple(self, p1, p2):  # 建立恋爱关系self.relationship = [p1, p2]print("[%s]和[%s]确定了恋爱关系"%(p1.name, p2.name))class Person():def __init__(self, name, age, sex):self.name = nameself.age = ageself.sex = sexperson1 = Person("zhaopeng", 25, "M")  
person2 = Person("wangwu", 25, "F")
relationship = Relationship()
relationship.make_couple(person1, person2)
# [zhaopeng]和[wangwu]确定了恋爱关系

现在我们再做一点改进,我们希望能在人的属性里面查到自己的男朋友/女朋友,这里就需要对Person类进行修改:

class Relationship():def __init__(self):self.relationship = []  # 生成空列表def make_couple(self, p1, p2):  # 建立恋爱关系self.relationship = [p1, p2]print("[%s]和[%s]确定了恋爱关系"%(p1.name, p2.name))class Person():def __init__(self, name, age, sex, relation):self.name = nameself.age = ageself.sex = sexself.relation = relation  # 把对象是谁加到实例属性里面relationship = Relationship()
person1 = Person("zhaopeng", 25, "M", relationship)  
person2 = Person("wangwu", 25, "F", relationship)
relationship.make_couple(person1, person2)
print(person1.relation.relationship)
# 这里person1.relation其实就是之前建立的relationship = Relationship()
# 然后再.relationship输出的是那个列表

但是这样显示是个列表,我们再优化Relationship类,使得它更完整:

class Relationship():def __init__(self):self.relationship = []  # 生成空列表def make_couple(self, p1, p2):  # 建立恋爱关系self.relationship = [p1, p2]print("[%s]和[%s]确定了恋爱关系"%(p1.name, p2.name))def get_partner(self, person):  # 找寻另一半# 这里还要传入person是因为,self.relationship列表里有两个人,需要确定具体是显示哪一个的另一半if len(self.relationship) == 0:print("[%s]没有对象!" % person.name)else:for i in self.relationship:if i != person:print("[%s]的对象是[%s]" % (person.name, i.name))def break_up(self):  # 模拟分手if len(self.relationship) == 0:print("两人已经分手了")else:print("[%s]和[%s]分手了"%(self.relationship[0].name, self.relationship[1].name))self.relationship = []class Person():def __init__(self, name, age, sex, relation):self.name = nameself.age = ageself.sex = sexself.relation = relation  # 把对象是谁加到实例属性里面# 实例化
relationship = Relationship()
person1 = Person("zhaopeng", 25, "M", relationship)  
person2 = Person("wangwu", 25, "F", relationship)relationship.make_couple(person1, person2)  # 建立恋爱关系
# [zhaopeng]和[wangwu]确定了恋爱关系
person1.relation.get_partner(person1)  # 找到person1的另一半是谁
# [zhaopeng]的对象是[wangwu]
person1.relation.break_up()  # 分手
# [zhaopeng]和[wangwu]分手了
person2.relation.get_partner(person2)  # 此时获取person2的对象,显示无
# [wangwu]没有对象!

以上我们就同步了两个人的恋爱关系,同时导演了一部恋爱到分手的大戏(大雾)。

(3)组合关系
# 组合关系:由一堆组件构成一个完整的实体,组件本身独立但又不能自己运行,必须跟宿主组合在一起运行
# 这里的武器类就必须依赖人来运行,人实例化对象的同时也实例化武器
class Weapon():def gun(self, dog):self.attack_val = 50self.name = "枪"dog.life_val -= self.attack_valprint("[%s]被[%s]攻击了,掉血[%s],还剩血量[%s]"%(dog.name, self.name, self.attack_val, dog.life_val))def knife(self, dog):self.attack_val = 20self.name = "匕首"dog.life_val -= self.attack_valprint("[%s]被[%s]攻击了,掉血[%s],还剩血量[%s]"%(dog.name, self.name, self.attack_val, dog.life_val))def AK47(self, dog):self.attack_val = 80self.name = "AK47"dog.life_val -= self.attack_valprint("[%s]被[%s]攻击了,掉血[%s],还剩血量[%s]"%(dog.name, self.name, self.attack_val, dog.life_val))class Person():life_val = 100def __init__(self, name, age, sex):self.name = nameself.age = ageself.sex = sexself.weapon = Weapon()  # 把对象是谁加到实例属性里面class Dog():life_val = 100def __init__(self, name, d_type, attack_val):self.name = nameself.d_type = d_typeself.attack_val = attack_valdef bite(self, person):person.life_val -= self.attack_valprint("狗[%s]把人[%s]咬了,人掉血[%s],现在人剩余血量[%s]"%(self.name, person.name, self.attack_val, person.life_val))dog1 = Dog("zhangsan", "二哈", 5)
person1 = Person("Alex", 25, "M")
person1.weapon.gun(dog1)
# [zhangsan]被[枪]攻击了,掉血[50],还剩血量[50]
dog1.bite(person1)
# 狗[zhangsan]把人[Alex]咬了,人掉血[5],现在人剩余血量[95]

四. 类的继承

现在我们写人和猫。众所周知人和猫有很多相似之处,如它们都有姓名,性别,有2只眼睛,都会呼吸,会拉粑粑;也有不同之处,例如人会看书,猫会挠人的沙发,写成代码就是这样的:

class Person():def __init__(self, name, sex):self.name = nameself.sex = sexself.num_eyes = 2self.has_tails = Falsedef breathe(self):print(self.name,"在呼吸")def poop(self):print(self.name,"在拉粑粑")def read(self):print(self.name,"在读书")class Cat():def __init__(self, name, sex):self.name = nameself.sex = sexself.num_eyes = 2self.has_tails = Truedef breathe(self):print(self.name,"在呼吸")def poop(self):print(self.name,"在拉臭臭")def scratch_sofa(self):print(self.name,"在挠主人的沙发")person1 = Person("Alex", "M")
cat1 = Cat("MiaoMiao", "F")
person1.poop()
cat1.scratch_sofa()

现在我们要实现代码的重复利用,就可以使用类的继承,首先提取其公共部分写成mammul类:

class Mammul():def __init__(self, name, sex):self.name = nameself.sex = sexself.num_eyes = 2def breathe(self):print(self.name,"在呼吸")def poop(self):print(self.name,"在拉粑粑")

然后重写Person()和Cat()类,在括号内填写继承的父类名称,这个时候父类的__init__构造函数,还有breathe和poop方法都被继承了过来,虽然我们没有在Person()和Cat()类下面写他们。现在创建一个猫猫实例,由于Cat类没有__init__构造函数,系统会自动调用它继承的父类Mammul的构造函数,让实例具有姓名,性别,眼睛数等属性(我们先不写实例属性has_tails):

class Person(Mammul):def read(self):print(self.name,"在读书")class Cat(Mammul):def scratch_sofa(self):print(self.name,"在挠主人的沙发")person1 = Person("Alex", "M")
cat1 = Cat("MiaoMiao", "F")
person1.poop()  # Alex 在拉粑粑
cat1.scratch_sofa()  # MiaoMiao 在挠主人的沙发

然而,如果我们在子类里面写了专属于人的拉屎方法,就会优先调用子类的,没有的话才去父类找同名方法用:

class Mammul():def __init__(self, name, sex):self.name = nameself.sex = sexself.num_eyes = 2def breathe(self):print(self.name,"在呼吸")def poop(self):print(self.name,"在拉粑粑")class Person(Mammul):def poop(self):print(self.name,"在拉shi")def read(self):print(self.name,"在读书")person1 = Person("Alex", "M")
person1.poop()  # Alex 在拉shi

注意到我们还没有写实例属性has_tails,而如果在子类直接写:

class Person(Mammul):def __init__(self):self.has_tails = Falsedef poop(self):print(self.name,"在拉shi")def read(self):print(self.name,"在读书")

则根据前面的,系统会直接调用子类的__init__构造函数,所以父类的姓名,性别,2只眼属性都没办法继承过来,为了解决这个问题,标准写法应该加上super(),它也是一个类,既不是方法也不是函数。super会返回当前类的父类,在子类的构造函数中写super().__init__就会调用父类的构造函数。所以本节最开始的代码优化后可以这样写:

class Mammul():def __init__(self, name, sex):self.name = nameself.sex = sexself.num_eyes = 2def breathe(self):print(self.name,"在呼吸")def poop(self):print(self.name,"在拉粑粑")class Person(Mammul):def __init__(self, name, sex):super().__init__(name, sex)self.has_tails = Falsedef read(self):print(self.name,"在读书")class Cat(Mammul):def __init__(self, name, sex):super().__init__(name, sex)self.has_tails = Truedef scratch_sofa(self):print(self.name,"在挠主人的沙发")person1 = Person("Alex", "M")
cat1 = Cat("MiaoMiao", "F")
person1.poop()  # Alex 在拉shi
cat1.scratch_sofa()  # MiaoMiao 在挠主人的沙发
print(cat1.num_eyes)  # 2

最后我们再写一个人力资源管理系统作为类继承的练习:

# 类继承练习:人力系统
# 员工分为两类:全职员工FullTimeEmployee、兼职员工PartTimeEmployee。全职和兼职都有"姓名 name"、"工号 id"属性,
# 都具备"打印信息 print_info"(打印姓名、工号)方法。
# 全职有"月薪 monthly_salary"属性,兼职有"日薪 daily_salary"属性、"每月工作天数 work_days"的属性。
# 全职和兼职都有"计算月薪 calculate_monthly_pay"的方法,但具体计算过程不一样。
class Employee():def __init__(self, name, id):self.name = nameself.id = iddef print_info(self):print("员工的姓名是:", self.name)print("员工的id是:", self.id)class FullTimeEmployee(Employee):def __init__(self, name, id, month_salary):super().__init__(name, id)self.month_salary = month_salaryself.type = "全职员工"def caculate_month_salary(self):print("员工[%s]是全职员工,当月月薪是:[%s]"%(self.name, self.month_salary))class PartTimeEmployee(Employee):def __init__(self, name, id, day_salary, work_days):super().__init__(name, id)self.day_salary = day_salaryself.work_days = work_daysself.type = "兼职员工"def caculate_month_salary(self):print("员工[%s]是兼职员工,当月工作天数是[%s],每天工资是[%s],本月工资是:[%s]"%(self.name, self.work_days, self.day_salary, self.day_salary*self.work_days))employee1 = FullTimeEmployee("Alex", 4312890, 2500)
employee2 = PartTimeEmployee("Jack", 5410984, 25, 14)
employee1.print_info()
# 员工的姓名是: Alex
# 员工的id是: 4312890
employee1.caculate_month_salary()
#员工[Alex]是全职员工,当月月薪是:[2500]
employee2.caculate_month_salary()
# 员工[Jack]是兼职员工,当月工作天数是[14],每天工资是[25],本月工资是:[350]

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

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

相关文章

智慧公厕的目的和意义是什么?

智慧公厕是近年来城市建设中的一项重要举措,其目的在于实现公共厕所的智慧化管理,为市民群众提供更好的服务体验,助力智慧城市和数字环卫的发展,提升社会公共卫生服务水平。 与此同时,智能公厕也具有重要的意义&#x…

springboot+vue实现微信公众号扫码登录

通常在个人网站中,都会有各种第三方登录,其中微信登录需要认证才能使用,导致个人开发者不能进行使用此功能,但是我们可以使用微信公众号回复特定验证码来进行登录操作。 微信关键词处理 微信公众号关键词自动回复,具体…

60kW 可编程直流回馈负载箱的优势和特点

60kW可编程直流回馈负载箱是一种先进的电力设备,主要用于模拟电网中的负载,为电力系统提供稳定的负载环境。它具有许多优势和特点,使其在电力系统中得到了广泛的应用。 60kW可编程直流回馈负载箱具有高效的能源转换效率,能够将电能…

人机界面和三菱PLC之间以太网通信

本文主要描述人机界面WinCC如何与三菱Q系列PLC进行以太网通讯,主要介绍了CPU自带以太网口和扩展以太网模块两种情况以及分别使用TCP、UDP两种协议进行通讯组态步骤及其注意事项。 一、 说明 WinCC从V7.0 SP2版本开始增加了三菱以太网驱动程序,支持和三…

Windows常用协议

LLMNR 1. LLMNR 简介 链路本地多播名称解析(LLMNR)是一个基于域名系统(DNS)数据包格式的协议,可用于解析局域网中本地链路上的主机名称。它可以很好地支持IPv4和IPv6,是仅次于DNS 解析的名称解析协议。 2.LLMNR 解析过程 当本地hosts 和 DNS解析 当本地hosts 和 …

docker 常用指令(启动,关闭,查看运行状态)

文章目录 docker 常用指令启动 docker关闭 docker查看 docker的运行状态 docker 常用指令 启动 docker systemctl start docker关闭 docker systemctl stop docker查看 docker的运行状态 systemctl status docker如下图所示: 表示docker正在运行中

集合框架体系和使用1(Collection)

Map的不同实现类单独再搞一章讲 目录 数组的特点、弊端与集合框架体系介绍 数组 特点 弊端 Java集合框架体系(java.util包下) java.util.Collection:存储一个一个的数据(主要讲两个子接口) java.util.Map:存储一对一对的数据…

基于uniapp大学生社团活动管理系统python+java+node.js+php微信小程序

uni-app框架:使用Vue.js开发跨平台应用的前端框架,编写一套代码,可编译到Android、小程序等平台。 语言:pythonjavanode.jsphp均支持 框架支持:springboot/Ssm/thinkphp/django/flask/express均支持 运行软件:idea/eclipse/vscod…

递归和迭代【Py/Java/C++三种语言详解】LeetCode每日一题240218【树DFS】LeetCode 589、 N 叉树的前序遍历

有LeetCode算法/华为OD考试扣扣交流群可加 948025485 可上全网独家的 欧弟OJ系统 练习华子OD、大厂真题 绿色聊天软件戳 od1336了解算法冲刺训练 文章目录 题目描述解题思路代码方法一:递归法PythonJavaC时空复杂度 方法二:迭代法PythonJavaC时空复杂度 …

面试redis篇-08数据淘汰策略

原理 当Redis中的内存不够用时,此时在向Redis中添加新的key,那么Redis就会按照某一种规则将内存中的数据删除掉,这种数据的删除规则被称之为内存的淘汰策略。 Redis支持8种不同策略来选择要删除的key: noeviction: 不淘汰任何key,但是内存满时不允许写入新数据,默认就是…

JetBrains系列工具,配置PlantUML绘图

PlantUML是一个很强大的绘图工具,各种图都可以绘制,具体的可以去官网看看,或者百度。 PlantUML简述 https://plantuml.com/zh/ PlantUML语言参考指引 https://plantuml.com/zh/guide PlantUML语言是依赖Graphviz进行解析的。Graphviz是开源…

[设计模式Java实现附plantuml源码~行为型] 撤销功能的实现——备忘录模式

前言: 为什么之前写过Golang 版的设计模式,还在重新写Java 版? 答:因为对于我而言,当然也希望对正在学习的大伙有帮助。Java作为一门纯面向对象的语言,更适合用于学习设计模式。 为什么类图要附上uml 因为很…

2024程序员容器化上云之旅-第6集-Ubuntu-WSL2-Windows11版:艰难复活

故事梗概 Java程序员马意浓在互联网公司维护老旧电商后台系统。 渴望学习新技术的他在工作中无缘Docker和K8s。 他开始自学Vue3并使用SpringBoot3完成了一个前后端分离的Web应用系统,并打算将其用Docker容器化后用K8s上云。 8 复活重生 周末终于有点属于自己的…

【书籍分享 • 第三期】虚拟化与容器技术

文章目录 一、本书内容二、读者对象三、编辑推荐四、前言4.1 云计算技术的发展4.2 KVM、Docker4.3 本书内容简介4.4 作者简介 五、粉丝福利 一、本书内容 《虚拟化与容器技术》通过深入浅出的方式介绍KVM虚拟化技术与Docker容器技术的概念、原理及实现方法,内容包括…

Linux之安装Nginx、前后端分离项目部署

目录 一、安装Nginx 1.1先一键安装4个依赖 1.2下载并解压安装包 1.3安装nginx,一般我们在nginx都是要安装ssl证书的 1.4 启动nginx服务 1.5开放80端口 1.6配置nginx自启动 1.7修改/etc/rc.d/rc/local的权限 二、多个tomcat负载加后端部署 2.1创建多个tomca…

Windows已经安装了QT 6.3.0,如何再安装一个QT 5.12

要在Windows上安装Qt 5.12,您可以按照以下步骤操作: 下载Qt 5.12:访问Qt官方网站或其他可信赖的来源,下载Qt 5.12的安装包。 下载安装地址 下载安装详细教程 安装问题点 qt安装时“Error during installation process(qt.tools…

react useRef用法

1&#xff0c;保存变量永远不丢失 import React, { useState,useRef } from react export default function App() { const [count,setcount] useState(0) var mycount useRef(0)//保存变量永远不丢失--useRef用的是闭包原理 return( <div> <button onClick{()>…

跨境电商营销进化史:从传统广告到智能化策略的全面探析

随着全球化的不断推进和互联网技术的飞速发展&#xff0c;跨境电商在过去几年里取得了显著的发展。在这个竞争激烈的市场中&#xff0c;企业们纷纷调整营销策略以应对不断变化的消费者需求和市场趋势。本文Nox聚星将和大家探讨跨境电商营销策略的演变过程&#xff0c;从传统的推…

MySQL基础(二)

文章目录 MySQL基础&#xff08;二&#xff09;1. 数据库操作-DQL1.1 介绍1.2 语法1.3 基本查询1.4 条件查询1.5 聚合函数1.6 分组查询1.7 排序查询1.8 分页查询1.9 案例1.9.1 案例一1.9.2 案例二 2. 多表设计2.1 一对多2.1.1 表设计2.1.2 外键约束 2.2 一对一2.3 多对多2.4 案…

Python爬虫中的单线程、多线程问题(文末送书)

前言 在使用爬虫爬取数据的时候&#xff0c;当需要爬取的数据量比较大&#xff0c;且急需很快获取到数据的时候&#xff0c;可以考虑将单线程的爬虫写成多线程的爬虫。下面来学习一些它的基础知识和代码编写方法。 一、进程和线程 进程可以理解为是正在运行的程序的实例。进…