Python的类全面系统学习
文章目录
- 1. 基本概念
- 1.1 类(Class)
- 1.2 对象(Object)
- 2. 类的属性和方法
- 3. 类的继承
- 3.1 继承的概念
- 3.2 单继承
- 3.3 多重继承
- 4. 方法重写与多态
- 4.1 方法重写
- 4.2 多态
- 5. 特殊方法与运算符重载
- 5.1 特殊方法(魔法方法)
- 5.1.1 `__init__` 方法
- 5.1.2 `__str__` 方法
- 5.1.3 `__repr__` 方法
- 5.1.4 `__len__` 方法
- 5.1.5 `__eq__` 方法
- 5.2 运算符重载
- 6. 静态方法与类方法
- 6.1 静态方法
- 6.2 类方法
- 6.3 静态方法与类方法的对比
- 7. 属性装饰器
- 7.1 定义只读属性
- 7.2 定义可读写属性
- 7.3 只读属性与可读写属性对比
- 8. 面向对象设计原则与模式
- 8.1 设计的五大基本原则
- 8.1.1 单一职责原则(Single Responsibility Principle,SRP)
- 8.1.2 开放封闭原则(Open/Closed Principle,OCP)
- 8.1.3 里氏替换原则(Liskov Substitution Principle,LSP)
- 8.1.4 接口隔离原则(Interface Segregation Principle,ISP)
- 8.1.5 依赖倒置原则(Dependency Inversion Principle,DIP)
- 8.2 设计模式
- 8.2.1 单例模式(Singleton Pattern)
- 8.2.2 工厂模式(Factory Pattern)
- 8.2.3 观察者模式(Observer Pattern)
1. 基本概念
在Python编程中,对象(Object)和类(Class)是面向对象编程(OOP)的核心概念。理解这两个概念有助于我们更好地组织代码,并提高代码的可重用性和可维护性。
1.1 类(Class)
类是一个模板或蓝图,用于定义对象的属性和行为。类定义了一组属性和方法,这些属性和方法是对象所共有的。可以将类看作是一种数据类型,就像字符串、整数等内置数据类型一样,但类是由用户定义的。
- 定义一个类
在Python中,使用class关键字来定义一个类。类的名称通常采用大写字母开头的驼峰命名法。
class Dog:pass # 使用pass语句创建一个空类
上面的代码定义了一个名为Dog的类,但这个类目前没有任何属性或方法。
1.2 对象(Object)
对象是类的实例。一个类可以有多个实例,每个实例都有独立的属性。对象是类的具体体现,通过类创建的对象可以使用类定义的属性和方法。
- 创建一个对象
my_dog = Dog() # 创建Dog类的一个实例
在上面的代码中,my_dog是Dog类的一个实例(对象)。
2. 类的属性和方法
类可以包含属性(数据)和方法(函数)。属性是类的变量,用于存储对象的状态,而方法是类的函数,用于定义对象的行为。
- 定义类的属性和方法
class Dog:# 类的属性species = "Canis familiaris"# 初始化方法,用于初始化实例的属性def __init__(self, name, age):self.name = name # 实例属性self.age = age# 类的方法def bark(self):return f"{self.name} says woof!"# 创建一个Dog类的实例
my_dog = Dog("Buddy", 3)# 访问实例属性
print(my_dog.name) # 输出: Buddy
print(my_dog.age) # 输出: 3# 调用实例方法
print(my_dog.bark()) # 输出: Buddy says woof!# 访问类属性
print(Dog.species) # 输出: Canis familiaris
在这个示例中:
species是一个类属性,所有Dog类的实例共享这个属性。name和age是实例属性,每个实例都有独立的这些属性。__init__方法是初始化方法,在创建实例时被调用,用于初始化实例的属性。bark是一个实例方法,可以通过实例来调用。
3. 类的继承
3.1 继承的概念
继承是面向对象编程的一个重要特性,它允许一个类(子类或派生类)继承另一个类(父类或基类)的属性和方法。通过继承,子类可以重用父类的代码,同时可以扩展或修改父类的行为。
继承的主要优点包括:
- 代码重用:子类可以直接使用父类中已经定义的属性和方法,避免重复代码。
- 扩展功能:子类可以增加新的属性和方法,扩展父类的功能。
- 多态性:子类可以重写父类的方法,提供特定的实现。
3.2 单继承
在Python中,单继承指的是一个子类继承一个父类。子类可以通过在类定义中指定父类的方式来继承父类。
示例:定义一个父类和一个子类
# 定义一个父类
class Animal:def __init__(self, name):self.name = namedef speak(self):return f"{self.name} makes a sound."# 定义一个子类,继承自Animal类
class Dog(Animal):def speak(self):return f"{self.name} says woof!"# 创建父类和子类的实例
generic_animal = Animal("Animal")
dog = Dog("Buddy")# 调用方法
print(generic_animal.speak()) # 输出: Animal makes a sound.
print(dog.speak()) # 输出: Buddy says woof!
在这个示例中:
Animal是父类,定义了__init__方法和speak方法。Dog是子类,通过在类定义中括号内指定父类Animal来实现继承。- 子类
Dog重写了父类的speak方法。
3.3 多重继承
多重继承指的是一个子类可以继承多个父类。Python支持多重继承,但需要谨慎使用,因为它可能导致复杂的继承关系和潜在的冲突。
- 示例:多重继承
# 定义两个父类
class Canine:def __init__(self):self.has_tail = Truedef wag_tail(self):return "Wagging tail."class Pet:def __init__(self, name):self.name = namedef play(self):return f"{self.name} is playing."# 定义一个子类,继承自Canine和Pet
class Dog(Canine, Pet):def __init__(self, name):Canine.__init__(self)Pet.__init__(self, name)# 创建子类的实例
dog = Dog("Buddy")# 访问继承的属性和方法
print(dog.has_tail) # 输出: True
print(dog.wag_tail()) # 输出: Wagging tail.
print(dog.play()) # 输出: Buddy is playing.
在这个示例中:
Canine和Pet是两个父类。Dog是一个子类,通过在类定义中括号内指定多个父类实现多重继承。- 子类
Dog在其构造函数中显式调用了两个父类的构造函数,以初始化父类的属性。
4. 方法重写与多态
4.1 方法重写
方法重写(Method Overriding)是指在子类中定义一个与父类具有相同名称的方法,从而取代父类中的方法实现。当子类的实例调用这个方法时,将执行子类中的版本,而不是父类中的版本。
- 示例:方法重写
# 定义父类
class Animal:def speak(self):return "Animal makes a sound."# 定义子类,重写父类的方法
class Dog(Animal):def speak(self):return "Dog says woof!"# 创建父类和子类的实例
generic_animal = Animal()
dog = Dog()# 调用方法
print(generic_animal.speak()) # 输出: Animal makes a sound.
print(dog.speak()) # 输出: Dog says woof!
在这个示例中:
Animal类定义了一个speak方法。Dog类继承自Animal,并重写了speak方法。- 当调用
dog.speak()时,执行的是Dog类中的speak方法。
4.2 多态
多态(Polymorphism)是一种面向对象编程的特性,允许使用不同的类的对象来调用相同的方法。不同的对象在调用相同的方法时,表现出不同的行为。多态性通常通过继承和方法重写来实现。
- 示例:多态
# 定义父类
class Animal:def speak(self):raise NotImplementedError("Subclass must implement abstract method")# 定义子类
class Dog(Animal):def speak(self):return "Dog says woof!"class Cat(Animal):def speak(self):return "Cat says meow!"# 定义一个函数,接受Animal类型的对象
def make_animal_speak(animal):print(animal.speak())# 创建不同类型的Animal对象
dog = Dog()
cat = Cat()# 调用函数,实现多态
make_animal_speak(dog) # 输出: Dog says woof!
make_animal_speak(cat) # 输出: Cat says meow!
在这个示例中:
Animal类定义了一个抽象的speak方法,要求所有子类实现这个方法。Dog和Cat类分别继承自Animal,并实现了各自的speak方法。make_animal_speak函数接受一个Animal类型的对象,并调用它的speak方法。- 通过传递不同类型的
Animal对象(Dog和Cat),函数调用表现出不同的行为,实现了多态。
多态的优势
-
代码灵活性:可以编写更加灵活和可扩展的代码。
-
代码重用:通过继承和方法重写,可以减少代码重复,提高代码重用性。
-
接口一致性:多态性使得可以使用统一的接口来处理不同类型的对象,简化代码。
-
示例:多态在实际应用中的使用
# 定义基类
class Shape:def area(self):raise NotImplementedError("Subclass must implement abstract method")# 定义子类
class Circle(Shape):def __init__(self, radius):self.radius = radiusdef area(self):return 3.14 * self.radius ** 2class Square(Shape):def __init__(self, side):self.side = sidedef area(self):return self.side ** 2# 定义一个函数,接受Shape类型的对象
def print_area(shape):print(f"The area is {shape.area()}")# 创建不同类型的Shape对象
circle = Circle(5)
square = Square(4)# 调用函数,实现多态
print_area(circle) # 输出: The area is 78.5
print_area(square) # 输出: The area is 16
在这个示例中:
Shape类定义了一个抽象的area方法。Circle和Square类分别继承自Shape,并实现了各自的area方法。print_area函数接受一个Shape类型的对象,并调用它的area方法。- 通过传递不同类型的
Shape对象(Circle和Square),函数调用表现出不同的行为,实现了多态。
5. 特殊方法与运算符重载
5.1 特殊方法(魔法方法)
特殊方法(也称为魔法方法)是Python中具有特殊名称的方法,它们是通过双下划线包围的。特殊方法允许类定义特定的行为,如初始化对象、表示对象、比较对象等。以下是一些常用的特殊方法:
5.1.1 __init__ 方法
__init__ 方法是一个构造函数,在创建对象时自动调用,用于初始化对象的属性。
class Person:def __init__(self, name, age):self.name = nameself.age = agep = Person("Alice", 30)
print(p.name) # 输出: Alice
print(p.age) # 输出: 30
5.1.2 __str__ 方法
__str__ 方法定义了对象的字符串表示,在使用 print 函数或 str() 函数时调用。
class Person:def __init__(self, name, age):self.name = nameself.age = agedef __str__(self):return f"Person(name={self.name}, age={self.age})"p = Person("Alice", 30)
print(p) # 输出: Person(name=Alice, age=30)
5.1.3 __repr__ 方法
__repr__ 方法定义了对象的官方字符串表示,通常用于调试。在使用 repr() 函数或交互解释器中直接输入对象时调用。
class Person:def __init__(self, name, age):self.name = nameself.age = agedef __repr__(self):return f"Person(name={self.name}, age={self.age})"p = Person("Alice", 30)
print(repr(p)) # 输出: Person(name=Alice, age=30)
5.1.4 __len__ 方法
__len__ 方法定义了对象的长度,在使用 len() 函数时调用。
class MyList:def __init__(self, data):self.data = datadef __len__(self):return len(self.data)my_list = MyList([1, 2, 3, 4])
print(len(my_list)) # 输出: 4
5.1.5 __eq__ 方法
__eq__ 方法定义了对象的相等性比较,在使用 == 运算符时调用。
class Person:def __init__(self, name, age):self.name = nameself.age = agedef __eq__(self, other):if isinstance(other, Person):return self.name == other.name and self.age == other.agereturn Falsep1 = Person("Alice", 30)
p2 = Person("Alice", 30)
p3 = Person("Bob", 25)print(p1 == p2) # 输出: True
print(p1 == p3) # 输出: False
5.2 运算符重载
运算符重载(Operator Overloading)允许我们定义或重定义类的运算符行为。通过重载运算符,可以实现自定义的运算符行为,使类的实例能够参与各种运算。
- 示例:重载加法运算符 (
+)
class Vector:def __init__(self, x, y):self.x = xself.y = ydef __add__(self, other):if isinstance(other, Vector):return Vector(self.x + other.x, self.y + other.y)return NotImplementeddef __repr__(self):return f"Vector({self.x}, {self.y})"v1 = Vector(2, 3)
v2 = Vector(5, 7)
v3 = v1 + v2print(v3) # 输出: Vector(7, 10)
在这个示例中:
-
__add__方法重载了加法运算符,使得两个Vector对象可以相加。 -
__repr__方法用于提供对象的字符串表示,便于调试和打印输出。 -
示例:重载其他运算符
除了加法运算符 (+),我们还可以重载其他运算符,如减法运算符 (-)、乘法运算符 (*)、除法运算符 (/)、比较运算符 (<, >, <=, >=) 等。
class Vector:def __init__(self, x, y):self.x = xself.y = ydef __sub__(self, other):if isinstance(other, Vector):return Vector(self.x - other.x, self.y - other.y)return NotImplementeddef __mul__(self, scalar):if isinstance(scalar, (int, float)):return Vector(self.x * scalar, self.y * scalar)return NotImplementeddef __lt__(self, other):if isinstance(other, Vector):return (self.x**2 + self.y**2) < (other.x**2 + other.y**2)return NotImplementeddef __repr__(self):return f"Vector({self.x}, {self.y})"v1 = Vector(2, 3)
v2 = Vector(5, 7)print(v1 - v2) # 输出: Vector(-3, -4)
print(v1 * 3) # 输出: Vector(6, 9)
print(v1 < v2) # 输出: True
在这个示例中:
__sub__方法重载了减法运算符 (-),使得两个Vector对象可以相减。__mul__方法重载了乘法运算符 (*),使得Vector对象可以与标量相乘。__lt__方法重载了小于运算符 (<),使得可以比较两个Vector对象的大小。
6. 静态方法与类方法
6.1 静态方法
静态方法是类中定义的方法,但它不依赖于类的实例或类本身的属性。它类似于普通函数,只是定义在类的命名空间中。静态方法可以通过类名直接调用,也可以通过类的实例调用。通常用于定义逻辑上属于类但不需要访问类或实例属性的方法。
- 定义和使用静态方法
在Python中,使用@staticmethod装饰器定义静态方法。
class MathOperations:@staticmethoddef add(a, b):return a + b@staticmethoddef multiply(a, b):return a * b# 通过类名调用静态方法
print(MathOperations.add(3, 5)) # 输出: 8
print(MathOperations.multiply(3, 5)) # 输出: 15# 通过实例调用静态方法
math_ops = MathOperations()
print(math_ops.add(10, 20)) # 输出: 30
print(math_ops.multiply(10, 20)) # 输出: 200
在这个示例中:
add和multiply是静态方法,不访问类的任何属性或实例属性。- 静态方法可以通过类名或类的实例调用。
6.2 类方法
类方法是类中定义的方法,使用@classmethod装饰器定义。类方法的第一个参数是类本身,通常命名为cls。类方法可以访问类属性和调用其他类方法,但不能直接访问实例属性。
- 定义和使用类方法
在Python中,使用@classmethod装饰器定义类方法。
class Person:population = 0 # 类属性def __init__(self, name):self.name = namePerson.population += 1@classmethoddef get_population(cls):return cls.population@classmethoddef create_person(cls, name):return cls(name)# 创建实例
p1 = Person("Alice")
p2 = Person("Bob")# 通过类名调用类方法
print(Person.get_population()) # 输出: 2# 使用类方法创建实例
p3 = Person.create_person("Charlie")
print(p3.name) # 输出: Charlie# 再次调用类方法获取更新后的人口数量
print(Person.get_population()) # 输出: 3
在这个示例中:
get_population是一个类方法,返回当前人口数量(类属性population)。create_person是一个类方法,用于创建新的Person实例。- 类方法可以通过类名或类的实例调用。
6.3 静态方法与类方法的对比
| 特性 | 静态方法 | 类方法 |
|---|---|---|
| 定义装饰器 | @staticmethod | @classmethod |
| 第一个参数 | 无特殊参数 | cls(指向类本身) |
| 访问类属性 | 不能 | 可以 |
| 访问实例属性 | 不能 | 不能 |
| 调用方式 | 通过类名或实例调用 | 通过类名或实例调用 |
静态方法和类方法各有用途,选择使用哪种方法取决于具体需求:
- 使用静态方法来定义与类关联的函数,但不需要访问类或实例属性。
- 使用类方法来操作类属性或调用其他类方法。
7. 属性装饰器
属性装饰器@property是Python中一个非常有用的功能,它允许你将类的方法转换为属性,从而实现更简洁和更易读的代码。使用@property装饰器可以定义只读属性和可读写属性。
7.1 定义只读属性
只读属性是指只能获取其值而不能修改其值的属性。通过使用@property装饰器,可以将一个方法定义为只读属性。
- 示例:定义只读属性
class Circle:def __init__(self, radius):self._radius = radius # 保护属性@propertydef radius(self):return self._radius@propertydef area(self):return 3.14 * self._radius ** 2# 创建实例
circle = Circle(5)# 访问只读属性
print(circle.radius) # 输出: 5
print(circle.area) # 输出: 78.5# 尝试修改只读属性会引发错误
# circle.radius = 10 # AttributeError: can't set attribute
在这个示例中:
radius和area属性使用@property装饰器定义为只读属性。- 可以通过实例访问这些属性,但不能修改它们。
7.2 定义可读写属性
要定义可读写属性,需要同时定义getter和setter方法。使用@property装饰器定义getter方法,并使用@<属性名>.setter装饰器定义setter方法。
- 示例:定义可读写属性
class Circle:def __init__(self, radius):self._radius = radius # 保护属性@propertydef radius(self):return self._radius@radius.setterdef radius(self, value):if value > 0:self._radius = valueelse:raise ValueError("Radius must be positive")@propertydef area(self):return 3.14 * self._radius ** 2# 创建实例
circle = Circle(5)# 访问可读写属性
print(circle.radius) # 输出: 5# 修改可读写属性
circle.radius = 10
print(circle.radius) # 输出: 10
print(circle.area) # 输出: 314.0# 尝试设置非法值会引发错误
# circle.radius = -5 # ValueError: Radius must be positive
在这个示例中:
radius属性有getter和setter方法,使用@property和@radius.setter装饰器定义。area属性仍然是只读属性,使用@property装饰器定义。- 通过setter方法,可以对
radius属性进行合法性检查,确保其值为正数。
7.3 只读属性与可读写属性对比
| 特性 | 只读属性 | 可读写属性 |
|---|---|---|
| Getter方法 | 使用@property装饰器定义 | 使用@property装饰器定义 |
| Setter方法 | 不定义Setter方法 | 使用@<属性名>.setter装饰器定义 |
| 可修改性 | 属性值不能被修改 | 属性值可以被修改并可以进行合法性检查 |
| 使用场景 | 属性值一旦设定后不应被改变的情况 | 属性值需要动态调整并可能需要验证的情况 |
通过使用@property装饰器,我们可以将类的方法转换为属性,从而实现更简洁和更易读的代码。属性装饰器不仅提高了代码的可读性,还提供了对属性值的更精细的控制。
8. 面向对象设计原则与模式
8.1 设计的五大基本原则
SOLID原则是面向对象设计的五大基本原则,它们有助于创建更灵活、可维护和可扩展的代码。
8.1.1 单一职责原则(Single Responsibility Principle,SRP)
每个类应该只有一个单一的职责,即一个类只负责一件事情。这使得类更容易理解、维护和修改。
- 示例:
class Report:def __init__(self, data):self.data = datadef generate_report(self):# 生成报告passclass ReportPrinter:def print_report(self, report):# 打印报告pass
在这个示例中,Report类只负责生成报告,而ReportPrinter类负责打印报告。
8.1.2 开放封闭原则(Open/Closed Principle,OCP)
软件实体(类、模块、函数等)应该对扩展开放,对修改封闭。这意味着可以扩展一个类的行为,而无需修改其源代码。
- 示例:
class Shape:def area(self):passclass Rectangle(Shape):def __init__(self, width, height):self.width = widthself.height = heightdef area(self):return self.width * self.heightclass Circle(Shape):def __init__(self, radius):self.radius = radiusdef area(self):return 3.14 * self.radius ** 2
在这个示例中,Shape类可以通过扩展子类来增加新形状,而无需修改现有类的代码。
8.1.3 里氏替换原则(Liskov Substitution Principle,LSP)
子类对象应该可以替换父类对象,并且程序的行为不会改变。这意味着子类必须能够替代父类,且不改变程序的正确性。
- 示例:
class Bird:def fly(self):passclass Sparrow(Bird):def fly(self):return "Sparrow flying"class Ostrich(Bird):def fly(self):raise NotImplementedError("Ostriches cannot fly")def make_bird_fly(bird):print(bird.fly())sparrow = Sparrow()
ostrich = Ostrich()make_bird_fly(sparrow) # 输出: Sparrow flying
make_bird_fly(ostrich) # 抛出NotImplementedError
在这个示例中,Ostrich类违反了里氏替换原则,因为它不能飞翔。
8.1.4 接口隔离原则(Interface Segregation Principle,ISP)
客户端不应该被迫依赖它不使用的方法。应将胖接口拆分为更小、更具体的接口,这样客户端将只需知道它们感兴趣的方法。
- 示例:
class Printer:def print(self):passclass Scanner:def scan(self):passclass MultiFunctionDevice(Printer, Scanner):def print(self):return "Printing..."def scan(self):return "Scanning..."
在这个示例中,Printer和Scanner接口被分离,客户端只需依赖他们需要的方法。
8.1.5 依赖倒置原则(Dependency Inversion Principle,DIP)
高层模块不应该依赖于低层模块,二者都应该依赖于抽象。抽象不应该依赖于细节,细节应该依赖于抽象。
- 示例:
class Database:def save(self, data):passclass MySQLDatabase(Database):def save(self, data):print("Saving data in MySQL database")class User:def __init__(self, database: Database):self.database = databasedef save_user(self, data):self.database.save(data)# 使用依赖注入
db = MySQLDatabase()
user = User(db)
user.save_user("User data")
在这个示例中,高层模块(User类)依赖于抽象(Database接口),而不是具体实现(MySQLDatabase类)。
8.2 设计模式
设计模式是解决常见软件设计问题的典型解决方案。以下是一些常见的设计模式:
8.2.1 单例模式(Singleton Pattern)
单例模式确保一个类只有一个实例,并提供全局访问点。
- 示例:
class Singleton:_instance = Nonedef __new__(cls, *args, **kwargs):if not cls._instance:cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)return cls._instance# 使用单例模式
singleton1 = Singleton()
singleton2 = Singleton()print(singleton1 is singleton2) # 输出: True
8.2.2 工厂模式(Factory Pattern)
工厂模式定义了一个用于创建对象的接口,但由子类决定实例化哪个类。工厂方法让类的实例化推迟到子类。
- 示例:
class Animal:def speak(self):passclass Dog(Animal):def speak(self):return "Woof!"class Cat(Animal):def speak(self):return "Meow!"class AnimalFactory:@staticmethoddef create_animal(animal_type):if animal_type == "dog":return Dog()elif animal_type == "cat":return Cat()else:raise ValueError("Unknown animal type")# 使用工厂模式
dog = AnimalFactory.create_animal("dog")
cat = AnimalFactory.create_animal("cat")print(dog.speak()) # 输出: Woof!
print(cat.speak()) # 输出: Meow!
8.2.3 观察者模式(Observer Pattern)
观察者模式定义对象之间的一对多依赖,使得每当一个对象改变状态时,其所有依赖者都会收到通知并自动更新。
- 示例:
class Observer:def update(self, message):passclass Subject:def __init__(self):self._observers = []def attach(self, observer):self._observers.append(observer)def detach(self, observer):self._observers.remove(observer)def notify(self, message):for observer in self._observers:observer.update(message)class ConcreteObserver(Observer):def update(self, message):print(f"Received message: {message}")# 使用观察者模式
subject = Subject()
observer1 = ConcreteObserver()
observer2 = ConcreteObserver()subject.attach(observer1)
subject.attach(observer2)subject.notify("Observer Pattern in Python")
# 输出:
# Received message: Observer Pattern in Python
# Received message: Observer Pattern in Python
这些设计模式和SOLID原则有助于创建更健壮、可维护和可扩展的代码。通过实践和运用这些概念,你可以提升你的软件设计能力。
相关文章:
Python的类全面系统学习
文章目录 1. 基本概念1.1 类(Class)1.2 对象(Object) 2. 类的属性和方法3. 类的继承3.1 继承的概念3.2 单继承3.3 多重继承 4. 方法重写与多态4.1 方法重写4.2 多态 5. 特殊方法与运算符重载5.1 特殊方法(魔法方法&…...
信号处理中简单实用的方法
最小二乘法拟合消除趋势项 消除趋势项函数 在MATLAB的工具箱中已有消除线性趋势项的detrend函数;再介绍以最小二乘法拟合消除趋势项的polydetrend 函数。 函数:detrend功能:消除线性趋势项 调用格式:ydetrend(x) 说明:输入参数x是带有线性趋势项的信号序列,输出…...
Jeecg | 如何解决 ERR Client sent AUTH, but no password is set 问题
最近在尝试Jeecg低代码开发,但是碰到了超级多的问题,不过总归是成功运行起来了。 下面说说碰到的最后一个配置问题:连接redis失败 Error starting ApplicationContext. To display the conditions report re-run your application with deb…...
数据容器:set(集合) 更新啦!
数据容器:set(集合) 1.集合的定义方式 {元素, 元素, 元素} # 定义集合 my_set {"欣欣向荣", "嘉嘉", "red", "欣欣向荣", "嘉嘉", "red", "欣欣向荣", "嘉嘉…...
算法入门----小话算法(1)
下面就首先从一些数学问题入手。 Q1: 如何证明时间复杂度O(logN) < O(N) < O(NlogN) < O(N2) < O(2N) < O(N!) < O(NN)? A: 如果一个以整数为参数的不等式不能很容易看出不等的关系,那么最好用图示或者数学归纳法。 很显…...
Vue | 自定义组件双向绑定基础用法
Vue | 自定义组件双向绑定基础用法 vue 中,由于单向数据流,常规的父子组件属性更新,需要 在父组件绑定相应属性,再绑定相应事件,事件里去做更新的操作,利用语法糖 可以减少绑定事件的操作。 这里就简单的梳…...
python使用modbustcp协议与PLC进行简单通信
AI应用开发相关目录 本专栏包括AI应用开发相关内容分享,包括不限于AI算法部署实施细节、AI应用后端分析服务相关概念及开发技巧、AI应用后端应用服务相关概念及开发技巧、AI应用前端实现路径及开发技巧 适用于具备一定算法及Python使用基础的人群 AI应用开发流程概…...
mongodb在游戏开发领域的优势
1、分布式id 游戏服务器里的大部分数据都是要求全局唯一的,例如玩家id,道具id。之所以有这种要求,是因为运营业务上需要进行合服操作,保证不同服的数据在进行合服之后,也能保证id不冲突。如果采用关系型数据库&#x…...
大数据Scala教程从入门到精通第十篇:Scala在IDEA中编写Hello World代码的简单说明
一:代码展示 object Main {def main(args: Array[String]): Unit {//SCALA中可以不写;//绿色的小三角达标的是这个类中有一个MAIN方法代表是可以执行的。//ctrl shift f10可以直接运行println("Hello world!")//Java中的类库我们可以直接使用System.o…...
【SPSS】基于因子分析法对水果茶调查问卷进行分析
🤵♂️ 个人主页:艾派森的个人主页 ✍🏻作者简介:Python学习者 🐋 希望大家多多支持,我们一起进步!😄 如果文章对你有帮助的话, 欢迎评论 💬点赞Ǵ…...
ElasticSearch学习篇12_《检索技术核心20讲》基础篇
背景 学习极客实践课程《检索技术核心20讲》https://time.geekbang.org/column/article/215243 课程分为基础篇、进阶篇、系统案例篇 主要记录企业课程学习过程课程大纲关键点,以文档形式记录笔记。 内容 检索技术:它是更底层的通用技术,…...
Reids高频面试题汇总总结
一、Redis基础 Redis是什么? Redis是一个开源的内存数据存储系统,它可以用作数据库、缓存和消息中间件。Redis支持多种数据结构,如字符串、哈希表、列表、集合、有序集合等,并提供了丰富的操作命令来操作这些数据结构。Redis的主要特点是什么? 高性能:Redis将数据存储在内…...
19 - grace数据处理 - 补充 - 地下水储量计算过程分解 - 冰后回弹(GIA)改正
19 - grace数据处理 - 补充 - 地下水储量计算过程分解 - 冰后回弹(GIA)改正 0 引言1 gia数据处理过程0 引言 由水量平衡方程可以将地下水储量的计算过程分解为3个部分,第一部分计算陆地水储量变化、第二部分计算地表水储量变化、第三部分计算冰后回弹改正、第四部分计算地下…...
车载客流统计设备:双目3D还原智能统计算法的应用与优势
随着城市交通的日益繁忙和公共交通系统的不断完善,对公交车等交通工具的客流统计和分析变得越来越重要。传统的客流统计方法往往存在效率低下、精度不足等问题,难以满足现代城市交通管理的需求。而基于双目3D还原智能统计算法的车载客流统计设备…...
U盘无法打开?数据恢复与预防措施全解析
在日常生活和工作中,U盘已成为我们存储和传输数据的重要工具。然而,有时我们会遇到U盘无法打开的情况,这无疑给我们带来了诸多不便。本文将深入探讨U盘打不开的现象、原因及解决方案,并分享如何预防此类问题的发生。 一、U盘无法访…...
apollo版本更新简要概述
apollo版本更新简要概述 Apollo 里程碑版本9.0重要更新Apollo 开源平台 9.0 的主要新特征如下:基于包管理的 PnC 扩展开发范式基于包管理的感知扩展开发范式全新打造的 Dreamview Plus 开发者工具感知模型全面升级,支持增量训练 版本8.0版本6.0 Apollo 里…...
基于心电疾病分类的深度学习模型部署应用于OrangePi Kunpeng Pro开发板
一、开发板资源介绍 该板具有4核心64位的处理器和8TOPS的AI算力,让我们验证一下,在该板上跑深度学习模型的效果如何? 二、配网及远程SSH登录访问系统 在通过microusb连接串口进入开发板调试,在命令行终端执行以下命令 1&#…...
vue中axios的使用
1.get请求 axios.get(http://127.0.0.1:2333/show_course, {params: {param: choice} }) .then((response) > {this.list response.data; }) .catch((error) > {console.error(error); }); 2.post请求:当需要向服务器提交数据以创建新资源时使用。例如&…...
Spark SQL【Java API】
前言 之前对 Spark SQL 的影响一直停留在 DSL 语法上面,感觉可以用 SQL 表达的,没有必要用 Java/Scala 去写,但是面试一段时间后,发现不少公司还是在用 SparkSQL 的,京东也在使用 Spark On Hive 而不是我以为的 Hive O…...
文心智能体平台丨创建你的四六级学习小助手
引言 在人工智能飞速发展的今天,我们迎来了文心智能体平台。该平台集成了最先进的人工智能技术,旨在为用户提供个性化、高效的学习辅助服务。今天,我们将向大家介绍如何利用文心智能体平台,创建一个专属于你的四六级学习小助手。…...
label-studio的使用教程(导入本地路径)
文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...
【力扣数据库知识手册笔记】索引
索引 索引的优缺点 优点1. 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度(创建索引的主要原因)。3. 可以加速表和表之间的连接,实现数据的参考完整性。4. 可以在查询过程中,…...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...
Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...
前端倒计时误差!
提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...
YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...
大数据零基础学习day1之环境准备和大数据初步理解
学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 (1)设置网关 打开VMware虚拟机,点击编辑…...
Mac软件卸载指南,简单易懂!
刚和Adobe分手,它却总在Library里给你写"回忆录"?卸载的Final Cut Pro像电子幽灵般阴魂不散?总是会有残留文件,别慌!这份Mac软件卸载指南,将用最硬核的方式教你"数字分手术"࿰…...
用docker来安装部署freeswitch记录
今天刚才测试一个callcenter的项目,所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...
tree 树组件大数据卡顿问题优化
问题背景 项目中有用到树组件用来做文件目录,但是由于这个树组件的节点越来越多,导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多,导致的浏览器卡顿,这里很明显就需要用到虚拟列表的技术&…...
