第6篇:Python进阶:精通面向对象编程(OOP)

第6篇:面向对象编程(OOP)

目录

  1. 面向对象编程概述
    • 什么是面向对象编程
    • 面向过程与面向对象的区别
  2. 类与对象
    • 类的定义
    • 对象的创建与使用
    • 类的属性与方法
  3. 构造方法与析构方法
    • 构造方法 __init__
    • 析构方法 __del__
  4. 继承
    • 单继承
    • 多继承
    • 方法重写
  5. 多态
    • 多态的概念
    • 实现多态
  6. 封装
    • 公有与私有属性
    • 访问控制
  7. 类方法与静态方法
    • 类方法 @classmethod
    • 静态方法 @staticmethod
  8. 特殊方法
    • __str____repr__
    • __len____getitem__ 等魔法方法
  9. 示例代码
  10. 常见问题及解决方法
  11. 总结

面向对象编程概述

什么是面向对象编程

**面向对象编程(Object-Oriented Programming,简称OOP)**是一种编程范式,基于“对象”这一概念来组织软件设计。对象是数据和操作数据的代码的集合,通过类来定义对象的结构和行为。OOP强调封装、继承和多态等特性,旨在提高代码的重用性和可维护性。

面向过程与面向对象的区别

特性面向过程编程面向对象编程
代码组织基于函数和逻辑流程基于类和对象
数据与功能关系数据和功能分离,数据通过参数传递数据和功能绑定在对象内部
重用性通过函数调用实现代码重用通过继承和组合实现代码重用
可维护性随着程序复杂度增加,维护变得困难通过模块化和封装提高代码的可维护性
实例C语言、Pascal等Python、Java、C++等

类与对象

类的定义

是面向对象编程的核心概念,是创建对象的蓝图或模板。类定义了对象的属性(数据)和方法(功能)。

# 示例:定义一个简单的类
class Dog:
    def __init__(self, name, age):
        self.name = name  # 属性
        self.age = age    # 属性

    def bark(self):       # 方法
        print(f"{self.name} says: Woof!")

对象的创建与使用

对象是类的实例化,拥有类定义的属性和方法。

# 创建对象
my_dog = Dog("Buddy", 3)

# 访问属性
print(my_dog.name)  # 输出: Buddy
print(my_dog.age)   # 输出: 3

# 调用方法
my_dog.bark()        # 输出: Buddy says: Woof!

类的属性与方法

  • 属性:类中定义的变量,用于存储对象的状态。
  • 方法:类中定义的函数,用于描述对象的行为。
class Car:
    # 类属性
    wheels = 4

    def __init__(self, brand, model):
        self.brand = brand  # 实例属性
        self.model = model  # 实例属性

    def drive(self):        # 方法
        print(f"The {self.brand} {self.model} is driving.")
# 创建对象
my_car = Car("Toyota", "Camry")

# 访问类属性
print(Car.wheels)    # 输出: 4

# 访问实例属性
print(my_car.brand)  # 输出: Toyota
print(my_car.model)  # 输出: Camry

# 调用方法
my_car.drive()       # 输出: The Toyota Camry is driving.

构造方法与析构方法

构造方法 __init__

构造方法用于在创建对象时初始化对象的属性。使用 __init__ 方法定义。

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

# 创建对象时自动调用构造方法
person1 = Person("Alice", 30)
print(person1.name)  # 输出: Alice
print(person1.age)   # 输出: 30

析构方法 __del__

析构方法在对象被销毁时调用,用于清理资源。使用 __del__ 方法定义。

class FileHandler:
    def __init__(self, filename):
        self.file = open(filename, 'w')

    def write_data(self, data):
        self.file.write(data)

    def __del__(self):
        self.file.close()
        print("文件已关闭。")

# 创建对象并写入数据
handler = FileHandler("example.txt")
handler.write_data("Hello, World!")

# 删除对象,触发析构方法
del handler  # 输出: 文件已关闭。

注意:由于Python的垃圾回收机制,__del__ 方法的调用时机不确定,建议使用上下文管理器(with 语句)来管理资源。


继承

单继承

继承允许一个类(子类)继承另一个类(父类)的属性和方法,实现代码重用。

class Animal:
    def __init__(self, name):
        self.name = name

    def speak(self):
        pass

class Cat(Animal):
    def speak(self):
        print(f"{self.name} says: Meow!")

# 创建对象
my_cat = Cat("Whiskers")
my_cat.speak()  # 输出: Whiskers says: Meow!

多继承

多继承允许一个子类继承多个父类的属性和方法。

class Flyer:
    def fly(self):
        print("I can fly.")

class Swimmer:
    def swim(self):
        print("I can swim.")

class Duck(Flyer, Swimmer):
    def quack(self):
        print("Quack!")

# 创建对象
donald = Duck()
donald.fly()    # 输出: I can fly.
donald.swim()   # 输出: I can swim.
donald.quack()  # 输出: Quack!

方法重写

方法重写允许子类重新定义父类的方法,以实现特定的行为。

class Vehicle:
    def start_engine(self):
        print("Engine started.")

class ElectricCar(Vehicle):
    def start_engine(self):
        print("Electric motor started silently.")

# 创建对象
car = Vehicle()
car.start_engine()       # 输出: Engine started.

electric_car = ElectricCar()
electric_car.start_engine()  # 输出: Electric motor started silently.

多态

多态的概念

多态指的是相同的接口可以调用不同类型的对象,实现不同的行为。通过继承和方法重写,可以实现多态性。

实现多态

class Shape:
    def draw(self):
        pass

class Circle(Shape):
    def draw(self):
        print("绘制一个圆形。")

class Rectangle(Shape):
    def draw(self):
        print("绘制一个矩形。")

def render(shape):
    shape.draw()

# 创建对象
circle = Circle()
rectangle = Rectangle()

# 调用相同的函数,行为不同
render(circle)     # 输出: 绘制一个圆形。
render(rectangle)  # 输出: 绘制一个矩形。

封装

公有与私有属性

封装是将数据和操作数据的代码绑定在一起,并隐藏内部实现细节。通过定义公有和私有属性,实现数据的保护。

  • 公有属性:可以被类外部访问和修改。
  • 私有属性:通过在属性名前加双下划线 __,实现私有化,只能在类内部访问。
class BankAccount:
    def __init__(self, owner, balance=0):
        self.owner = owner          # 公有属性
        self.__balance = balance    # 私有属性

    def deposit(self, amount):
        if amount > 0:
            self.__balance += amount
            print(f"存入金额:{amount},当前余额:{self.__balance}")
        else:
            print("存入金额必须大于零。")

    def withdraw(self, amount):
        if 0 < amount <= self.__balance:
            self.__balance -= amount
            print(f"取出金额:{amount},当前余额:{self.__balance}")
        else:
            print("取款金额无效或余额不足。")

    def get_balance(self):
        return self.__balance

# 创建对象
account = BankAccount("Bob", 1000)
print(account.owner)       # 输出: Bob
# print(account.__balance) # AttributeError: 'BankAccount' object has no attribute '__balance'

# 使用方法访问私有属性
account.deposit(500)       # 输出: 存入金额:500,当前余额:1500
account.withdraw(200)      # 输出: 取出金额:200,当前余额:1300
print(account.get_balance())  # 输出: 1300

访问控制

通过使用公有、受保护(单下划线 _)和私有(双下划线 __)属性,控制对类内部数据的访问。

class Example:
    public_attr = "公有属性"
    _protected_attr = "受保护属性"
    __private_attr = "私有属性"

    def __init__(self):
        self.public_attr = "实例公有属性"
        self._protected_attr = "实例受保护属性"
        self.__private_attr = "实例私有属性"

# 创建对象
obj = Example()

# 访问公有属性
print(obj.public_attr)          # 输出: 实例公有属性

# 访问受保护属性(约定俗成,不建议外部访问)
print(obj._protected_attr)      # 输出: 实例受保护属性

# 访问私有属性(不允许,需通过方法访问)
# print(obj.__private_attr)     # AttributeError

# 通过名称改写访问私有属性
print(obj._Example__private_attr)  # 输出: 实例私有属性

注意:私有属性虽然可以通过名称改写访问,但这违背了封装的原则,不推荐这样做。


类方法与静态方法

类方法 @classmethod

类方法绑定到类而非实例,使用 @classmethod 装饰器定义。第一个参数通常命名为 cls,表示类本身。

class Employee:
    raise_amount = 1.05  # 类属性

    def __init__(self, name, salary):
        self.name = name
        self.salary = salary

    @classmethod
    def set_raise_amount(cls, amount):
        cls.raise_amount = amount

    def apply_raise(self):
        self.salary = int(self.salary * self.raise_amount)

# 使用类方法修改类属性
Employee.set_raise_amount(1.10)

# 创建对象
emp1 = Employee("Alice", 50000)
emp2 = Employee("Bob", 60000)

emp1.apply_raise()
emp2.apply_raise()

print(emp1.salary)  # 输出: 55000
print(emp2.salary)  # 输出: 66000

静态方法 @staticmethod

静态方法不绑定到类或实例,使用 @staticmethod 装饰器定义。它们不接收 selfcls 参数,适用于与类相关但不依赖于类或实例状态的功能。

class MathUtils:
    @staticmethod
    def add(a, b):
        return a + b

    @staticmethod
    def multiply(a, b):
        return a * b

# 调用静态方法
result1 = MathUtils.add(5, 3)
result2 = MathUtils.multiply(4, 2)

print(result1)  # 输出: 8
print(result2)  # 输出: 8

特殊方法

__str____repr__

__str____repr__ 是用于定义对象的字符串表示的方法。

  • __str__:用于定义 print() 函数和 str() 函数的输出。
  • __repr__:用于定义对象的官方字符串表示,主要用于调试。
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __str__(self):
        return f"Point({self.x}, {self.y})"

    def __repr__(self):
        return f"Point(x={self.x}, y={self.y})"

# 创建对象
p = Point(2, 3)

# 使用print()调用__str__
print(p)            # 输出: Point(2, 3)

# 使用repr()
print(repr(p))      # 输出: Point(x=2, y=3)

__len____getitem__ 等魔法方法

魔法方法(Magic Methods)允许自定义对象的行为,使其支持内置函数和运算符。

class CustomList:
    def __init__(self, items):
        self.items = items

    def __len__(self):
        return len(self.items)

    def __getitem__(self, index):
        return self.items[index]

    def __setitem__(self, index, value):
        self.items[index] = value

    def __delitem__(self, index):
        del self.items[index]

# 创建对象
clist = CustomList([1, 2, 3, 4])

# 使用len()
print(len(clist))    # 输出: 4

# 使用索引访问
print(clist[2])      # 输出: 3

# 修改元素
clist[1] = 20
print(clist.items)   # 输出: [1, 20, 3, 4]

# 删除元素
del clist[3]
print(clist.items)   # 输出: [1, 20, 3]

示例代码

以下示例展示了如何使用面向对象编程创建一个简单的图书管理系统。

项目结构

library/
    __init__.py
    book.py
    member.py
    library.py
main.py

library/book.py

# library/book.py

class Book:
    def __init__(self, title, author, isbn):
        self.title = title
        self.author = author
        self.isbn = isbn
        self.is_checked_out = False

    def check_out(self):
        if not self.is_checked_out:
            self.is_checked_out = True
            print(f"《{self.title}》已被借出。")
        else:
            print(f"《{self.title}》目前不可借。")

    def return_book(self):
        if self.is_checked_out:
            self.is_checked_out = False
            print(f"《{self.title}》已被归还。")
        else:
            print(f"《{self.title}》未被借出。")

    def __str__(self):
        status = "已借出" if self.is_checked_out else "可借"
        return f"《{self.title}》 by {self.author} (ISBN: {self.isbn}) - {status}"

library/member.py

# library/member.py

class Member:
    def __init__(self, name, member_id):
        self.name = name
        self.member_id = member_id
        self.borrowed_books = []

    def borrow_book(self, book):
        if not book.is_checked_out:
            book.check_out()
            self.borrowed_books.append(book)
            print(f"{self.name} 已借阅《{book.title}》。")
        else:
            print(f"《{book.title}》目前不可借。")

    def return_book(self, book):
        if book in self.borrowed_books:
            book.return_book()
            self.borrowed_books.remove(book)
            print(f"{self.name} 已归还《{book.title}》。")
        else:
            print(f"{self.name} 未借阅《{book.title}》。")

    def __str__(self):
        return f"会员:{self.name} (ID: {self.member_id}) - 借阅书籍:{len(self.borrowed_books)}"

library/library.py

# library/library.py

from library.book import Book
from library.member import Member

class Library:
    def __init__(self):
        self.books = []
        self.members = []

    def add_book(self, title, author, isbn):
        new_book = Book(title, author, isbn)
        self.books.append(new_book)
        print(f"已添加《{title}》到图书馆。")

    def add_member(self, name, member_id):
        new_member = Member(name, member_id)
        self.members.append(new_member)
        print(f"已注册会员:{name} (ID: {member_id})。")

    def find_book_by_title(self, title):
        for book in self.books:
            if book.title == title:
                return book
        return None

    def find_member_by_id(self, member_id):
        for member in self.members:
            if member.member_id == member_id:
                return member
        return None

    def display_books(self):
        print("图书馆藏书:")
        for book in self.books:
            print(book)

    def display_members(self):
        print("图书馆会员:")
        for member in self.members:
            print(member)

main.py

# main.py

from library.library import Library

def main():
    # 创建图书馆实例
    library = Library()

    # 添加书籍
    library.add_book("Python编程入门", "张三", "1234567890")
    library.add_book("数据科学与大数据分析", "李四", "0987654321")

    # 添加会员
    library.add_member("Alice", "M001")
    library.add_member("Bob", "M002")

    # 显示书籍和会员
    library.display_books()
    library.display_members()

    # Alice借阅《Python编程入门》
    alice = library.find_member_by_id("M001")
    book = library.find_book_by_title("Python编程入门")
    if alice and book:
        alice.borrow_book(book)

    # Bob尝试借阅已被借出的书
    bob = library.find_member_by_id("M002")
    if bob and book:
        bob.borrow_book(book)

    # Alice归还书籍
    if alice and book:
        alice.return_book(book)

    # Bob再次尝试借阅
    if bob and book:
        bob.borrow_book(book)

    # 显示最终状态
    library.display_books()
    library.display_members()

if __name__ == "__main__":
    main()

运行结果

已添加《Python编程入门》到图书馆。
已添加《数据科学与大数据分析》到图书馆。
已注册会员:Alice (ID: M001)。
已注册会员:Bob (ID: M002)。
图书馆藏书:
《Python编程入门》 by 张三 (ISBN: 1234567890) - 可借
《数据科学与大数据分析》 by 李四 (ISBN: 0987654321) - 可借
图书馆会员:
会员:Alice (ID: M001) - 借阅书籍:0
会员:Bob (ID: M002) - 借阅书籍:0
《Python编程入门》已被借出。
Alice 已借阅《Python编程入门》。
《Python编程入门》目前不可借。
Alice 已归还《Python编程入门》。
《Python编程入门》已被借出。
Bob 已借阅《Python编程入门》。
图书馆藏书:
《Python编程入门》 by 张三 (ISBN: 1234567890) - 已借出
《数据科学与大数据分析》 by 李四 (ISBN: 0987654321) - 可借
图书馆会员:
会员:Alice (ID: M001) - 借阅书籍:0
会员:Bob (ID: M002) - 借阅书籍:1

常见问题及解决方法

问题1:self 参数的作用是什么?

原因:在类的方法中,第一个参数通常命名为 self,用于引用对象本身,访问对象的属性和方法。

解决方法:确保在定义类的方法时,正确使用 self 作为第一个参数,并在调用时不需要显式传递。

class Example:
    def __init__(self, value):
        self.value = value

    def display(self):
        print(self.value)

# 创建对象
obj = Example(10)
obj.display()  # 输出: 10

问题2:如何实现私有属性的访问和修改?

原因:私有属性通过双下划线 __ 定义,不能直接从类外部访问或修改。

解决方法:通过类的方法(如getter和setter)来访问和修改私有属性。

class Person:
    def __init__(self, name):
        self.__name = name  # 私有属性

    def get_name(self):
        return self.__name

    def set_name(self, new_name):
        self.__name = new_name

# 创建对象
person = Person("Alice")

# 通过方法访问和修改私有属性
print(person.get_name())  # 输出: Alice
person.set_name("Bob")
print(person.get_name())  # 输出: Bob

问题3:如何避免多重继承中的钻石问题?

原因:多重继承可能导致继承层次复杂,出现钻石继承问题,导致方法解析顺序(MRO)混乱。

解决方法

  • 使用组合(Composition)代替多重继承。
  • 明确继承顺序,理解Python的MRO(C3线性化)。
  • 尽量简化类的继承关系。
class A:
    def method(self):
        print("A.method")

class B(A):
    def method(self):
        print("B.method")
        super().method()

class C(A):
    def method(self):
        print("C.method")
        super().method()

class D(B, C):
    def method(self):
        print("D.method")
        super().method()

# 创建对象
d = D()
d.method()

# 输出:
# D.method
# B.method
# C.method
# A.method

解释:Python按照MRO顺序调用方法,避免了重复调用。

问题4:如何使用装饰器增强类的方法?

原因:装饰器可以在不修改原方法代码的情况下,增强方法的功能,如日志记录、权限检查等。

解决方法:定义装饰器函数,并将其应用于类的方法。

def log_decorator(func):
    def wrapper(*args, **kwargs):
        print(f"调用方法: {func.__name__}")
        return func(*args, **kwargs)
    return wrapper

class Calculator:
    @log_decorator
    def add(self, a, b):
        return a + b

    @log_decorator
    def multiply(self, a, b):
        return a * b

# 创建对象
calc = Calculator()
result1 = calc.add(5, 3)       # 输出: 调用方法: add
print(result1)                 # 输出: 8

result2 = calc.multiply(4, 2)  # 输出: 调用方法: multiply
print(result2)                 # 输出: 8

总结

在本篇文章中,我们深入探讨了Python中的面向对象编程(OOP)概念。通过理解类与对象、继承、多态、封装等核心特性,您可以编写更加结构化、可维护和可扩展的代码。面向对象编程不仅提升了代码的组织性,还促进了代码的重用性和灵活性。

学习建议

  1. 实践编写类与对象:尝试创建不同的类,定义属性和方法,掌握面向对象编程的基本技巧。
  2. 应用继承与多态:通过继承和方法重写,实现代码的重用和灵活扩展,理解多态的应用场景。
  3. 理解封装与访问控制:掌握公有、受保护和私有属性的使用,保护类的内部数据。
  4. 探索高级特性:学习类方法、静态方法和装饰器等高级特性,提升代码的功能性和可读性。
  5. 阅读和分析代码:阅读开源项目中的类和对象设计,学习优秀的面向对象编程实践。

接下来的系列文章将继续深入探讨Python的异常处理与文件操作,帮助您进一步掌握Python编程的核心概念和技巧。保持学习的热情,持续实践,您将逐步成为一名优秀的Python开发者!


如果您有任何问题或需要进一步的帮助,请随时在评论区留言或联系相关技术社区。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

keepalived双机热备(LVS+keepalived)实验笔记

目录 前提准备&#xff1a; keepalived1&#xff1a; keepalived2&#xff1a; web1&#xff1a; web2&#xff1a; keepalived介绍 功能特点 工作原理 应用场景 前提准备&#xff1a; 准备4台centos&#xff0c;其中两台为keepalived&#xff0c;两台为webkeepalive…

【Linux】12.Linux进程概念(1)

文章目录 1. 冯诺依曼体系结构2. 操作系统(Operator System)概念设计OS的目的胆小的操作系统定位如何理解 "管理"总结 3. 进程基本概念task_struct-PCB的一种task_ struct内容分类组织进程查看进程通过系统调用获取进程标示符通过系统调用创建进程-fork初识 1. 冯诺依…

LabVIEW 程序中的 R6025 错误

R6025错误 通常是 运行时库 错误&#xff0c;特别是与 C 运行时库 相关。这种错误通常会在程序运行时出现&#xff0c;尤其是在使用 C 编译的程序或依赖 C 运行时库的程序时。 ​ 可能的原因&#xff1a; 内存访问冲突&#xff1a; R6025 错误通常是由于程序在运行时访问无效内…

03JavaWeb——Ajax-Vue-Element(项目实战)

1 Ajax 1.1 Ajax介绍 1.1.1 Ajax概述 我们前端页面中的数据&#xff0c;如下图所示的表格中的学生信息&#xff0c;应该来自于后台&#xff0c;那么我们的后台和前端是互不影响的2个程序&#xff0c;那么我们前端应该如何从后台获取数据呢&#xff1f;因为是2个程序&#xf…

2024 京东零售技术年度总结

每一次回望&#xff0c;都为了更好地前行。 2024 年&#xff0c;京东零售技术在全面助力业务发展的同时&#xff0c;在大模型应用、智能供应链、端技术、XR 体验等多个方向深入探索。京东 APP 完成阶段性重要改版&#xff0c;打造“又好又便宜”的优质体验&#xff1b;国补专区…

Apache搭建https服务器

Apache搭建https服务器 REF: 使用OpenSSL自建一个HTTPS服务

XML在线格式化 - 加菲工具

XML在线格式化 打开网站 加菲工具 选择“XML 在线格式化” 输入XML&#xff0c;点击左上角的“格式化”按钮 得到格式化后的结果

BO-SVM贝叶斯算法优化支持向量机的数据多变量时间序列预测

BO-SVM贝叶斯算法优化支持向量机的数据多变量时间序列预测 目录 BO-SVM贝叶斯算法优化支持向量机的数据多变量时间序列预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab基于BO-SVR贝叶斯算法优化支持向量机的数据多变量时间序列预测&#xff0c;加入5折交叉验…

flutter R库对图片资源进行自动管理

项目中对资源的使用是开发过程中再常见不过的一环。 一般我们在将资源导入到项目中后,会通过资源名称来访问。 但在很多情况下由于我们疏忽输入错了资源名称,从而导致资源无法访问。 所以,急需解决两个问题: 资源编译期可检查可方便预览资源安装相关插件 在vscode中安装两…

【鱼皮大佬API开放平台项目】Spring Cloud Gateway HTTPS 配置问题解决方案总结

问题背景 项目架构为前后端分离的微服务架构&#xff1a; 前端部署在 8000 端口API 网关部署在 9000 端口后端服务包括&#xff1a; api-backend (9001端口)api-interface (9002端口) 初始状态&#xff1a; 前端已配置 HTTPS&#xff08;端口 8000&#xff09;后端服务未配…

Windows远程桌面网关出现重大漏洞

微软披露了其Windows远程桌面网关&#xff08;RD Gateway&#xff09;中的一个重大漏洞&#xff0c;该漏洞可能允许攻击者利用竞争条件&#xff0c;导致拒绝服务&#xff08;DoS&#xff09;攻击。该漏洞被标识为CVE-2025-21225&#xff0c;已在2025年1月的补丁星期二更新中得到…

‌如何有效学习PyTorch:从基础到实践的全面指南‌

随着人工智能和深度学习技术的飞速发展&#xff0c;PyTorch作为当前最流行的深度学习框架之一&#xff0c;凭借其动态计算图、灵活的编程模型以及强大的社区支持&#xff0c;在学术界和工业界均得到了广泛应用。本文旨在为初学者和有一定基础的读者提供一套系统、全面的PyTorch…

2Spark Core

2Spark Core 1.RDD 详解1) 为什么要有 RDD?2) RDD 是什么?3) RDD 主要属性 2.RDD-API1) RDD 的创建方式2) RDD 的算子分类3) Transformation 转换算子4) Action 动作算子 3. RDD 的持久化/缓存4. RDD 容错机制 Checkpoint5. RDD 依赖关系1) 宽窄依赖2) 为什么要设计宽窄依赖 …

视频超分(VSR)论文阅读记录/idea积累(一)

STAR: Spatial-Temporal Augmentation with Text-to-Video Models for Real-World Video Super-Resolution 关键词: text-to-video (T2V) Local Information Enhancement Module (LIEM) Dynamic Frequency (DF) 引言: VSR: 传统VSR分两大类recurrent-based和sliding-wind…

MySQL8数据库全攻略:版本特性、下载、安装、卸载与管理工具详解

大家好&#xff0c;我是袁庭新。 MySQL作为企业项目中的主流数据库&#xff0c;其5.x和8.x版本尤为常用。本文将详细介绍MySQL 8.x的特性、下载、安装、服务管理、卸载及管理工具&#xff0c;旨在帮助用户更好地掌握和使用MySQL数据库。 1.MySQL版本及下载 企业项目中使用的…

Docker安装PostGreSQL docker安装PostGreSQL 完整详细教程

Docker安装PostGreSQL docker安装PostGreSQL 完整详细教程 Docker常用命令大全Docker 运行命令生成Docker 上安装 PostGreSQL 14.15 的步骤&#xff1a;1、拉取 PostGreSQL 14.15 镜像2、创建并运行容器3、测试连接4、设置所有IP都可以运行连接进入容器内 修改配置文件关闭容器…

Elasticsearch:Jira 连接器教程第一部分

作者&#xff1a;来自 Elastic Gustavo Llermaly 将我们的 Jira 内容索引到 Elaasticsearch 中以创建统一的数据源并使用文档级别安全性进行搜索。 在本文中&#xff0c;我们将回顾 Elastic Jira 原生连接器的一个用例。我们将使用一个模拟项目&#xff0c;其中一家银行正在开发…

Spring 6 第1章——概述

一.Spring是什么 Spring是一款主流的Java EE轻量级&#xff08;体积小、不需要依赖其它组件&#xff09;开源框架Spring的目的是用于简化Java企业级应用的开发难度和开发周期Spring的用途不仅限于服务端的开发&#xff0c;从简单性、可测试性和松耦合的角度而言&#xff0c;任…

git管理源码之git安装和使用

git是什么&#xff1f; git是一个开源的分布式版本控制系统&#xff0c;可以有效、高速地处理从很小到非常大的项目版本管理&#xff0c;也是Linus Torvalds为了帮助管理Linux内核开发而开发的一个开放源码的版本控制软件。git与常用的版本控制工具SVN等不同&#xff0c;它采用…

大疆最新款无人机发布,可照亮百米之外目标

近日&#xff0c;DJI 大疆发布全新小型智能多光旗舰 DJI Matrice 4 系列&#xff0c;包含 Matrice 4T 和 Matrice 4E 两款机型。DJI Matrice 4E 价格为27888 元起&#xff0c;DJI Matrice 4T价格为38888元起。 图片来源&#xff1a;大疆官网 DJI Matrice 4E DJI Matrice 4T D…