Python编程基础:面向对象编程

简介: 巩固Python面向对象编程一些基础知识,学习有关类的创建使用,以及类的属性方法使用等一些基础操作。

一、前言

本期博客,我们将了解学习Python面向对象编程的相关知识,学习如何编写类和使用类等一系列操作。

二、我的环境

  • 电脑系统:Windows 11
  • 语言版本:Python 3.10.4
  • 编译器:VSCode

三、创建和使用类

我们在使用类时几乎可以模拟现实世界中的任何东西,接下来我们创建一个简单的Dog类来表示所有的小狗,并为它定义属性和行为。

1、创建Dog类

classDog:
"""模拟小狗"""def__init__(self, name, age):
"""初始化小狗属性"""self.name=nameself.age=agedefsit(self):
"""模拟小狗蹲下"""print(f"小狗{self.name}已经蹲下了。")
defroll_over(self):
"""模拟小狗打滚"""print(f"小狗{self.name}正在打滚。")

其中__init__()方法是一个特殊的方法,后续每当我们使用该类创建新实例的时候Python会自动运行该方法,在这个方法中形参self必不可少,而且必须位于其他形参的前面,每个与实例相关联的方法调用都会自动传递实参self,它是一个指向实例本身的引用,让实例能够访问类中的属性和方法。

2、根据类创建实例

接下来我们将根据之前创建的类创建一个实例:

my_dog=Dog("哈里", 3)
print(f"我的小狗叫{my_dog.name}。")
print(f"我的小狗今年{my_dog.age}岁了。")
my_dog.sit()
my_dog.roll_over()

它运行的结果是:

我的小狗叫哈里。我的小狗今年3岁了。小狗哈里已经蹲下了。小狗哈里正在打滚。

如果我们要访问类的属性需要使用“实例.属性”格式,例如上面我们访问小狗的名字my_dog.name。

如果我们要调用类的方法需要使用“实例.方法”格式,例如上面我们让小狗蹲下my_dog.sit()。

我们也可以创建多个实例,并且每个实例都有自己的一组属性,能够执行相同的操作:

my_dog=Dog("哈里", 3)
print(f"我的小狗叫{my_dog.name}。")
print(f"我的小狗今年{my_dog.age}岁了。")
my_dog.sit()
your_dog=Dog("卢斯", 4)
print(f"你的小狗叫{your_dog.name}。")
print(f"你的小狗今年{your_dog.age}岁了。")
your_dog.sit()

它运行的结果是:

我的小狗叫哈里。我的小狗今年3岁了。小狗哈里已经蹲下了。你的小狗叫卢斯。你的小狗今年4岁了。小狗卢斯已经蹲下了。

四、使用类和实例

我们还可以使用类来模拟现实世界中的很多情景,当我们的类编写好之后,我们就可以将时间花在根据类创建的实例上。

1、创建Car类

classCar:
"""模拟汽车"""def__init__(self, make, model, year):
"""初始化描述汽车的属性"""self.make=makeself.model=modelself.year=yeardefget_descriptive_name(self):
"""返回整洁的描述信息"""long_name=f"{self.year}{self.make}{self.model}"returnlong_name.title()
my_new_car=Car("audi", 'a4', 2022)
print(my_new_car.get_descriptive_name())

它运行的结果是:

2022AudiA4

2、给属性指定默认值

我们在创建实例时,有些属性无须通过形参来定义,我们可以指定默认值,例如我们添加一个odometer_reading的属性,其初始值为0,然后我们在添加一个read_odometer()方法,用于读取汽车的里程表:

classCar:
"""模拟汽车"""def__init__(self, make, model, year):
"""初始化描述汽车的属性"""self.make=makeself.model=modelself.year=yearself.odometer_reading=0defget_descriptive_name(self):
"""返回整洁的描述信息"""long_name=f"{self.year}{self.make}{self.model}"returnlong_name.title()
defread_odometer(self):
"""打印汽车里程表信息"""print(f"这辆车已经跑了{self.odometer_reading}公里了。")
my_new_car=Car("audi", 'a4', 2022)
print(my_new_car.get_descriptive_name())
my_new_car.read_odometer()

它运行的结果是:

2022AudiA4这辆车已经跑了0公里了。

3、修改属性值

新车的里程为0很正常,但随着开车,里程不可能一直为0,所以我们还需要定义一个可以修改属性的方法,下面介绍三种方法。

  • 直接修改属性的值
    这是最简单的方法在调用方法前指定属性值为多少。
my_new_car=Car("audi", 'a4', 2022)
print(my_new_car.get_descriptive_name())
my_new_car.odometer_reading=23my_new_car.read_odometer()
  • 它运行的结果是:
2022AudiA4这辆车已经跑了23公里了。
  • 这种方法简单,但非常不实用,因为我们可以随便定义里程,这不符合实际情况。
  • 通过方法修改属性的值
    定义一个方法,让其在内部更新,并且为其定义逻辑禁止将里程表读数往回调。
classCar:
--snip--defupdate_odometer(self, mileage):
"""将里程表读数设置为指定的值"""ifmileage>=self.odometer_reading:
self.odometer_reading=mileageelse:
print("你不能输入比之前里程数更低的数!")
--snip--my_new_car=Car("audi", 'a4', 2022)
print(my_new_car.get_descriptive_name())
my_new_car.update_odometer(23)
my_new_car.read_odometer()
  • 结果跟之前的一样,但添加了新逻辑判断。
  • 通过方法对属性的值进行递增
    有时候需要将属性值递增特定的量,而不是将其设置为全新的值。假设我们购买了一辆二手车,且从购买到登记期间增加了100英里的里程。下面的方法让我们能够传递这个增量,并相应地增大里程表读数。
classCar:
--snip--defupdate_odometer(self, mileage):
"""将里程表读数设置为指定的值"""ifmileage>=self.odometer_reading:
self.odometer_reading=mileageelse:
print("你不能输入比之前里程数更低的数!")
defincrement_odometer(self,miles):
self.odometer_reading+=miles--snip--my_used_car=Car("audi", 'a4', 2022)
print(my_used_car.get_descriptive_name())
my_used_car.update_odometer(23_500)
my_used_car.read_odometer()
my_used_car.increment_odometer(100)
my_used_car.read_odometer()
  • 运行的结果是:
2022AudiA4这辆车已经跑了23500公里了。这辆车已经跑了23600公里了。

五、继承

编写类时,并非总是要从空白开始。如果要编写的类是另一个现成类的特殊版本,可使用继承。一个类继承另一个类时,将自动获得另一个类的所有属性和方法。原有的类称为父类,而新类称为子类。子类继承了父类的所有属性和方法,同时还可以定义自己的属性和方法。

1、子类的方法__init__()

在既有类的基础上编写新类时,通常要调用父类的方法__init__(),从而让子类也包含这些属性。

下面我们在之前的Car类下再创建一个ElectricCar类,它具备Car类的所有功能。

classCar:
"""模拟汽车"""def__init__(self, make, model, year):
"""初始化描述汽车的属性"""self.make=makeself.model=modelself.year=yearself.odometer_reading=0defget_descriptive_name(self):
"""返回整洁的描述信息"""long_name=f"{self.year}{self.make}{self.model}"returnlong_name.title()
defupdate_odometer(self, mileage):
"""将里程表读数设置为指定的值"""ifmileage>=self.odometer_reading:
self.odometer_reading=mileageelse:
print("你不能输入比之前里程数更低的数!")
defincrement_odometer(self,miles):
self.odometer_reading+=milesdefread_odometer(self):
"""打印汽车里程表信息"""print(f"这辆车已经跑了{self.odometer_reading}公里了。")
classElectricCar(Car):
""""电动车的独特之处"""def__init__(self, make, model, year):
""""初始化父类的属性"""super().__init__(make, model, year)
my_tesla=ElectricCar('tesla','models', '2022')
print(my_tesla.get_descriptive_name())


它运行的结果是:

2022TeslaModels

在创建子类时,父类必须包含在当前文件中,且位于子类的前面。

子类中的super()是一种特殊的函数,可以让我们能够调用父类的方法。

2、给子类定义属性和方法

让一个类继承另一个类后,就可以添加区分子类和父类所需的新属性和新方法了。

下面我们将给电动车添加新属性以及一个描述该属性的方法。

classElectricCar(Car):
""""电动车的独特之处"""def__init__(self, make, model, year):
""""先初始化父类的属性,再初始化电动车特有属性"""super().__init__(make, model, year)
self.battery_size=75defdescribe_battery(self):
"""打印描述电瓶容量的消息"""print(f"这个电动车电瓶容量为{self.battery_size}kwh。")
my_tesla=ElectricCar('tesla','models', '2022')
print(my_tesla.get_descriptive_name())
my_tesla.describe_battery()

它运行的结果是:

2022TeslaModels这个电动车电瓶容量为75kwh。

模拟电动汽车时,可根据所需的准确程度添加任意数量的属性和方法。如果一个属性或方法是任何汽车都有的,而不是电动汽车特有的,就应将其加入到Car类而非ElectricCar类中。这样,使用Car类的人将获得相应的功能,而ElectricCar类只包含处理电动汽车特有属性和行为的代码。

3、重写父类的方法

对于父类,只要它不符合子类模拟的实物的行为就可以进行重写,我们只需要再子类中定义一个与要重写的父类方法同名的方法即可。

4、将实例用作属性

使用代码模拟实物时,你可能会发现自己给类添加的细节越来越多:属性和方法清单以及文件都越来越长。在这种情况下,可能需要将类的一部分提取出来,作为一个独立的类。可以将大型类拆分成多个协同工作的小类。

例如我们可以专门定义一个Battery类,将针对汽车电瓶的属性和方法提取出来。

classBattery:
"""模拟电动车电瓶"""def__init__(self, battery_size=75):
"""初始化电瓶的属性"""self.battery_size=battery_sizedefdescribe_battery(self):
"""打印描述电瓶容量的消息"""print(f"这个电动车电瓶容量为{self.battery_size}kwh。")
classElectricCar(Car):
""""电动车的独特之处"""def__init__(self, make, model, year):
""""先初始化父类的属性,再初始化电动车特有属性"""super().__init__(make, model, year)
self.battery=Battery()
my_tesla=ElectricCar('tesla','models', '2022')
print(my_tesla.get_descriptive_name())
my_tesla.battery.describe_battery()

它运行的结果是:

2022TeslaModels这个电动车电瓶容量为75kwh。

输出结果和之前一样,我们将电瓶和电动车分开,这样看似很麻烦要做很多额外的工作,但可以让我们更加专注于描述某一类,并且也更好的专门添加功能和修改。

六、最后我想说

本期的Python面向对象编程内容就到此为止了,内容也不是很多,总结的也比较粗略,想要学习更多有关这方面的知识可以多去看看相关书籍或者其他大佬的博客。

有关Python编程基础的内容更新也差不多结束了,后续更新可能就是具体的练习题目或者具体的问题解决。

最后,谢谢大家能阅读完,我也希望能得到大家的支持和肯定,谢谢!

目录
相关文章
|
1天前
|
存储 人工智能 数据挖掘
Python编程入门:从基础到实战
【9月更文挑战第26天】 在这篇文章中,我们将一起探索Python编程的奇妙世界。无论你是初学者还是有一定经验的开发者,这篇文章都将为你提供有价值的信息和技巧。我们将从Python的基本语法开始,然后逐步深入到更复杂的主题,如函数、类和模块。最后,我们将通过一个实际的项目来应用我们所学的知识。让我们一起开始这段Python编程之旅吧!
|
2天前
|
数据采集 人工智能 数据挖掘
Python编程入门:从基础到实战的快速指南
【9月更文挑战第25天】本文旨在为初学者提供一个简明扼要的Python编程入门指南。通过介绍Python的基本概念、语法规则以及实际案例分析,帮助读者迅速掌握Python编程的核心技能。文章将避免使用复杂的专业术语,而是采用通俗易懂的语言和直观的例子来阐述概念,确保内容的可读性和实用性。
|
1天前
|
Python
探索Python编程中的装饰器魔法
【9月更文挑战第26天】在Python的世界里,装饰器就像是一把瑞士军刀,小巧而功能强大。它们让代码更简洁、可维护性更强。本文将通过实际示例,带你领略装饰器的魔力,从基础到进阶,一步步揭开它的神秘面纱。
9 2
|
2天前
|
机器学习/深度学习 人工智能 数据挖掘
探索Python编程之美:从基础到进阶
【9月更文挑战第25天】在数字时代的浪潮中,编程已成为一项宝贵的技能。本篇文章将引导你步入Python的奇妙世界,一个既适合初学者又深受资深开发者喜爱的编程语言。我们将一起揭开Python语言的基础面纱,探索它的核心概念,并通过实际示例深入理解其强大功能。无论你是编程新手还是希望提升自己的老手,这篇文章都将为你提供一条清晰的学习路径,助你在编程之旅上更进一步。
|
2天前
|
存储 开发者 Python
从理论到实践:Python中Trie树与Suffix Tree的完美结合,开启编程新篇章!
在编程领域,高效的数据结构对于解决问题至关重要。本文通过一个案例分析,介绍如何在Python中结合使用Trie树(前缀树)和Suffix Tree(后缀树)。案例聚焦于开发具备高效拼写检查和文本相似度检测功能的文本编辑器。首先,通过构建Trie树快速检查单词是否存在;接着,利用Suffix Tree检测文本相似度。尽管Python标准库未直接提供Suffix Tree,但可通过第三方库或自定义实现。本文展示了高级数据结构在实际应用中的强大功能,并强调了理论与实践相结合的重要性。
10 1
|
1天前
|
Python
python编程获取续蜀山剑侠传:从目录名称、网址到内容
python编程获取续蜀山剑侠传:从目录名称、网址到内容
|
1天前
|
移动开发 Python Windows
python编程获取网页标题title的几种方法及效果对比(源代码)
python编程获取网页标题title的几种方法及效果对比(源代码)
|
1天前
|
Python
python编程获取《续蜀山剑侠传》目录信息:目录名称和网址
python编程获取《续蜀山剑侠传》目录信息:目录名称和网址
|
1天前
|
Python
告别低效!Python并查集:数据结构界的超级英雄,拯救你的编程人生!
告别低效!Python并查集:数据结构界的超级英雄,拯救你的编程人生!
5 0
|
2天前
|
数据挖掘 Python
Python数据挖掘编程基础
本章介绍了Python数据挖掘编程的基础知识,涵盖Python入门所需的命令、判断与循环、函数、库导入等内容,并重点讲解了数据分析预处理和建模常用库。通过学习基本运算、数据结构、字符串操作等,帮助读者快速掌握Python语言,为后续数据挖掘工作打下坚实基础。例如,通过代码`a=3`进行赋值,利用`a*3`执行乘法运算,使用`a**3`计算幂,以及通过对字符串的拼接和分割操作,展示Python的强大功能。
10 0