【100天精通python】Day12:面向对象编程_属性和继承的基本语法与示例

本文涉及的产品
访问控制,不限时长
简介: 【100天精通python】Day12:面向对象编程_属性和继承的基本语法与示例

属性是类的特征或数据成员,可以包含各种数据类型,如整数、字符串、列表等。通过属性,我们可以为类定义各种特征和行为。

       继承是一种类之间的关系,它允许一个类(称为子类)继承另一个类(称为父类)的属性和方法。通过继承,子类可以重用父类的功能,并且还可以根据需要添加新的属性和方法。

  • 属性表示对象的状态或数据,是对象的特征。在面向对象编程中,类可以定义属性,而实例则拥有这些属性的具体值。
  • 继承是一种对象间的关系,一个类可以继承另一个类的属性和方法,从而复用已有的代码并扩展功能。
  • 继承允许我们建立类的层次结构,从抽象类继承出具体的子类,子类可以拥有父类的所有属性和方法,同时也可以根据需要添加自己特有的属性和方法。

1 属性(Attributes)

在Python中,可以通过在类中定义变量来创建属性。这些变量被称为实例变量或属性。每个实例变量都属于类的一个实例,并且可以根据需要分配不同的值。

1.1 属性的基本语法

定义属性:属性通常在类的内部定义,可以通过在类中声明变量来创建属性。属性可以是实例属性(属于类的实例)或类属性(属于类本身)。

class MyClass:
    # 定义实例属性
    instance_var = 10
    def __init__(self):
        # 初始化实例属性
        self.name = "John"

访问属性:在类的方法中可以通过使用self关键字来访问实例属性。对于类属性,可以使用类名来访问。

class MyClass:
    class_var = 20
    def __init__(self):
        self.instance_var = 10
    def get_class_var(self):
        # 访问类属性
        return MyClass.class_var
    def get_instance_var(self):
        # 访问实例属性
        return self.instance_var

修改属性:类的方法可以通过self关键字修改实例属性的值。

class MyClass:
    def __init__(self):
        self.instance_var = 10
    def set_instance_var(self, value):
        # 修改实例属性的值
        self.instance_var = value

属性的可见性:在Python中,默认情况下,类的所有属性都是公有的,可以在类的外部访问。如果希望将属性设置为私有的,可以在属性名前添加两个下划线__。

class MyClass:
    def __init__(self):
        # 私有属性
        self.__private_var = 10
    def get_private_var(self):
        # 访问私有属性
        return self.__private_var
    def set_private_var(self, value):
        # 修改私有属性的值
        self.__private_var = value

属性的装饰器:可以使用@property装饰器将类的方法转换为属性。这样可以在使用属性时像访问属性一样调用方法。

class MyClass:
    def __init__(self):
        self.__private_var = 10
    @property
    def private_var(self):
        # 使用装饰器将方法转换为属性
        return self.__private_var

示例:

class Car:
    def __init__(self, make, model, year):
        self.make = make
        self.model = model
        self.year = year
car1 = Car("Toyota", "Corolla", 2022)
car2 = Car("Honda", "Civic", 2021)
print(car1.make)  # 输出:Toyota
print(car2.year)  # 输出:2021

在上面的示例中,我们创建了一个名为Car的类,并在初始化方法__init__中定义了三个属性:make、model和year。然后,我们创建了两个Car类的实例,并为每个实例分配了不同的值。

1.2 创建用于计算的属性

       在Python中,我们可以使用@property装饰器来创建用于计算的属性。计算属性是一种通过调用特定方法计算得到的属性值,而不是直接存储在实例变量中的值。计算属性可以根据其他实例变量的值来计算,或者进行复杂的计算逻辑。

       使用@property装饰器可以创建用于计算属性的语法格式。@property装饰器允许我们将一个方法转换为只读属性,该属性的值是通过计算而来,而不是存储在实例变量中。

       以下是@property的语法格式:

class ClassName:
    def __init__(self, ...):
        # 初始化实例变量
    @property
    def attribute_name(self):
        # 计算属性的逻辑
        return computed_value

在上面的语法格式中:

  • ClassName 是类的名称,表示我们正在定义一个类。
  • ... 是__init__方法的参数列表,用于初始化实例变量。
  • attribute_name 是计算属性的名称,可以根据实际情况来指定。
  • computed_value 是通过计算得到的属性值,可以根据实际情况来计算。

使用@property装饰器可以将一个方法定义为计算属性,并且可以像访问普通属性一样访问它。当访问计算属性时,实际上是调用了被@property装饰的方法,并返回该方法的返回值作为属性值。

在使用@property装饰器时,需要注意以下几点:

计算属性的名称和实例变量的名称应该不同,否则会导致无限递归。

计算属性只能用于读取,不能用于修改。如果想要修改计算属性的值,需要定义一个对应的setter方法,并使用@property.setter装饰器。

下面是一个示例,演示如何创建一个计算属性:

class Circle:
    def __init__(self, radius):
        self.radius = radius
    @property
    def diameter(self):
        return self.radius * 2
    @property
    def area(self):
        return 3.14 * (self.radius ** 2)
    @property
    def circumference(self):
        return 2 * 3.14 * self.radius
# 创建Circle对象
circle = Circle(5)
# 访问计算属性
print(circle.diameter)  # 输出:10
print(circle.area)  # 输出:78.5
print(circle.circumference)  # 输出:31.400000000000002
# 修改radius属性并重新计算计算属性
circle.radius = 8
print(circle.diameter)  # 输出:16
print(circle.area)  # 输出:201.12
print(circle.circumference)  # 输出:50.24

在上面的示例中,我们创建了一个名为Circle的类,其中包含radius属性和三个计算属性:diameter、area和circumference。通过@property装饰器,我们将这三个方法定义为计算属性,并通过访问这些计算属性来获取计算得到的结果。

       计算属性可以动态地计算属性值,而不需要额外的存储空间,从而节省了内存和代码维护成本。在实际应用中,计算属性常用于根据对象的其他属性来计算相关的值,或者进行复杂的数学计算和逻辑操作。

1.3 属性的安全保护机制

在Python中,可以通过设置访问控制来为属性设置安全机制,以防止意外地修改或访问属性。在Python中,有两种常用的访问控制方式:公开访问和私有访问。

公开访问: 公开访问是Python默认的属性访问方式,即所有属性都可以直接访问和修改。这种方式没有访问控制,属性的访问和修改是完全开放的。例如:

class Circle:
    def __init__(self, radius):
        self.radius = radius
circle = Circle(5)
print(circle.radius)  # 输出:5
circle.radius = 8
print(circle.radius)  # 输出:8

私有访问: 为了设置安全机制,可以在属性名前加上两个下划线"__",将属性设置为私有属性。私有属性只能在类的内部访问,外部无法直接访问和修改。要访问私有属性,可以通过公开的访问接口进行间接访问。例如:

class Circle:
    def __init__(self, radius):
        self.__radius = radius
    def get_radius(self):
        return self.__radius
    def set_radius(self, radius):
        if radius > 0:
            self.__radius = radius
circle = Circle(5)
print(circle.get_radius())  # 输出:5
# 试图直接访问私有属性将报错
# print(circle.__radius)  # 报错:'Circle' object has no attribute '__radius'
circle.set_radius(8)
print(circle.get_radius())  # 输出:8

通过以上示例,我们在属性名前添加了两个下划线"__",将radius属性设置为私有属性。为了访问和修改私有属性,我们定义了公开的访问接口get_radius()和set_radius(),通过这些接口间接地访问和修改私有属性。

通过使用私有属性和公开访问接口,可以在类的内部控制对属性的访问和修改,从而实现属性的安全性。这样可以防止外部不恰当地修改属性,保护了属性的完整性和数据安全。

2 继承(Inheritance)

f0ce7231343f43b18a090581af19ca5c.png

       继承是面向对象编程中的一个重要概念,它允许我们创建一个新的类(称为子类)来继承另一个已有类(称为父类)的属性和方法。子类可以继承父类的所有公有成员,并且还可以添加自己的成员。继承使得代码重用和组织变得更加简单和有效。

2.1 继承的基本语法

class ParentClass:
    # 父类的属性和方法
class ChildClass(ParentClass):
    # 子类继承父类的属性和方法,并可以添加自己的属性和方法

在上面的语法中,我们首先定义了一个父类ParentClass,其中包含一些属性和方法。然后我们定义一个子类ChildClass,并在括号中指定父类名ParentClass。子类ChildClass继承了父类ParentClass的所有属性和方法,并且还可以添加自己的属性和方法。

       在Python中,可以通过将父类作为参数传递给子类来实现继承。子类将继承父类的属性和方法,并可以在需要时添加新的属性和方法。

       以下是一个简单的示例,演示了如何创建一个父类和一个子类,并通过继承获得父类的属性和方法:

# 定义父类
class Animal:
    def __init__(self, name, species):
        self.name = name
        self.species = species
    def make_sound(self):
        pass
# 定义子类,并继承父类Animal
class Dog(Animal):
    def __init__(self, name, breed):
        # 调用父类的构造函数
        super().__init__(name, species="Dog")
        self.breed = breed
    def make_sound(self):
        return "Woof!"
# 创建子类对象
dog = Dog("Buddy", "Labrador")
print(dog.name)  # 输出:Buddy
print(dog.species)  # 输出:Dog
print(dog.breed)  # 输出:Labrador
print(dog.make_sound())  # 输出:Woof!

在上面的示例中,我们定义了一个Animal父类,其中包含两个属性name和species,以及一个抽象方法make_sound。然后我们定义了一个Dog子类,并通过继承获得了父类Animal的属性和方法。在子类中,我们还添加了一个自己的属性breed,并实现了make_sound方法。通过继承,我们可以在子类中重用父类的代码,并且还可以扩展和定制子类的功能。

2.2 方法的重写

       方法的重写(Method Overriding)是面向对象编程中的一个重要概念,它允许子类覆盖(重写)父类中已有的方法,从而实现对方法的定制和扩展。当子类中定义了一个与父类中同名的方法时,子类的方法将覆盖父类的方法,从而在子类对象中调用该方法时会执行子类中的实现而不是父类的实现。

       重写方法的基本语法如下:

class ParentClass:
    def some_method(self):
        # 父类的方法实现
class ChildClass(ParentClass):
    def some_method(self):
        # 子类重写的方法实现

在上面的语法中,我们定义了一个父类ParentClass,其中包含一个名为some_method的方法。然后我们定义了一个子类ChildClass,并在其中重新定义了some_method方法。当子类对象调用some_method方法时,将会执行子类的方法实现。

以下是一个示例,演示了如何在子类中重写父类的方法:

# 定义父类
class Animal:
    def make_sound(self):
        return "Some generic sound"
# 定义子类,并继承父类Animal
class Dog(Animal):
    def make_sound(self):
        return "Woof!"
# 创建子类对象
dog = Dog()
print(dog.make_sound())  # 输出:Woof!

在上面的示例中,我们定义了一个父类Animal,其中包含一个make_sound方法,它返回一个通用的声音字符串。然后我们定义了一个Dog子类,并在其中重写了make_sound方法,使其返回"Woof!"。当我们创建子类对象并调用make_sound方法时,将会执行子类Dog中重写的方法,输出"Woof!",而不是父类Animal中的实现。这就是方法重写的作用,它允许子类在需要的时候定制和扩展父类的方法。

2.3 派生类中调用基类的_init_()方法

在派生类(子类)中调用基类(父类)的__init__()方法,可以通过使用super()函数来实现。super()函数是Python内置函数,它用于访问父类的方法和属性。

在派生类的__init__()方法中使用super()函数,可以在子类的构造函数中先调用父类的构造函数,然后再添加子类自己的初始化代码。这样可以确保子类对象在初始化时包含父类的属性。

下面是一个示例,演示了如何在子类中调用基类的__init__()方法:

class ParentClass:
    def __init__(self, name):
        self.name = name
class ChildClass(ParentClass):
    def __init__(self, name, age):
        super().__init__(name)  # 调用父类的__init__方法
        self.age = age
# 创建子类对象
child = ChildClass("Alice", 25)
print(child.name)  # 输出:Alice
print(child.age)   # 输出:25

在上面的示例中,我们定义了一个父类ParentClass,其中有一个__init__()方法,用于初始化name属性。

又定义了一个子类ChildClass,并在其__init__()方法中使用super().__init__(name)调用了父类的__init__()方法,从而在子类对象初始化时设置了name属性。

然后我们添加了子类自己的初始化代码,设置了age属性。最后,我们创建了子类对象并访问了name和age属性,验证了调用基类__init__()方法的正确性。

3 总结

属性:

  • 属性用于存储数据或计算属性值,是类的成员之一。
  • 在类中可以通过在类体中声明变量来定义属性。属性可以是实例属性(属于类的实例)或类属性(属于类本身)。
  • 实例属性通过self关键字在类的方法中访问和修改,而类属性可以使用类名来访问。
  • 可以使用@property装饰器将方法转换为属性,从而实现属性的计算和访问控制。
  • 属性可以设置为私有的,通过在属性名前添加两个下划线__来实现私有属性。

继承:

  • 继承是面向对象编程中实现代码重用的机制,允许一个类(派生类)继承另一个类(基类)的属性和方法。
  • 派生类可以获得基类的所有属性和方法,并可以在派生类中添加新的属性和方法,或重写基类的方法。
  • 继承的关系形成了类的层次结构,子类继承了父类的特性,并可以进一步派生出更多的子类。
  • 使用继承可以减少代码的重复,提高代码的可维护性和可扩展性。


相关实践学习
消息队列+Serverless+Tablestore:实现高弹性的电商订单系统
基于消息队列以及函数计算,快速部署一个高弹性的商品订单系统,能够应对抢购场景下的高并发情况。
云安全基础课 - 访问控制概述
课程大纲 课程目标和内容介绍视频时长 访问控制概述视频时长 身份标识和认证技术视频时长 授权机制视频时长 访问控制的常见攻击视频时长
目录
相关文章
|
20天前
|
人工智能 Ubuntu IDE
【Python】基础:环境配置与基础语法
本文介绍了Python编程语言及其环境配置方法。Python由Guido van Rossum于1991年创建,以其简洁、易学和强大的功能著称。文章详细讲解了Python的主要特点、Windows和Ubuntu下的安装配置步骤、基础语法、控制流、函数、文件操作、模块使用及面向对象编程等内容,帮助读者快速入门Python编程。
49 4
|
29天前
|
数据挖掘 Python
Python示例,展示如何找到最近一次死叉之后尚未形成金叉的位置
【10月更文挑战第7天】金融分析中,“死叉”指短期移动平均线(如MA5)跌破长期移动平均线(如MA10),而“金叉”则相反。本文提供Python代码示例,用于找出最近一次死叉后未形成金叉的位置,涵盖移动平均线计算、交叉点判断及结果输出等步骤,适合金融数据分析。
34 4
|
9天前
|
存储 Python Perl
python正则语法
本文介绍了正则表达式的基础知识及其在 Python 中的应用。首先解释了为什么要使用正则表达式,通过一个判断手机号的示例展示了正则表达式的简洁性。接着详细介绍了 `re` 模块的常用方法,如 `match()`、`search()`、`findall()`、`finditer()` 等,并讲解了正则表达式的基本语法,包括匹配单个字符、数字、锚字符和限定符等。最后,文章还探讨了正则表达式的高级特性,如分组、编译和贪婪与非贪婪模式。
12 2
|
9天前
|
数据挖掘 Python
Python示例,展示如何找到最近一次死叉之后尚未形成金叉的位置
金融分析中,“死叉”指短期移动平均线(如MA5)跌破长期移动平均线(如MA10),而“金叉”则相反。本文提供Python代码示例,用于找出最近一次死叉后未形成金叉的位置,涵盖移动平均线计算、交叉点判断及结果输出等步骤,适合金融数据分析。
15 1
|
15天前
|
存储 程序员 开发者
Python编程入门:从零开始掌握基础语法
【10月更文挑战第21天】本文将带你走进Python的世界,通过浅显易懂的语言和实例,让你快速了解并掌握Python的基础语法。无论你是编程新手还是想学习一门新的编程语言,这篇文章都将是你的不二之选。我们将一起探索变量、数据类型、运算符、控制结构、函数等基本概念,并通过实际代码示例加深理解。准备好了吗?让我们开始吧!
|
25天前
|
索引 Python
python-类属性操作
【10月更文挑战第11天】 python类属性操作列举
15 1
|
24天前
|
Linux Android开发 开发者
【Python】GUI:Kivy库环境安装与示例
这篇文章介绍了 Kivy 库的安装与使用示例。Kivy 是一个开源的 Python 库,支持多平台开发,适用于多点触控应用。文章详细说明了 Kivy 的主要特点、环境安装方法,并提供了两个示例:一个简单的 Hello World 应用和一个 BMI 计算器界面。
38 0
|
29天前
|
PyTorch 测试技术 算法框架/工具
Python中Thop库的常见用法和代码示例
肆十二在B站分享了关于THOP(Torch-OpCounter)的实战教学视频。THOP是一个用于计算PyTorch模型操作数和计算量的工具,帮助开发者评估模型复杂度和性能。本文介绍了THOP的安装、使用方法及基本用例,包括如何计算模型的FLOPs和参数量。
64 0
|
29天前
|
Python
Python中tqdm模块的常用方法和示例
`tqdm` 是一个快速、可扩展的Python进度条库,适用于长循环中添加进度提示。通过封装迭代器 `tqdm(iterator)`,可以轻松实现进度显示。支持自定义描述、宽度及嵌套进度条,适用于多种迭代对象。在Jupyter notebook中,可自动调整显示效果。
32 0
|
29天前
|
Python
Python中threading模块的常用方法和示例
Python 的 `threading` 模块提供了多线程编程的能力,允许同时执行多个线程。主要类包括 `Thread`、`Lock` 和 `Condition`。`Thread` 类用于创建和管理线程,`Lock` 用于同步线程,防止资源竞争,`Condition` 用于线程间协调。本文介绍了这些类的常用方法及示例代码,帮助你更好地理解和使用多线程编程。
25 0
下一篇
无影云桌面