Python_面向对象

news2024/11/23 23:36:12

面向对象编程(Object-Oriented Programming,OOP)是一种编程范式,它将数据和操作数据的方法组合在一起,以便将数据和行为视为一个整体。这种编程范式的历程可以追溯到20世纪60年代,但直到80年代才开始流行。

在面向对象编程中,数据和方法被组织成类(Class),类是一种抽象数据类型,它定义了一组属性和方法。对象(Object)是类的一个实例1,它包含了类的属性和方法。通过创建对象,我们可以使用类中定义的方法来操作对象的属性。

Python_面向对象

  • 一、定义和调用
    • 1.1 在Python中,`self`确实是在定义类的方法时必须有的
    • 1.2 属性 + 行为
    • 1.3 构造方法(构造函数)
    • 1.4 魔术方法
  • 二、三大特性
    • 2.1 封装
      • 2.1.1私有的成员
    • 2.2 继承
      • 2.2.1 单继承
      • 2.2.2 多继承 --同名的方法和变量,左到右的优先继承
      • 2.2.3 pass关键字
      • 2.2.4 复写父类成员方法
        • (2)使用父类成员【两种方式】
    • 2.* 类型注解
      • 2.*.1. 变量类型注解:
      • 2.*.2. 函数参数和返回值的类型注解:[ 提示性 ]
      • 2.*.3. 类型注解和容器类型:
        • 注意事项:
      • 2.*.4 Union类型
    • 2.3 多态
    • 2.4 抽象类

类可描述事物,万物皆可是对象。对象具有具体的属性和指定的行为
对象名=类名称()

类是描述了一组有相同特性(属性)和相同行为(方法)的一组对象的集合。
对象或实体所拥有的特征在类中表示时称为类的属性。对象执行的操作称为类的方法。

一、定义和调用

  1. 类的定义:
    class关键字,其中写类的属性和行为
class Student:
  	#类的属性 即:成员变量
	name = None
	Id = None
 
	#类的行为 即:成员方法
	def GoStudy(self)"
	  print(f"{self.name}study")
self作用: 在成员方法内部,要访问成员变量,必须加self,其中的self代表类的实例,而非类.
  类本身包含了类的属性、方法和其他类级别的成员,它定义了一组对象共享的特征和行为

1.1 在Python中,self确实是在定义类的方法时必须有的

尽管在调用时不需要显式传入相应的参数。`self`在类的方法中的作用非常重要。在参数列表中可以忽略掉
  1. 代表实例:self是一个约定俗成的名称,它代表类的实例本身。通过self,你可以在方法内部访问和操作该实例的属性和方法。

  2. (1)访问成员变量:在类的方法中,如果要访问类的成员变量(也称为属性),必须使用self来引用它们。这样Python才知道你要访问的是实例的属性而不是局部变量。
    (2) [ 在类的方法中,要访问类的成员变量(也称为属性),需要使用self关键字来引用它们。 ]

  3. 区分类成员和局部变量:使用self可以帮助区分类成员(属于类的属性和方法)和方法内部的局部变量。这有助于避免命名冲突和混淆。

class MyClass:
    def __init__(self, value):
        self.value = value  # 使用self访问成员变量value

    def print_value(self):
        print(self.value)  # 使用self访问成员变量value

# 创建对象并调用方法
obj = MyClass(42)
obj.print_value()  # 输出: 42

总之,self在Python中扮演着关键的角色,它允许类的方法操作类的实例并访问其属性。因此,虽然不需要在调用方法时显式传入self参数,但在方法定义中必须有self参数来引用实例。

2.创建对象

对象名 = 类的名称()
stu1 = Student()

1.2 属性 + 行为

在Python中,类(Class)是一种蓝图或模板,用于创建对象(Object)。类定义了对象的属性(Attributes)和行为(Methods)。让我解释一下它们之间的概念:

  1. 属性(Attributes):
    • 属性是类中的变量,用于存储对象的数据。这些数据可以是数字、字符串、布尔值等等,取决于对象的特性。
    • 在类中定义属性时,它们通常用于表示对象的状态或特征。
    • 你可以通过在类中使用构造函数(通常是__init__方法)来初始化对象的属性。

示例:

class Person:
    def __init__(self, name, age):
        self.name = name  # 属性1: 名字
        self.age = age    # 属性2: 年龄

# 创建一个Person对象
person1 = Person("Alice", 30)

# 访问对象的属性
print(person1.name)  # 输出: Alice
print(person1.age)   # 输出: 30
  1. 行为(Methods):
    • 行为是类中的函数,用于执行特定的操作或任务。这些函数可以访问和操作对象的属性。
    • 方法定义了对象的行为,通常以对象自身(通常命名为self)作为第一个参数,以便在方法内部访问属性。

示例:

class Dog:
    def __init__(self, name):
        self.name = name
    
    def bark(self):
        print(f"{self.name} is barking!")

# 创建一个Dog对象
dog1 = Dog("Buddy")

# 调用对象的方法
dog1.bark()  # 输出: Buddy is barking!

总之,属性定义了对象的特性和状态,而方法定义了对象的行为。通过使用类,你可以创建具有共同属性和行为的多个对象。

1.3 构造方法(构造函数)

构造方法在Python中通常使用`__init__`方法来定义。

通过构造方法,你可以在创建类的实例时传递参数,并将这些参数用于初始化实例的属性。

在下面的demo中没有提前写成员变量也是可以的,因为Py中可以在构造方法(__init__方法)内部动态地创建并初始化成员变量(实例属性),而不需要提前在类定义中声明它们。

这意味着你可以在构造方法中为对象添加属性,而不必提前在类定义中列出所有可能的属性。这可以根据对象的实际需求来进行,从而使你能够更灵活地使用类。

class Person:
    def __init__(self, name, age):
        self.name = name  # 使用传入的name参数初始化name属性
        self.age = age    # 使用传入的age参数初始化age属性

# 创建Person对象时传递参数
person1 = Person("Alice", 30)
person2 = Person("Bob", 25)

# 访问对象的属性
print(person1.name)  # 输出: Alice
print(person1.age)   # 输出: 30

print(person2.name)  # 输出: Bob
print(person2.age)   # 输出: 25

证明有构造方法会自动执行,也就是说明了在构造方法中的变量会被创建且被赋值。
在这里插入图片描述

当创建Person对象时,必须传递这两个参数,这样对象的属性就被正确赋值。
__init__方法接受两个参数(nameage),并将它们用于初始化实例的属性。

1.4 魔术方法

在这里插入图片描述

  1. __init__ 方法示例:
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

person = Person("Alice", 30)
print(person.name)  # 输出: Alice
print(person.age)   # 输出: 30
  1. __str____repr__ 方法示例:
class MyClass:
    def __init__(self, value):
        self.value = value

    def __str__(self):
        return f"MyClass instance with value: {self.value}"

    def __repr__(self):
        return f"MyClass({self.value})"

obj = MyClass(42)
print(str(obj))    # 输出: MyClass instance with value: 42
print(repr(obj))   # 输出: MyClass(42)
  1. __getitem____setitem__ 方法示例:
class MyList:
    def __init__(self):
        self.data = []

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

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

my_list = MyList()
my_list.data = [1, 2, 3]

print(my_list[0])  # 输出: 1
my_list[1] = 42
print(my_list[1])  # 输出: 42
  1. __len__ 方法示例:
class MyContainer:
    def __init__(self, data):
        self.data = data

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

container = MyContainer([1, 2, 3, 4, 5])
print(len(container))  # 输出: 5
  1. __iter____next__ 方法示例(创建一个可迭代的类):
class MyRange:
    def __init__(self, start, end):
        self.start = start
        self.end = end

    def __iter__(self):
        return self

    def __next__(self):
        if self.start >= self.end:
            raise StopIteration
        current = self.start
        self.start += 1
        return current

# 使用可迭代对象
my_range = MyRange(1, 5)
for num in my_range:
    print(num)  # 输出: 1 2 3 4
  1. __eq__, __lt__, 和 __gt__ 方法示例(自定义对象的比较行为):
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __eq__(self, other):
        return self.x == other.x and self.y == other.y

    def __lt__(self, other):
        return self.x < other.x and self.y < other.y

    def __gt__(self, other):
        return self.x > other.x and self.y > other.y

point1 = Point(1, 2)
point2 = Point(1, 2)
point3 = Point(2, 3)

print(point1 == point2)  # 输出: True
print(point1 < point3)   # 输出: True
print(point1 > point3)   # 输出: False

继续探讨Python中的魔术方法的示例:

  1. __contains__ 方法示例(自定义对象的成员资格检查):
class MyList:
    def __init__(self, data):
        self.data = data

    def __contains__(self, item):
        return item in self.data

my_list = MyList([1, 2, 3, 4, 5])
print(3 in my_list)  # 输出: True
print(6 in my_list)  # 输出: False
  1. __add__, __sub__, 和 __mul__ 方法示例(自定义对象的数学操作):
class ComplexNumber:
    def __init__(self, real, imaginary):
        self.real = real
        self.imaginary = imaginary

    def __add__(self, other):
        real_sum = self.real + other.real
        imaginary_sum = self.imaginary + other.imaginary
        return ComplexNumber(real_sum, imaginary_sum)

    def __sub__(self, other):
        real_diff = self.real - other.real
        imaginary_diff = self.imaginary - other.imaginary
        return ComplexNumber(real_diff, imaginary_diff)

    def __mul__(self, other):
        real_product = self.real * other.real - self.imaginary * other.imaginary
        imaginary_product = self.real * other.imaginary + self.imaginary * other.real
        return ComplexNumber(real_product, imaginary_product)

    def __str__(self):
        return f"{self.real} + {self.imaginary}i"

# 使用自定义复数类
c1 = ComplexNumber(1, 2)
c2 = ComplexNumber(2, 3)

c3 = c1 + c2
print(c3)  # 输出: 3 + 5i

c4 = c1 - c2
print(c4)  # 输出: -1 - 1i

c5 = c1 * c2
print(c5)  # 输出: -4 + 7i

继续探讨Python中的魔术方法的示例:

  1. __enter____exit__ 方法示例(上下文管理器):
class FileContextManager:
    def __init__(self, filename, mode):
        self.filename = filename
        self.mode = mode

    def __enter__(self):
        self.file = open(self.filename, self.mode)
        return self.file

    def __exit__(self, exc_type, exc_value, traceback):
        self.file.close()

# 使用上下文管理器来读取文件
with FileContextManager('example.txt', 'r') as file:
    data = file.read()
    print(data)
  1. __call__ 方法示例(使对象可调用):
class CallableClass:
    def __init__(self):
        self.counter = 0

    def __call__(self):
        self.counter += 1
        return f"Called {self.counter} times."

callable_obj = CallableClass()
print(callable_obj())  # 输出: Called 1 times.
print(callable_obj())  # 输出: Called 2 times.
  1. __del__ 方法示例(析构方法,不建议常用):
class MyClass:
    def __init__(self, value):
        self.value = value

    def __del__(self):
        print(f"Deleting an instance with value: {self.value}")

obj1 = MyClass(42)
obj2 = obj1  # 创建对同一对象的引用

del obj1  # 不会触发析构方法
del obj2  # 触发析构方法,输出: Deleting an instance with value: 42

这些示例继续展示了魔术方法的使用,包括上下文管理器、使对象可调用、析构方法等。请注意,析构方法__del__不常用,因为Python通常会自动处理垃圾回收。根据你的需求,选择实现适当的魔术方法来自定义对象的行为。

二、三大特性

2.1 封装

  它使得类可以自由地改变内部实现,而不会对外部的代码产生负面影响。

封装是面向对象编程的三大特性之一,它指的是将数据(属性)和操作数据的方法(方法)封装在一个类内部,同时对外部隐藏类的内部实现细节。封装有以下几个关键概念:

  1. 属性私有化(Private Attributes):通常使用特殊的命名约定,如在属性名称前面添加一个下划线(例如 _value)来表示属性是私有的,外部代码不应直接访问它们。

  2. 公有方法(Public Methods):提供公有方法来访问和操作私有属性。这些方法允许外部代码以受控的方式访问和修改对象的状态。

  3. 信息隐藏(Information Hiding):通过封装,隐藏了类的内部实现细节,使对象的使用者只需关注如何使用对象,而不需要了解其内部的工作原理。

示例:

class Student:
    def __init__(self, name, age):
        self._name = name  # 私有属性
        self._age = age    # 私有属性

    def get_name(self):   # 公有方法访问私有属性
        return self._name

    def set_age(self, age):  # 公有方法修改私有属性
        if age > 0:
            self._age = age

# 创建Student对象
student = Student("Alice", 20)

# 访问和修改属性通过公有方法
print(student.get_name())  # 输出: Alice
student.set_age(21)
print(student._age)        # 输出: 21(虽然属性是私有的,但仍然可以访问)

封装的优点包括:

  • 控制对象的状态:通过公有方法来限制属性的访问和修改,可以防止不合法的状态。
  • 简化接口:使用者只需关注公有方法,而不需要了解内部实现。
  • 提高代码可维护性:内部实现的变化不会影响外部代码,降低耦合性。

2.1.1私有的成员

在Python中,私有成员通常通过命名约定来实现,而不是严格的访问控制关键字(如Java中的private

私有成员的方式:只需要在变量和方法,以__开头(2个下划线)

其无法被类对象使用,但可以被其他成员使用【以公共的方法调用不公共的方法】

__age=None

def __callMe(self):
#可以在私有方法内使用私有变量
def use_age_Mrthod(self):
		if self.__age :
		else :
			self._ _callMe()

2.2 继承

有新的内容,使用父类的成员变量和方法

class 类名(父类):
	结构

继承是面向对象编程的三大特性之一,它允许一个类(子类)基于另一个类(父类)的定义来创建新的类。子类继承了父类的属性和方法,并可以在此基础上添加新的属性和方法,或者重写父类的方法。继承有以下关键概念:

  1. 父类和子类(Base Class and Derived Class):父类是被继承的类,子类是继承父类的类。

  2. 继承关系(Inheritance Relationship):子类继承了父类的属性和方法。

  3. 重写(Override):子类可以重写父类的方法,以改变或扩展方法的行为。

  4. 扩展(Extension):子类可以添加新的属性和方法。

示例:

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

    def speak(self):
        pass  # 父类的方法,可以在子类中重写

class Dog(Animal):  # Dog是Animal的子类
    def speak(self):  # 重写父类的方法
        return f"{self.name} says Woof!"

    def wag_tail(self):  # 子类添加新方法
        return f"{self.name} wags tail."

# 创建Dog对象
dog = Dog("Buddy")
print(dog.speak())     # 输出: Buddy says Woof!
print(dog.wag_tail())  # 输出: Buddy wags tail.

继承的优点包括:

  • 代码重用:子类可以重用父类的属性和方法,减少代码的重复编写。
  • 统一接口:多个相关类可以共享相同的接口,使代码更易于理解和维护。
  • 多态性:子类可以替代父类的位置,实现多态,提高灵活性。

2.2.1 单继承

单继承是面向对象编程中的一个概念,它指的是一个子类只能继承自一个父类的特性和行为。在单继承模型中,一个类只能有一个直接的父类,这是Python的默认继承方式。这种继承模型有以下特点:

  1. 单一的继承链:每个类只有一个直接的父类,从而构成了一条单一的继承链。这意味着子类只能继承一个父类的特性和行为。

  2. 简单明了:单继承模型相对简单,易于理解和维护。每个类只有一个父类,不会出现多重继承的复杂性。

  3. Python的默认继承模型:Python默认采用单继承模型,这是因为它更加简单和直观,适用于大多数情况。

示例:

class Animal:
    def speak(self):
        pass

class Dog(Animal):
    def speak(self):
        return "Woof!"

class Cat(Animal):
    def speak(self):
        return "Meow!"

dog = Dog()
print(dog.speak())  # 输出: Woof!

cat = Cat()
print(cat.speak())  # 输出: Meow!

在上面的示例中,DogCat 类都继承自 Animal 类,它们构成了一条单一的继承链。每个子类重写了父类的 speak 方法,以实现自己的行为。

2.2.2 多继承 --同名的方法和变量,左到右的优先继承

多继承是面向对象编程中的一个概念,它指的是一个子类可以继承自多个父类的特性和行为。与单继承不同,多继承允许一个类同时具有多个直接的父类。在多继承模型中,一个子类可以继承多个不同父类的属性和方法。

  1. 多继承链:一个子类可以继承多个父类,从而构成多个继承链。这意味着子类可以具有多个不同父类的特性和行为。

  2. 复杂性:多继承模型相对复杂,因为可能会出现多个父类之间的冲突和重复。需要小心设计和解决这些问题。

  3. Python的多继承:Python支持多继承,允许一个类继承自多个父类。在多继承情况下,类可以使用逗号分隔列表来指定多个父类。

示例:

class Animal:
    def speak(self):
        pass

class Dog(Animal):
    def speak(self):
        return "Woof!"

class Cat(Animal):
    def speak(self):
        return "Meow!"

class Bird:
    def speak(self):
        return "Chirp!"

# 多继承示例
class Pet(Dog, Cat, Bird):
    pass

pet = Pet()
print(pet.speak())  # 输出: Woof!(优先调用第一个父类的方法)

在上面的示例中,Pet 类同时继承自 DogCatBird 三个父类,因此它可以调用这三个父类中的 speak 方法。

需要注意的是,多继承可能会引入冲突和命名空间问题,因此需要小心使用,确保合理设计类的层次结构,以避免混淆和复杂性。在Python中,可以使用super()函数来调用多继承中的父类方法,以解决一些问题。

2.2.3 pass关键字

pass 是Python中的一个关键字,它是一个空语句,用于表示不执行任何操作。pass 主要用于语法完整性,当代码块需要存在但不需要执行任何操作时,可以使用它。在其他编程语言中,通常使用大括号 {} 来表示空代码块,但在Python中,使用 pass 来达到相同的目的。

常见用途包括:

  1. 占位符:在编写代码时,有时可能会先定义一个函数、类或条件语句,但还没有实现其具体功能。此时可以使用 pass 作为占位符,以后再添加实际的代码。
def my_function():
    pass  # 占位符,未实现功能
  1. 空的循环体:有时可能需要创建一个循环,但循环体内暂时为空,可以使用 pass 表示循环体为空。
for item in my_list:
    pass  # 暂时没有操作
  1. 类定义:在定义一个类时,有时可能希望暂时只创建类的框架而不实现具体方法,可以使用 pass
class MyClass:
    pass  # 暂时没有属性或方法

pass 的存在允许你在代码中留下一些空白的地方,而不会引发语法错误。但要注意,过多地使用 pass 可能会导致代码的可读性下降,因此应该谨慎使用,确保它们的存在是合理的。

2.2.4 复写父类成员方法

(1)子类重写父类的方法

class Person:
    name = "Jack"

    def call_Name(self):
        print(f"{self.name}hhh")


class Student(Person):
    name = "Peter"

    def call_Name(self):
        print(f"{self.name}")


stu = Person()
print(stu.name)
stu.call_Name()

stu = Student()
print(stu.name)
stu.call_Name()


在这里插入图片描述

(2)使用父类成员【两种方式】

方式一:调用父类的方法

成员变量:父类名称.成员变量
成员方法:父类名称.成员方法(self)
# 调用父类的成员
class Parent:
    def __init__(self):
        self.value = 42

    def parent_method(self):
        return "Hello from Parent!"

class Child(Parent):
    def child_method(self):
        parent_value = Parent().value  # 调用父类的属性
        parent_greeting = Parent().parent_method()  # 调用父类的方法
        return f"Child says: Parent value is {parent_value}, {parent_greeting}"

child = Child()
print(child.child_method())

方法二 使用super()调用父类成员

成员变量:super().成员变量
成员方法:super().成员方法()

super() 并不直接支持访问父类的属性。你需要通过父类的构造函数 super().init() 来初始化属性,然后才能在子类中访问它们。

# 使用super()调用父类的成员
class Parent:
    def __init__(self):
        self.value = 42

    def parent_method(self):
        return "Hello from Parent!"

class Child(Parent):
    def child_method(self):
        parent_value = super().value  # 使用super()调用父类的属性
        parent_greeting = super().parent_method()  # 使用super()调用父类的方法
        return f"Child says: Parent value is {parent_value}, {parent_greeting}"

child = Child()
print(child.child_method())

2.* 类型注解

变量注释
形参列表的注释

类型注解是Python 3引入的一项功能,它允许你在变量、函数参数和函数返回值等地方添加类型信息,以提供代码的可读性和类型检查。虽然类型注解在运行时不会影响程序的行为,但它可以用于静态类型检查工具,如mypy,以帮助捕获潜在的类型错误。

2.*.1. 变量类型注解:

做一个备注

#可以不需要
name: str = "John"  # 声明name变量的类型为str
age: int = 30      # 声明age变量的类型为int

# 在无法看出类型时使用
varx:int =random.randint(1,10) # type: int

2.*.2. 函数参数和返回值的类型注解:[ 提示性 ]

函数->返回值类型

def greet(name: str) -> str:
    return f"Hello, {name}"

def add(a: int, b: int) -> int:
    return a + b

在上述示例中,函数greet接受一个参数name,其类型为str,并且返回一个str类型的值。函数add接受两个参数ab,都是int类型,并返回一个int类型的值。

对比
在这里插入图片描述
在这里插入图片描述

2.*.3. 类型注解和容器类型:

from typing import List

def calculate_average(numbers: List[float]) -> float:
    total = sum(numbers)
    return total / len(numbers)

在上述示例中,我们使用了List[float]来注解参数numbers,表示这是一个浮点数的列表,函数返回值也被注解为float类型。

类型注解有助于提高代码的可读性,尤其对于大型项目和团队合作而言,它们可以更清晰地传达变量和函数的预期类型。此外,类型检查工具如mypy可以根据这些注解来检查代码中的类型错误,帮助提前发现潜在的问题。

注意事项:

(1)基础容器

my_list:list=[1,2,3]
my_tuple:tuple=("hello",False,123)
my_set:set={1,2,3}
my_dict:dict ={"hrllo",123}

print(my_list)
print(my_tuple)
print(my_set)
print(my_dict)

在这里插入图片描述
(2)详细容器
元组的详细类型设置要详细,每一个都要标记
字典的详细类型要详细。键值都要

my_list:list[int]=[1,2,3]
my_tuple:tuple[str, bool, int]=("hello",False,123)
my_set:set[int]={1,2,3}
my_dict:dict[str,int] ={"hrllo",123}


print(my_list)
print(my_tuple)
print(my_set)
print(my_dict)

在这里插入图片描述

2.*.4 Union类型

导包:from typing import Union
使用:Union[类型,类型,…,类型]

Union类型是Python类型注解中的一种,它允许变量或函数参数可以具有多种不同类型中的一个。Union类型用于描述一个变量可以接受多个可能的数据类型,提供了更灵活的类型注解方式。

变量的:

from typing import Union

# 声明变量的Union类型
variable: Union[int, float, str]

# 变量可以是int、float或str中的任意一个
variable = 42       # 合法,变量是整数类型
variable = 3.14     # 合法,变量是浮点数类型
variable = "Hello"  # 合法,变量是字符串类型

# 但不合法的情况,会引发类型错误
variable = [1, 2, 3]  # 不合法,列表不在Union类型中的选项中

函数的

from typing import Union

def double_or_square(value: Union[int, float]) -> Union[int, float]:
    if isinstance(value, int):
        return value * 2
    elif isinstance(value, float):
        return value ** 2

result1 = double_or_square(5)       # 返回整数 10
result2 = double_or_square(3.5)     # 返回浮点数 12.25

在上面的示例中,double_or_square函数接受一个参数value,它的类型注解使用了Union类型,表示可以是intfloat中的任意一种类型。函数根据参数的类型执行不同的操作,然后返回相应的类型。

2.3 多态

多种状态,处于某种身份,表现出不同的对象会得到不同的状态

多态是面向对象编程的三大特性之一,它允许不同的对象对相同的方法名产生不同的行为。多态使得代码更加灵活,能够处理不同类型的对象,而无需关心其具体类型。多态有以下关键概念:

  1. 基类和派生类(Base Class and Derived Class):基类定义了通用的接口和方法,派生类继承了基类,并可以根据需要重写方法。

  2. 方法重写(Method Overriding):派生类可以重写基类中已有的方法,以实现自己的行为。

  3. 多态性(Polymorphism):不同的对象可以使用相同的方法名,但产生不同的行为。

示例:

class Animal:
    def speak(self):
        pass

class Dog(Animal):
    def speak(self):
        return "Woof!"

class Cat(Animal):
    def speak(self):
        return "Meow!"

# 多态性示例
animals = [Dog(), Cat()]

for animal in animals:
    print(animal.speak())

# 输出:
# Woof!
# Meow!

多态的优点包括:

  • 通用接口:多态允许使用通用接口处理不同类型的对象,增加了代码的灵活性和可复用性。
  • 减少条件语句:避免了大量的条件语句,代码更加简洁和可维护。
  • 扩展性:可以轻松地添加新的派生类,而不影响已有代码。

2.4 抽象类

父类用来指定方法是什么,子类来决定具体的实现过程。

  1. 抽象类

    • 抽象类是一种包含抽象方法的类,抽象方法是没有具体实现的方法,只有方法的声明。
    • 抽象类可以包含普通方法,这些方法有具体的实现。
    • 抽象类不能被实例化,只能被继承。
    • 子类继承抽象类时,必须实现抽象类中的所有抽象方法,否则子类也会被视为抽象类。

    在Python中,你可以使用abc模块创建抽象类。以下是一个抽象类的示例:

    from abc import ABC, abstractmethod
    
    class Animal(ABC):  # 继承ABC类表示抽象类
        @abstractmethod
        def speak(self):
            pass
    
    class Dog(Animal):
        def speak(self):
            return "Woof!"
    
    class Cat(Animal):
        def speak(self):
            return "Meow!"
    
    dog = Dog()
    cat = Cat()
    
    print(dog.speak())  # 输出: Woof!
    print(cat.speak())  # 输出: Meow!
    

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

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

相关文章

【C语言】【结构体的位段】位段的内存分配及注意事项

1.什么是位段&#xff1a; struct A { int _a:2; int _b:5; int _c:10; int _d:30; };1.A就是一个位段类型的变量&#xff0c;位表示比特位&#xff0c;意思是 A中的变量申请内存的比特位数 比如 _a要占 2 个bit 2.位段的成员必须是 int ,unsigned int ,signed int 类型的&…

瑞吉shardingjdbc4.0.0-RC1-->RC2 读写分离示例错误排查

linux环境&#xff1a;CentOS7.8mysql5.7.29 idea&#xff1a;jdk1.8maven3.5 框架&#xff1a;springboot2.4.5 mybatisplus3.4.2(mybatis-plus-boot-starter)sharding-jdbc4.0.0-RC2(sharding-jdbc-spring-boot-starter兼容性问题由1改成2)druid B站项目视频&#xff1a;…

格拉姆角场GAF将时序数据转换为图像并应用于凯斯西楚大学轴承故障诊断(Python代码,CNN模型)

1.运行效果&#xff1a; 格拉姆角场GAF将时序数据转换为图像并应用于故障诊断&#xff08;Python代码&#xff09;_哔哩哔哩_bilibili 环境库 只要tensorflow版本大于等于2.4.0即可运行 2.GAF的内容 GAF是一种用于时间序列数据可视化和特征提取的技术&#xff0c;通常用于…

小谈设计模式(9)—工厂方法模式

小谈设计模式&#xff08;9&#xff09;—工厂方法模式 专栏介绍专栏地址专栏介绍 工厂方法模式角色分类抽象产品&#xff08;Abstract Product&#xff09;具体产品&#xff08;Concrete Product&#xff09;抽象工厂&#xff08;Abstract Factory&#xff09;具体工厂&#x…

去雨去雪去雾数据集构建

在进行去雨去雪去雾算法的学习过程中&#xff0c;需要构建去雨去雪去雾数据集&#xff0c;本文参考Learning Multiple Adverse Weather Removal via Two-stage Knowledge Learning and Multi-contrastive Regularization: Toward a Unified Model论文中的数据集设定&#xff0c…

15np+pandas+matplotlib

numpy 维数 一维:shape(4,)二维:shape(4,5)三维:shape(4,5,6) 创建ndarray–np.array() # 可以是数组[1,2,3] 元组(1,2,3) 迭代对象range(n) np.array([1,2,3,4,5])列表中元素类型不同&#xff0c;会使用元素类型最大的作为ndarray类型 指定维度ndim 赋值操作 赋值&#xff…

【SpringBoot学习】收藏的学习资料,精!

文章目录 Spring实战&#xff08;第五版&#xff09;&#xff1a; https://potoyang.gitbook.io/spring-in-action-v5/di-er-bu-fen-ji-cheng-spring Spring实战&#xff08;第五版&#xff09;&#xff1a; https://potoyang.gitbook.io/spring-in-action-v5/di-er-bu-fen-ji-…

【cv】图像预处理技术——从特征检测讲述图像预处理理论、实践、应用|01

博主简介&#xff1a;努力学习的22级计算机科学与技术本科生&#x1f338;博主主页&#xff1a; 是瑶瑶子啦每日一言&#x1f33c;: 每一个不曾起舞的日子&#xff0c;都是对生命的辜负。——尼采 文章目录 前言0、特征检测、特征提取、特征描述、特征匹配一、图像预处理概述二…

十、空闲任务及其钩子函数

1、空闲任务的介绍 (1)一个良好的程序&#xff0c;它的任务都是事件驱动的&#xff1a;平时大部分时间处于阻塞状态。 (2)有可能我们自己创建的所有任务都无法执行&#xff0c;但是调度器必须能找到一个可以运行的任务。所以&#xff0c;我们要提供空闲任务。 (3)在使用vTas…

一站式企业协同研发云——云效

一站式企业协同研发云——云效 文章目录 一站式企业协同研发云——云效什么是云效云效的作用云效使用说明公司领导操作步骤项目创建者或项目组长操作步骤项目上线部署 什么是云效 云效是一种基于云计算技术的软件研发与交付管理平台&#xff0c;旨在提高团队的协作效率和软件交…

读者写者问题—内含408真题

读者写者问题—含408 一、问题描述 一个数据问价或记录可以被多个进程共享&#xff0c;我们把只读该文件的进程称为“读者进程”&#xff0c;其他进程为“写者进程”。允许多个进程同时读一个共享对象&#xff0c;但不允许一个写者进程和其他写者进程或读者进程同时访问共享对…

ElementUI结合Vue完成主页的CUD(增删改)表单验证

目录 一、CUD ( 1 ) CU讲述 ( 2 ) 编写 1. CU 2. 删除 二、验证 前端整合代码 : 一、CUD 以下的代码基于我博客中的代码进行续写 : 使用ElementUI结合Vue导航菜单和后台数据分页查询 ( 1 ) CU讲述 在CRUD操作中&#xff0c;CU代表创建&#xff08;Create&#xff09…

通过Nginx配置域名映射到本地项目

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

Spring的注解开发-Spring配置其它注解

Spring配置其它注解 Primary 拓展&#xff1a;Primary注解用于标注相同类型的Bean优先被使用权&#xff0c;Primary是Spring3.0引入的&#xff0c;与Componen&#xff08;及其衍生的三个注解&#xff09;t和Bean一起使用&#xff0c;标注该Bean的优先级更高&#xff0c;则在通…

【知识回顾】Java常用类库-Java Runtime

文章目录 一、快速入门1.1 Runtime 介绍1.2 常用方法1.2.1 基本方法1.2.2 行为控制类1.2.3 系统信息类1.2.4 exec1.2.5 其他方法1.2.6 注意事项 二、基本使用2.1 获取当前虚拟机信息2.2 操作系统进程2.3 Process对象 三、业务场景实战3.1 执行外部脚本3.2 动态加载类 四、小结 …

《数据结构、算法与应用C++语言描述》-栈的应用-迷宫老鼠问题

迷宫老鼠 问题描述 迷宫&#xff08;如图 8-9 所示&#xff09;是一个矩形区域&#xff0c;有一个入口和一个出口。迷宫内部包含不能穿越的墙壁或障碍物。这些障碍物沿着行和列放置&#xff0c;与迷宫的边界平行。迷宫的入口在左上角&#xff0c;出口在右下角。 假定用 nxm 的…

【Java每日一题】——第十六题:将数组元素逆序并遍历输出。(2023.09.30)

&#x1f578;️Hollow&#xff0c;各位小伙伴&#xff0c;今天我们要做的是第十五题。 &#x1f3af;问题&#xff1a; 设有数组如下&#xff1a;int[] arr{11,34,47,19,5,87,63,88}; 测试结果如下&#xff1a; &#x1f3af; 答案&#xff1a; int a[]new int [10];Random …

《三国志》游戏的MySQL数据设计与管理

在任何成功的游戏背后,都有一个精心设计和管理的数据系统。这不仅决定了游戏的运行效率,还直接影响到玩家的游戏体验。 本文将深入探讨著名游戏《三国志》中的数据设计和管理。本文将讲解游戏中核心的数据元素、数据管理方法,以及开发团队在数据方面所做的工作。 文章目录 …

【C语言次列车ing】No.1站---C语言入门

文章目录 前言一、什么是C语言二、第一个C语言程序三、数据类型四、变量、常量五、字符串转义字符注释 前言 &#x1f467;个人主页&#xff1a;小沈YO. &#x1f61a;小编介绍&#xff1a;欢迎来到我的乱七八糟小星球&#x1f31d; &#x1f4cb;专栏&#xff1a;C语言次列车i…

考研王道强化阶段(二轮复习)“算法题”备考打卡表 记录

问题&#xff1a;做408真题_2010_42题&#xff0c;即王道书 2.2.3_大题_10 思路&#xff1a; 回头补 代码&#xff1a; int moveL(SqlList &L,SqlList &S,int p) {// 健壮性表达if( L.len 0 ){return 0;}// 调用另外一个顺序表存储pos前面的元素for( int i0;i<p;…