Python教程:面向对象

模块3:Python高级

模块概述

本课程旨在介绍Python编程语言中的面向对象编程(OOP)概念和技术。学生将学习如何使用类、对象、继承、多态等OOP的关键要素来构建灵活、可重用和可扩展的代码。通过实际编程练习和项目,学生将提高他们的编程技能,学会设计和实现面向对象的解决方案。

面向对象编程是在面向过程编程的基础上发展来的,它比面向过程编程具有更强的灵活性和扩展性。面向对象编程是程序员发展的分水岭,很多初学者会因无法理解面向对象而放弃学习编程,所以我们一定要足够重视。

课程目标
  • 理解面向对象编程的基本原则和思想。
  • 掌握Python中的类、对象、属性和方法的概念。
  • 熟悉继承、多态和封装等OOP的高级概念。
  • 能够设计和实现面向对象的解决方案。
  • 培养良好的编码风格和软件工程实践。

面向对象基础

【1】类和对象

(1)类和对象的概念

面向对象编程(Object-oriented Programming,简称 OOP)是一种编程范式。

  • 从思想角度讲

面向对象思想来源于对现实世界的认知。现实世界中每一个事物都是一个对象,它是一种具体的概念。类是人们抽象出来的一个概念,所有拥有相同属性和功能的事物称为一个类;而拥有相同属性和功能的具体事物则成为这个类的实例对象。

现实世界缤纷复杂、种类繁多,难于认识和理解。但是聪明的人们学会了把这些错综复杂的事物进行分类,从而使世界变得井井有条。比如我们由各式各样的汽车抽象出汽车的概念,由形形色色的猫抽象出猫的概念,由五彩斑斓的鲜花抽象出花的概念等。汽车、猫、鲜花都代表着一类事物。每一类事物都有特定的状态,比如汽车的品牌、时速、马力、耗油量、座椅数,小猫的年龄、体重、毛色,鲜花的颜色、花瓣形状、花瓣数目,都是在描述事物的状态。每类事物也都有一定的行为,比如汽车启动、行驶、加速、减速、刹车、停车,猫捉老鼠,鲜花盛开。这些不同的状态行为将各类事物区分开来。

面向对象编程提供了一种从现实世界中抽象出概念和实体的方法。通过类和对象的概念,可以将现实世界中的问题和关系转化为代码结构,使得程序更加符合问题域的模型化。

面向对象编程通过采用类的概念,把事物编写成一个个“类”。在类中,用数据表示事物的状态,用函数实现事物的行为,这样就使编程方式和人的思维方式保持一致,极大的降低了思维难度。

  • 从封装角度讲

面向对象编程(Object-oriented Programming,简称 OOP),是一种封装代码的方法。其实,在前面章节的学习中,我们已经接触了封装,比如说,将乱七八糟的数据扔进列表中,这就是一种简单的封装,是数据层面的封装;把常用的代码块打包成一个函数,这也是一种封装,是语句层面的封装。

# 声明类
class Dog:legs_num = 4has_hair = Truehas_tail = Truedef bark(self):print("狗狂吠")def bite(self):print("狗咬人")def fetch(self):print("狗捡球")# 实例化对象
alex = Dog()
print(alex.legs_num)
alex.bark()
alex.bite()class Bird:legs_nums = 2has_wings = Truehas_teeth = Falsedef fly(self):print("鸟飞翔")def eat_worms(self):print("鸟吃虫子")def nest(self):print("鸟筑巢")# 实例化对象
b1 = Bird()
print(b1.has_wings)
print(b1.has_teeth)
b1.fly()

面向对象编程(Object-Oriented Programming,简称OOP)相较于面向过程编程(Procedural Programming)有以下几个优点:

  1. 封装性(Encapsulation):面向对象编程通过将数据和操作封装在一个对象中,使得对象成为一个独立的实体。对象对外部隐藏了内部的实现细节,只暴露出必要的接口,从而提高了代码的可维护性和模块化程度。
  2. 继承性(Inheritance):继承是面向对象编程的重要特性之一。它允许创建一个新的类(子类),从一个现有的类(父类或基类)继承属性和方法。子类可以通过继承获得父类的特性,并可以在此基础上进行扩展或修改。继承提供了代码重用的机制,减少了重复编写代码的工作量。
  3. 多态性(Polymorphism):多态性使得对象可以根据上下文表现出不同的行为。通过多态机制,可以使用统一的接口来处理不同类型的对象,而不需要针对每种类型编写特定的代码。这提高了代码的灵活性和可扩展性。
  4. 代码的可维护性和可扩展性:面向对象编程强调模块化和代码复用,通过将功能划分为独立的对象和类,使得代码更易于理解、测试和维护。当需求变化时,面向对象编程的结构和机制使得代码的修改和扩展更加简洁和可靠。

总的来说,面向对象编程提供了一种更加结构化、可扩展和可维护的编程范式。它通过封装、继承和多态等特性,使得代码更加模块化、灵活和易于理解。这些优点使得面向对象编程成为当今广泛采用的编程范式之一,被广泛应用于软件开发中。

(2)类和实例对象的语法

面向对象最重要的概念就是类(Class)和实例(Instance),必须牢记类是抽象的模板,比如Person类,而实例是根据类创建出来的一个个具体的“对象”,每个对象都拥有相同的方法,但各自的数据可能不同。

# 声明类
class 类名:类属性...方法...# 类的实例化
实例对象 = 类名() # 开辟一块独立的属于实例空间,将空间地址作为返回值# 实例对象可以通过句点符号调用类属性和方法
实例对象.类属性
实例对象.方法(实参)
  1. 和变量名一样,类名本质上就是一个标识符,命名遵循变量规范。如果由单词构成类名,建议每个单词的首字母大写,其它字母小写。
  2. 冒号 + 缩进标识类的范围
  3. 无论是类属性还是类方法,对于类来说,它们都不是必需的,可以有也可以没有。另外,Python 类中属性和方法所在的位置是任意的,即它们之间并没有固定的前后次序。
# 声明类
class Dog:legs_num = 4has_hair = Truehas_tail = Truedef bark(self):print("狗狂吠")def bite(self):print("狗咬人")def fetch(self):print("狗捡球")# 实例化对象
alex = Dog()
print(alex.legs_num)
alex.bark()
alex.bite()
# 实例化对象
peiQi = Dog()
# print(id(alex))
# print(id(peiQi))print(id(alex.legs_num))
print(id(peiQi.legs_num))print(id(alex.bark))
print(id(peiQi.bark))

【2】实例属性和实例方法

(1)实例属性

类变量(类属性)的特点是,所有类的实例化对象都同时共享类变量,也就是说,类变量在所有实例化对象中是作为公用资源存在的。实例属性是属于类的每个实例对象的特定属性。实例属性是在创建对象时赋予的,每个对象可以具有不同的实例属性值。

alex = Dog()
peiQi = Dog()
# 实例属性: 属于实例对象自己的属性
alex.name = "李杰"
alex.age = 10
peiQi.name = "武大郎"
peiQi.age = 20
# 问题1:
print(alex.name)
alex.age = 30
print(alex.age)
# 问题2:
print(peiQi.age)
# 问题3:
alex.bark()
alex.bark = "hello world"
# alex.bark()
peiQi.bark()
(2)实例方法和self

在 Python 的类定义中,self 是一个特殊的参数,用于表示类的实例对象自身。self 参数必须作为第一个参数出现在类的方法定义中,通常被约定为 self,但实际上你可以使用其他名称。

当你调用类的方法时,Python 会自动将调用该方法的实例对象传递给 self 参数。这样,你就可以通过 self 参数来引用和操作实例对象的属性和方法。

class Dog:def eat(self):print(f"{self.name}正在吃东西。")def run(self):print(f"{self.name}正在跑。")def sleep(self):print(f"{self.name}正在睡觉。")def bark(self):print(f"{self.name}正在狂吠。")def show_info(self):print(f"名字:{self.name},品种:{self.breed},颜色:{self.color},年龄:{self.age}")# 声明对象
bulldog = Dog()
# 赋值实例属性
bulldog.name = "小灰"
bulldog.breed = "斗牛犬"
bulldog.color = "浅灰色"
bulldog.age = 5# 调用斗牛犬的行为
bulldog.eat()
bulldog.run()
bulldog.sleep()
bulldog.bark()
bulldog.show_info()

【3】构造方法__init__

目前的程序:

class Dog:def eat(self):print(f"{self.name}正在吃东西。")def run(self):print(f"{self.name}正在跑。")def sleep(self):print(f"{self.name}正在睡觉。")def bark(self):print(f"{self.name}正在狂吠。")def show_info(self):print(f"名字:{self.name},品种:{self.breed},颜色:{self.color},年龄:{self.age}")# 声明对象
bulldog = Dog()
# 赋值实例属性
bulldog.name = "小灰"
bulldog.breed = "斗牛犬"
bulldog.color = "浅灰色"
bulldog.age = 5# 调用斗牛犬的行为
bulldog.eat()
bulldog.run()
bulldog.sleep()
bulldog.bark()
bulldog.show_info()# 声明对象
beagle = Dog()
# "小黄","小猎犬", "橘色", 6
# beagle.bark()  # 报错# 赋值实例属性
beagle.name = "小黄"
beagle.breed = "小猎犬"
beagle.color = "橘色"
beagle.age = 6beagle.bark()
beagle.show_info()

在这套代码中,对象的属性是通过直接赋值给对象的实例属性来实现的,而不是在构造方法中进行初始化。这样做可能会导致以下问题:

  1. 代码冗余:每次创建对象时都需要分别为每个对象赋值实例属性,这会导致代码冗余和重复劳动。
  2. 可维护性差:如果类的属性发生变化或新增属性,需要修改多处代码来适应这些变化,而如果使用构造方法来初始化属性,则只需要在一个地方进行修改。

为了改进这种写法,可以使用构造方法来初始化对象的属性。构造方法在创建对象时自动调用,并可以接受参数来初始化对象的属性。

class Dog:def __init__(self, name, breed, color, age):self.name = nameself.breed = breedself.color = colorself.age = agedef eat(self):print(f"{self.name}正在吃东西。")def run(self):print(f"{self.name}正在跑。")def sleep(self):print(f"{self.name}正在睡觉。")def bark(self):print(f"{self.name}正在狂吠。")def show_info(self):print(f"名字:{self.name},品种:{self.breed},颜色:{self.color},年龄:{self.age}")# 声明对象
bulldog = Dog("小灰", "斗牛犬", "浅灰色", 5)# 调用斗牛犬的行为bulldog.bark()
bulldog.show_info()# 声明对象
beagle = Dog("小黄", "小猎犬", "橘色", 6)beagle.bark()
beagle.show_info()

实例化一个类的过程可以分为以下几个步骤:

  1. 创建一个新的对象(即开辟一块独立空间),它是类的实例化结果。
  2. 调用类的__init__方法,将新创建的对象作为第一个参数(通常命名为self),并传递其他参数(如果有的话)。
  3. __init__方法中,对对象进行初始化,可以设置对象的属性和执行其他必要的操作。
  4. 返回新创建的对象,使其成为类的实例。

在创建类时,我们可以手动添加一个 __init__() 方法,该方法是一个特殊的类实例方法,称为构造方法(或构造函数)。

__init__() 方法可以包含多个参数,但必须包含一个名为 self 的参数,且必须作为第一个参数。除了 self 参数外,还可以自定义一些参数,从而完成初始化的工作。

  1. 注意到__init__方法的第一个参数永远是self,表示创建的实例本身,因此,在__init__方法内部,就可以把各种属性绑定到self,因为self是指向创建的实例本身。
  2. 实例属性,实例变量,实例成员变量都是指的存在实例空间的属性

【4】一切皆对象

在python语言中,一切皆对象!

我们之前学习过的字符串,列表,字典等等数据都是一个个的类,我们用的所有数据都是一个个具体的实例对象。

区别就是,那些类是在解释器级别注册好的,而现在我们学习的是自定义类,但语法使用都是相同的。所以,我们自定义的类实例对象也可以和其他数据对象一样可以进行传参、赋值等操作。

练习:游戏案例

函数版本:

hero = {"name": "yuan","health": 1000,"gold": 100,"defense": 10,"attack": 90,"level": 1,"weapon_list": []
}# 测试攻击敌人
enemy = {"name": "alex","health": 500,"defense": 5,"attack": 50,"gold": 100,"level": 1,"weapon_list": []
}def attack_enemy(player, enemy):damage = player["attack"] - enemy["defense"]if damage > 0:enemy["health"] -= damageprint(f"{player['name']}成功攻击了敌人{enemy['name']},造成了{damage}点伤害。")else:print(f"{player['name']}的攻击被敌人防御了。")def buy_weapon(player, weapon):player["weapon_list"].append(weapon)print(f"{player['name']}购买装备{weapon}!")def level_up(player):player["level"] += 1player["gold"] += 100print(f"{player['name']}升级了,奖励金币100!")buy_weapon(hero, "屠龙刀")
attack_enemy(hero, enemy)
level_up(hero)

面向对象版本:

class Weapon:def __init__(self, name, attack, defense):self.name = nameself.attack = attackself.defense = defensedef upgrade(self):self.attack += 50self.defense += 50print(f"{self.name}的防御力增加了50点。")print(f"{self.name}的防御力增加了50点。")class Player:def __init__(self, name, health=100, gold=100, defense=100, attack=100, level=1, weapon_list=[]):self.name = nameself.health = healthself.gold = goldself.defense = defenseself.attack = attackself.level = levelself.weapon_list = weapon_listdef attack_enemy(self, enemy, weapon_index=None):if weapon_index is None:damage = self.attack - enemy.defenseelse:damage = self.weapon_list[weapon_index].attack - enemy.defenseif damage > 0:enemy.health -= damageprint(f"{self.name}成功攻击了敌人{enemy.name},造成了{damage}点伤害。")else:print(f"{self.name}的攻击被敌人防御了。")def buy_weapon(self, weapon):self.weapon_list.append(weapon)print(f"{self.name}购买装备{weapon.name}!")def level_up(self):self.level += 1self.gold += 100print(f"{self.name}升级了,奖励金币100!")p1 = Player("YUAN")
p2 = Player("ALEX")p1.attack_enemy(p2)
w1 = Weapon("屠龙刀", 1000, 300)
p1.buy_weapon(w1)
p1.attack_enemy(p2, 0)

【5】类对象和类属性

class Person:# 类属性legs_num = 2has_emotion = Truedef __init__(self, name, age):self.name = nameself.age = agedef play_fire(self):print("%s玩火"%self.name)# 实例对象和类对象可以获取类属性,但是只有类对象才能修改类属性
yuan = Person("yuan", 18)
alvin = Person("alvin", 18)print(yuan.legs_num)
print(yuan.name)
# Person:一个类对象
print(Person.legs_num)

【6】静态方法和类方法

(1)静态方法

定义:使用装饰器@staticmethod。参数随意,没有selfcls参数,但是方法体中不能使用类或实例的任何属性和方法;

调用:类对象或实例对象都可以调用。

class Cal():@staticmethoddef add(x,y):return x+y@staticmethoddef mul(x,y):return x*ycal=Cal()
print(cal.add(1, 4))
or
print(Cal.add(3,4))
(2)类方法

定义:使用装饰器@classmethod。第一个参数必须是当前类对象,该参数名一般约定为cls,通过它来传递类的属性和方法(不能传实例的属性和方法);

调用:类对象或实例对象都可以调用。

class Student:# 类属性cls_number = 68@classmethoddef add_cls_number(cls):cls.cls_number+=1print(cls.cls_number)Student.add_cls_number()

思考:

  • 类对象.实例方法会怎么样?

  • 类方法的意义是什么,在实例方法中使用类对象变量不可以吗?

Day12:面向对象进阶

一、面向对象之继承

面向对象的编程带来的主要好处之一是代码的重用,实现这种重用的方法之一是通过继承机制。通过继承创建的新类称为子类派生类,被继承的类称为基类父类超类

class 派生类名(基类名)...
【1】继承的基本使用

继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类。通过使用继承我们能够非常方便地复用以前的代码,能够大大的提高开发的效率。

实际上继承者是被继承者的特殊化,它除了拥有被继承者的特性外,还拥有自己独有得特性。例如猫有抓老鼠、爬树等其他动物没有的特性。同时在继承关系中,继承者完全可以替换被继承者,反之则不可以,例如我们可以说猫是动物,但不能说动物是猫就是这个道理,其实对于这个我们将其称之为“向上转型”。

诚然,继承定义了类如何相互关联,共享特性。对于若干个相同或者相识的类,我们可以抽象出他们共有的行为或者属相并将其定义成一个父类或者超类,然后用这些类继承该父类,他们不仅可以拥有父类的属性、方法还可以定义自己独有的属性或者方法。

同时在使用继承时需要记住三句话:

1、子类拥有父类非私有化的属性和方法。

2、子类可以拥有自己属性和方法,即子类可以对父类进行扩展。

3、子类可以用自己的方式实现父类的方法。(下面会介绍)。

# 无继承方式class Dog:def eat(self):print("eating...")def sleep(self):print("sleep...")def swimming(self):print("swimming...")class Cat:def eat(self):print("eating...")def sleep(self):print("sleep...")def climb_tree(self):print("climb_tree...")# 继承方式class Animal:def eat(self):print("eating...")def sleep(self):print("sleep...")class Dog(Animal):def swimming(self):print("toshetou...")class Cat(Animal):def climb_tree(self):print("climb_tree...")alex = Dog()
alex.run()
【2】重写父类方法和调用父类方法
class Person(object):def __init__(self,name,age):self.name=nameself.age=agedef sleep(self):print("基类sleep...")class Emp(Person):# def __init__(self,name,age,dep):#      self.name = name#      self.age = age#      self.dep = depdef __init__(self, name, age, dep):# Person.__init__(self,name,age)super().__init__(name,age)self.dep = depdef sleep(self):if "不在公司":# print("子类sleep...")# 调用父类方法# 方式1 :父类对象调用 父类对象.方法(self,其他参数)# Person.sleep(self)# 方式2: super关键字 super(子类对象,self).方法(参数)or super().方法(参数)super().sleep()yuan = Emp("yuan",18,"教学部")
yuan.sleep()
print(yuan.dep)# 测试题:class Base:def __init__(self):self.func()def func(self):print('in base')class Son(Base):def func(self):print('in son')s = Son()
【3】多重继承

如果在继承元组中列了一个以上的类,那么它就被称作"多重继承" 。派生类的声明,与他们的父类类似,继承的基类列表跟在类名之后,如下所示:

class SubClassName (ParentClass1[, ParentClass2, ...]):...

多继承有什么意义呢?还拿上面的例子来说,蝙蝠和鹰都可以飞,飞的功能就重复定义了。

class Animal:def eat(self):print("eating...")def sleep(self):print("sleep...")class Eagle(Animal):def fly(self):print("fly...")class Bat(Animal):def fly(self):print("fly...")

有同学肯定想那就放到父类Animal中,可是那样的话其他不会飞的动物还怎么继承Animal呢?所以,这时候多重继承就发挥功能了:

class Fly:def fly(self):print("fly...")class Eagle(Animal,Fly):passclass Bat(Animal,Fly):pass
【4】 type 和isinstance方法
class Animal:def eat(self):print("eating...")def sleep(self):print("sleep...")class Dog(Animal):def swim(self):print("swimming...")alex = Dog()
mjj = Dog()print(isinstance(alex,Dog))
print(isinstance(alex,Animal))
print(type(alex))
【4】dir()方法和__dict__属性

dir(obj)可以获得对象的所有属性(包含方法)列表, 而obj.__dict__对象的自定义属性字典

注意事项:

  1. dir(obj)获取的属性列表中,方法也认为属性的一种。返回的是list
  2. obj.__dict__只能获取自己自定义的属性,系统内置属性无法获取。返回是dict
class Student:def __init__(self, name, score):self.name = nameself.score = scoredef test(self):passyuan = Student("yuan", 100)
print("获取所有的属性列表")
print(dir(yuan))print("获取自定义属性字段")
print(yuan.__dict__)

其中,类似__xx__的属性和方法都是有特殊用途的。如果调用len()函数视图获取一个对象的长度,其实在len()函数内部会自动去调用该对象的__len__()方法

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

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

相关文章

太速科技-1路万兆光纤SFP+和1路千兆网络 FMC子卡模块

1路万兆光纤SFP和1路千兆网络 FMC子卡模块 一、概述 该板卡是基于kc705和ml605的fmc 10g万兆光纤扩展板设计,提供了1路万兆光纤SFP和1路千兆网络接口。可搭配我公司开发的FPGA载卡使用。载卡可参考:ID204 SFP(10 Gigabit Small…

AWS-亚马逊网络服务(基础服务)-AWS 定价计算器-概述与动手部署:

让我们来概述并亲身实践如何使用 AWS 定价计算器来计算 概述: AWS 定价计算器是 Amazon Web Services (AWS) 提供的基于 Web 的工具,可帮助用户估算其特定用例的 AWS 服务成本。欢迎来到雲闪世界。 它允许客户建模他们的基础设施并根据他们打算使用的…

Android 9.0 增加interface audio接口,解决编译报错

最近修改Android接口,报了一个VNDK的错误 我总结了如下几种方式: 1、直接关闭(不推荐): 在BoardConfig.mk中加入如下两行,可以在编译的时候不去check VNDK,关掉这个可能会导致XTS某些测项跑不…

Burp Suite Professional 2024.8 for macOS x64 ARM64 - 领先的 Web 渗透测试软件

Burp Suite Professional 2024.8 for macOS x64 & ARM64 - 领先的 Web 渗透测试软件 世界排名第一的 Web 渗透测试工具包 请访问原文链接:https://sysin.org/blog/burp-suite-pro-mac/,查看最新版。原创作品,转载请保留出处。 作者主页…

Linux内核编程(十五)网络设备驱动

本文目录 一、常见的网络协议二、传输介质三、RJ-45接口 对于网络知识不太熟悉的同学可以查看这篇文章:计算机网络知识点详情总结。 一、常见的网络协议 TCP、UDP协议:详情查看-TCP、UDP系统编程。DNS协议:是互联网中用于将域名&#xff08…

RocketMQ集群搭建,及RocketMQ-Dashboard部署(前RocketMQ-Console)

集群搭建 RocketMQ不支持单主机搭建主从结构集群,当从节点启动时,即使和主节点设置不同的监听端口,他也要去监听主节点端口,也就是说正常启动的从节点会监听四个端口。原因未知,现象后面会列举出来。 1. 准备JAVA环境…

python用波形显示udp数据实现一个模拟示波器

显示端代码: import socket import matplotlib.pyplot as plt import matplotlib.animation as animation import numpy as np# UDP setup udp_ip = 0.0.0.0 # Listen on all network interfaces udp_port = 12345 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)…

在 Ubuntu 环境下使用 VSCode 和 PlatformIO 下载程序到 Arduino Uno

安装 VSCode 访问 VSCode 官网 下载 .deb 包使用以下命令安装&#xff1a;sudo dpkg -i <下载的文件名>.deb sudo apt-get install -f安装 PlatformIO 扩展 在 VSCode 中&#xff0c;转到扩展市场&#xff08;CtrlShiftX&#xff09;搜索 “PlatformIO IDE”点击 “安装”…

STM32 HAL CAN (TJA1050CAN模块) 通讯(一)理论

1、简介 CAN具备多个设备交互的能力,但是网上大多是两个单片机进行交互,或者单片机通过CAN收发器与上位机进行交互测试,本次通过STM32cubeMX完成CAN通讯配置,并通过多个单片机进行数据交互测试。 2、CAN简介 CAN是一种串行通讯协议,主要有低速、高速CAN两种。 低速CAN…

相亲交友系统商业开发

在快节奏的现代生活中&#xff0c;寻找真爱成为了许多人的渴望。相亲交友系统&#xff0c;作为连接心灵的桥梁&#xff0c;正逐渐成为人们寻找伴侣的首选方式。我们的团队h17711347205致力于开发一款创新的相亲交友系统&#xff0c;旨在通过智能化的匹配算法&#xff0c;为用户…

Android UID 和 userID 以及 appID

我们知道Android 操作系统是基于Linux内核的&#xff0c;所以Android 的UID 是基于 Linux UID的。 Linux UID Linux 本身就是一个多用户操作系统&#xff0c;每一个用户都会有一个UID&#xff0c;不同UID 之间的资源访问是受限的。 其中&#xff0c;Linux的DAC权限模型&#…

this.$route.path 和 location.href获取的值不一样

引言&#xff1a; vue项目中动态加载路由组件this. r o u t e . p a t h 获取不正确&#xff08;获取是‘ / ‘而不是‘ / f o r g e t P w d ’&#xff09;浏览器中的路由是 / f o r g e t P w d &#xff0c;路由全局钩子 r o u t e r . b e f o r e E a c h 得到的 p a t …

【UE5】控件蓝图——树视图(TreeView)的基本使用

目录 前言 效果 步骤 一、显示根节点 二、显示子节点 前言 我们在视口中添加1个方块&#xff0c;2个球体&#xff0c;5个圆柱 它们在大纲视图中的层级关系如下&#xff0c;那么如何将这种层级关系显示在树视图中是本篇文章要解决的问题。 效果 步骤 一、显示根节点 1…

[STM32]从零开始的STM32标准库环境搭建(小白向)

一、我们为什么要搭建STM32标准库开发环境 如果你对STM32有一定的了解&#xff0c;相信你已经认识了STM32的几种开发方式。基于STM32寄存器开发&#xff0c;基于ST官方的标准库开发&#xff0c;基于ST官方的HAL库开发。我们现在来了解一下这些库的优缺点。首先就是基于寄存器开…

macos USB外接键盘ctrl键绑定方法 解决外接USB键盘与mac键盘不一致问题

mac电脑外接USB键盘后我们需要修改一下 ctrl键的绑定后才符合我们的使用习惯,因为标准USB键盘和mac键盘上面的ctrl键是不一样的, mac上面的 command 键 对应我们USB键盘上面的 ctrl 键. 修改方法: 偏好设置 --> 键盘 点击修饰键 后 选择键盘里面选择 USB键盘 ,然后调换…

Leetcode JAVA刷刷站(111)二叉树的最小深度

一、题目概述 二、思路方向 在Java中&#xff0c;要找出二叉树的最小深度&#xff0c;我们可以使用递归的方法。基本思路是&#xff0c;对于给定的根节点&#xff0c;如果它是空的&#xff0c;那么最小深度为0&#xff08;但实际上&#xff0c;空树没有深度&#xff0c;但在…

django之ForeignKey、OneToOneField 和 ManyToManyField

在Django中&#xff0c;ForeignKey、OneToOneField 和 ManyToManyField 是用于定义模型之间关系的字段类型。 ForeignKey ForeignKey 用于定义多对一的关系。例如&#xff0c;一个Employee可以属于一个Department&#xff0c;一个Department可以有多个Employee。 from djang…

Sui Hacker House曼谷站报名开启:在Devcon 2024期间探索Sui区块链创新

Sui 曼谷 Hacker House 报名开启 Sui Bangkok Hacker House 将在曼谷于 2024 年 11 月 4 日至 17 日举办。诚邀开发者深入学习 Move 语言,在 Sui 网络上构建 MVP ,在充满活力的曼谷中度过难忘的两周。 诚挚地邀请开发者加入为期两周的 Sui Bangkok Hacker House。 你将与其他…

构建全景式智慧文旅生态:EasyCVR视频汇聚平台与AR/VR技术的深度融合实践

在科技日新月异的今天&#xff0c;AR&#xff08;增强现实&#xff09;和VR&#xff08;虚拟现实&#xff09;技术正以前所未有的速度改变着我们的生活方式和工作模式。而EasyCVR视频汇聚平台&#xff0c;作为一款基于云-边-端一体化架构的视频融合AI智能分析平台&#xff0c;可…

Docker数据卷创建、挂载、删除、数据共享

在创建 docker 的镜像和容器后&#xff0c;还需要对容器进行数据管理&#xff0c;以便能与主机、不同容器之间进行交换数据。 本文主要介绍如何通过数据卷的方式实现多个容器间的数据共享和交换。 了解docker数据卷 docker 数据卷&#xff08;Data Volume&#xff09;是一个…