Python面向对象基础:类与对象、继承、多态与魔法方法详解
1.什么是面向对象
1.1 面向对象和面向过程
编程思想就是人们利用计算机来解决问题的思维。
常见的思维方式有面向过程和面向对象。python是同时支持面向过程和面向对象的编程语言。
分类
1.面向过程
它是一种编程思想, 强调的是以 步骤(过程) 为基础完成各种操作。
2.面向对象
它是一种编程思想, 强调的是以 对象 为基础完成各种操作, 它是基于面向过程的。使人们的编程与实际的世界更加接近,所有的对象被赋予属性(名词)和方法(动词),这样编程就更加富有人性化。宗旨在于模拟现实世界。在现实生活中,所有事物全被视为对象(万物皆对象)。
- 更符合人们的思考习惯
- 把复杂的事情简单化
- 把人们从执行者变为指挥者
1.2 面型对象特征介绍
对于面向对象,通常具有以下这三大特性:
- 封装:把属性和方法封装在一起,仅提供对外的方法让别人去访问。好处: 简化编程
- 继承:孩子可使用老爹的东西。好处:代码复用
- 多态:同样一个函数(消息)在不同场景下表现出不同形态。 好处:解耦合,可拓展(一象多用)
1.封装
在面向对象中,封装就是隐藏对象的属性和实现细节,仅对外公开接口,控制在程序中属性的读和修改的访问级别,将抽象得到的数据和行为(或功能)相结合,形成一个有机的整体,也就是将数据与操作数据的源代码进行有机的结合,形成“类”,其中数据和函数都是类的成员。
- 封装的目的是简化编程,增强安全性
- 使用者不必了解具体的实现细节,而只是要通过外部接口以特定的访问权限来使用类的成员。
2.继承
在现实生活中,继承一般指的是子女继承父辈的财产,如“子承父业”等;在面向对象中,继承也是面向对象的基本特征之一;继承就是子类继承父类的属性和方法,使得子类对象(实例)具有父类的特征和行为。
3.多态
多态是指不同类的对象对同一消息做出响应,即同一消息可根据发送对象的不同而采用多种不同的行为方式。同样一个函数(消息)在不同场景下表现出不同形态(功能)
2.面向对象的基本概念
2.1 类与对象
Python是一门面向对象的语言(也是一门面向过程的语言)。要掌握面向对象的基本语法,则首先需要掌握两个重要的概念:
- 类:抽象的模板,对现实事物的抽象描述
- 对象:具体的实体,现实事物的具体体现
面向对象核心概念:
类: 抽象的概念, 看不见, 摸不着, 是 属性(名词) 和 行为(动词)的集合.
对象: 类的具体体现, 实现.
属性(名词): 用来描述事物的外在特征的, 例如: 姓名, 年龄...
格式: 和以前定义变量一样.
方法(动词): 用来描述事物能够做什么的, 例如: 吃, 喝...
格式: 和以前定义函数一样.
类是对事物的抽象,对象是对现实事物的具体体现。
2.2 创建类
我们都知道汽车是由汽车图纸生产出来的,那么汽车图纸就是一个模板(即类),在汽车图纸上,指定规则:生产出来的汽车必须具有跑起来的行为。这是抽象的概念模型。
类的基本语法格式
# 定义类
class 类名:
# 定义方法
方法列表...
案例:定义一个汽车类,并具有跑起来的行为
# 1.定义汽车类.
class Car: # 类名遵循 大驼峰命名法.
# 属性
# 方法
def run(self):
print('汽车会跑!...')
2.3 创建对象与调用
如何访问类中的成员?
- 创建该类的对象.
对象名 = 类名()
- 通过 对象名. 的方式调用.
对象性.属性名
对象名.方法名()
案例:
# 1.定义汽车类.
class Car:
# 属性
# 方法
def run(self):
print('汽车会跑!...')
# 2.创建汽车类的对象.
c1 = Car()
# 3. 调用Car类的run()函数, 简写版: 调用Car#run()
c1.run()

2.4 self关键字
概述:
- self是Python内置的关键字, 用于表示本类当前对象的引用,指向对象实例本身。
作用:
- 1个类是可以有多个对象的, 这多个对象都可以通过 对象名. 的方式访问类中的行为(函数)
- 函数默认有self属性, 函数通过self来区分到底是哪个对象调用的该函数。
案例1
定义汽车类, 创建多个该类的对象, 看看打印结果。


根据输出结果可以发现self和当前对象相同, 谁调用函数, self就代表哪个对象。
案例2
定义汽车类, 类内有run()函数, 并在work()中调用run()函数, 创建该类对象, 调用上述的函数.
# 1. 定义汽车类.
class Car:
# 属性(名词)
# 方法(动词)
# 1.1 run()函数
def run(self):
print(f'{self} 汽车在跑...')
# 1.2 work()函数, 在其内部调用run()
def work(self):
print(f'我是work函数, 我的self值: {self}')
self.run() # self = 本类当前对象的引用.
# 2.在类外访问Car类的方法(函数)
c1 = Car()
print(f'c1对象: {c1}')
c1.run() # c1在跑
print('-' * 36)
c1.work() # c1在work, c1在跑
print('*' * 36) # 分割线
# 3.再次创建对象.
c2 = Car()
print(f'c2对象: {c2}')
c2.run()
print('-' * 36)
c2.work()

总结:
- 在类外访问类中的方法, 需要通过 对象名. 的方式访问。
- 在类内访问类中的方法,需要通过 self. 的方式访问。
案例3
定义手机类, 能开机, 关机, 拍照。
# 1.定义手机类.
class Phone:
# 属性
# 方法
# 1.1 开机.
def open(self):
print(f'{self} 手机开机了')
# 1.2 关机.
def close(self):
print(f'{self} 手机关机了')
# 1.3 拍照.
def take_photo(self):
print(f'{self} 手机拍照了')
# 2. 创建手机类对象, 访问其成员.
p1 = Phone()
print(f'p1对象: {p1}')
p1.open()
p1.take_photo()
p1.close()
print('-' * 36)
# 3.继续创建手机类对象, 访问其成员.
p2 = Phone()
print(f'p2对象: {p2}')
p2.open()
p2.take_photo()
p2.close()

3.添加和获取对象属性
3.1 属性
属性表示的是固有特征,在Python中使用变量表示,例如人的姓名、年龄、身高、体重等,都是对象的属性。
3.2 类外面添加和获取对象属性
类外, 设置对象的属性, 格式如下:
特点: 该属性独属于这个对象, 即: 该类的其它对象没有这个属性。
类外, 获取对象的属性, 格式如下:
对象名.属性名
案例:
创建汽车类, 设置为红色, 4个轮胎, 有跑的功能。
# 1.创建汽车类.
class Car:
# 属性(名词), 事物具有哪些特征 -> 变量.
# 行为(动词), 事物能够做什么 -> 函数.
def run(self):
print('汽车会跑...')
# pass
# 2.创建该类的对象 -> 这个是 类外 的位置.
c1 = Car()
c1.run() # 汽车会跑...
# 细节1: 给c1对象设置属性.
c1.color = '红色'
c1.number = 4
# 细节2: 打印c1对象的属性值.
print(f'颜色: {c1.color}, 轮胎数: {c1.number}')
print('-' * 36)
# 3.继续创建该类的对象.
c2 = Car()
c2.run()
# 细节3: 尝试调用c2对象的 color和number属性
# print(f'颜色: {c2.color}, 轮胎数: {c2.number}')

3.3 类内部获取对象属性
回顾:
1. 类外访问类中的成员, 可以通过 对象名. 的方式.
2. 类内访问类中的成员, 可以通过 self. 的方式.
3. 类外通过 对象名.属性名 = 属性值 的方式 设置属性, 只有当前对象有.
细节:
类内如何设置属性, 要结合 魔法方法 __init__( ) 来实现, 在后面的魔术方法中介绍。
案例:
定义汽车类, 创建该类对象, 赋予颜色 和 轮胎数两个属性, 并在类内访问该属性。
# 1. 定义汽车类
class Car:
# 属性
# 行为
# 1.1 跑
def run(self):
print('汽车会跑')
# 1.2 定义函数show(), 实现 在类内访问 汽车对象的属性.
def show(self):
print(f'我是show函数, 对象的颜色: {self.color}, 轮胎数: {self.number}')
# 2.创建汽车类的对象
c1 = Car()
# 3. 给其(c1)赋予 属性 -> 类外设置属性.
c1.color = '红色'
c1.number = 4
# 4. 类外访问属性.
print(f"颜色: {c1.color}, 轮胎数: {c1.number}")
# 5. 类外访问行为(类中的函数)
c1.run()
c1.show()
print('-' * 36)
# 6. 继续创建汽车类对象, 尝试分别调用run(), show()函数.
c2 = Car()
c2.run()
# c2.show() # 报错.

4.魔法方法
4.1 概念
在Python中,有一些可以给Python类增加魔力的特殊方法,它们总是被双下划线所包围,我们称之为魔法方法。在特殊情况下会被自动调用,不需要开发者手动去调用。
__魔术方法名__()
4.2 _init_()
在Python中,当新创建一个对象时,则会自动触发__init__( )魔法方法。
分为两种情况:
无参数情况:不需要外面传递参数,初始化属性值。
有参数情况:当需要外面传递参数,初始化属性值。
无参数情况
案例:
定义汽车类, 默认属性为: color='黑色', number=3。
# 1. 定义汽车类.
class Car:
# 1.1 在魔法方法 init()中, 初始化: 属性.
def __init__(self):
print('我是 无参 init 魔法方法')
# 1.2 在init魔法方法中, 初始化属性, 则: 该类所有的对象, 一创建, 就有这些属性了.
self.color = '黑色'
self.number = 3
# 1.3 定义show()函数, 打印该类对象的 各个属性值.
def show(self):
print(f'颜色: {self.color}, 轮胎数: {self.number}')
# 2.创建汽车类对象.
c1 = Car() # 会自动调用 __init__()函数.
# 修改c1的属性值
c1.color = '红色'
c1.number = 6
# 打印c1对象的属性值.
print(c1.color, c1.number)
c1.show()
print('-' * 36)
c2 = Car()
c2.show()

有参数情况
案例:
创建汽车类, 不给默认值, 由汽车对象 外部各自赋值即可。
# 1. 定义汽车类.
class Car:
# 2.有参的 __init__()函数, 参数值由: 外部对象自行赋值.
def __init__(self, color, number):
"""
该魔法方法用于给 汽车类 对象的属性 赋值.
:param color: 车的颜色
:param number: 车的轮胎数
"""
self.color = color
self.number = number
# 定义show()函数, 打印该类对象的 各个属性值.
def show(self):
print(f'颜色: {self.color}, 轮胎数: {self.number}')
# 3. 创建汽车类对象.
# c1 = Car() # 报错, 因为默认调用了init()函数, 但是该函数有参数, 则必须传参.
c1 = Car('红色', 6)
c1.show()
print('-' * 36)
c2 = Car('绿色', 4)
c2.show()
c3 = Car()

4.3、__str__( )
当使用print输出对象时,默认打印对象的内存地址;如实现了__str__( )方法,print就自动调用该魔法方法,返回的值必须为字符串。
案例:
# 1. 定义汽车类.
class Car:
# 2.有参的 __init__()函数, 参数值由: 外部对象自行赋值.
def __init__(self, color, number):
"""
该魔法方法用于给 汽车类 对象的属性 赋值.
:param color: 车的颜色
:param number: 车的轮胎数
"""
self.color = color
self.number = number
# 魔法方法str(), 默认打印地址值, 无意义, 一般会重写, 改为打印对象的各个属性值.
def __str__(self):
# 返回值必须是字符串
return f'颜色: {self.color}, 轮胎数: {self.number}'
# return f'{self.color}, {self.number}'
# 3.创建该类的对象.
c1 = Car('绿色', 4)
print(c1) # 输出语句打印对象, 默认调用了该对象 所在类的 str魔法方法.
print('-' * 36)
c2 = Car('红色', 6)
print(c2)

4.4 _del_()
当删除对象时(调用del删除对象或文件执行结束后),Python解释器会默认调用__del__( )方法。
案例:
# 1. 定义汽车类, 属性: 品牌. 行为:run() 通过del魔法方法删除该类的对象, 看看效果.
class Car:
# 2. 在魔法方法init中, 完成: 属性的初始化.
def __init__(self, brand):
self.brand = brand
# 3.重写 str魔法方法, 打印对象的属性值.
def __str__(self):
return f'品牌: {self.brand}'
# 4. 重写 del魔法方法, 删除对象时给出提示.
def __del__(self):
print(f'{self} 对象被删除了!')
# 5. 创建汽车类对象.
c1 = Car('小米 Su7 Ultra')
print(c1)
# 6. 手动访问 brand 属性.
print(c1.brand)
print('-' * 36)
# 7.手动删除c1对象, 然后尝试 打印该对象 或者 访问对象的属性.
# del c1
# print(c1) # 报错.
print('程序结束!')

5.面向对象综合案例
5.1、案例1
"""
案例: 减肥案例.
需求:
例如,小明同学当前体重是100kg。每当他跑步一次时,则会减少0.5kg;每当他大吃大喝一次时,则会增加2kg。请试着采用面向对象方式完成案例。
分析:
类名: Student
对象名: xm
属性(名词): 当前体重, current_weight
行为(动词) 跑步, 吃饭
"""
# 1.定义学生类.
class Student:
# 2.在魔法方法init中, 完成: 对象的属性的初始化.
def __init__(self):
self.current_weight = 100
# 3.每当他跑步一次时,则会减少0.5kg
def run(self):
print('疯狂跑步...')
self.current_weight -= 0.5 # 体重减小.
# 4.大吃大喝.
def eat(self):
print('大吃大喝一顿...')
self.current_weight += 2
# 5.重写魔法方法str, 打印属性值, 即: 当前体重.
def __str__(self):
# return '当前体重: %s' % self.current_weight
return f'当前体重: {self.current_weight} kg!'
# 6. 测试.
if __name__ == '__main__':
# 6.1 创建学生对象.
xm = Student()
# 6.2 跑步
xm.run()
xm.run()
# 6.3 吃喝
xm.eat()
# 6.4 当前体重.
print(xm)
5.2、案例2
"""
案例: 烤地瓜案例.
需求:
1. 定义地瓜类 -> SweetPotato
2. 属性: 被烤时间cook_time, 烘焙状态 cook_state, 调料 condiments
3. 行为: 烘烤cook(), 添加调料 add_condiment()
4. 魔法方法: init() -> 初始化属性, str() -> 打印地瓜信息.
5. 规则:
烘烤时间 地瓜状态
[0, 3) 生的 包左不包右, 前闭后开.
[3, 7) 半生不熟
[7, 12) 熟了
[12, ∞] 糊了
"""
# 1. 定义地瓜类 -> SweetPotato
class SweetPotato:
# 2. 在魔法方法__init__()中, 初始化地瓜的属性.
def __init__(self):
self.cook_time = 0
self.cook_state = '生的'
self.condiments = []
# 3.具体的烘烤动作.
def cook(self, time):
# 3.1 根据烘烤时间, 修改地瓜的烘烤状态.
if time < 0:
print('无效值!')
else:
# 3.2 修改地瓜的 烘烤时间.
self.cook_time += time
# 3.3 根据烘烤时间, 修改地瓜的烘烤状态.
if 0 <= self.cook_time < 3:
self.cook_state = '生的'
elif 3 <= self.cook_time < 7:
self.cook_state = '半生不熟'
elif 7 <= self.cook_time < 12:
self.cook_state = '熟了'
else:
self.cook_state = '糊了'
# 4. 添加调料 add_condiment()
def add_condiment(self, condiment):
self.condiments.append(condiment)
# 5. 重写str()方法, 打印地瓜信息.
def __str__(self):
return f'烘烤时间: {self.cook_time}, 地瓜状态: {self.cook_state}, 调料: {self.condiments}'
# 6.测试.
if __name__ == '__main__':
# 7. 创建地瓜对象
dg = SweetPotato()
# 8. 具体的烘烤动作.
# dg.cook(-3)
dg.cook(3)
dg.cook(5)
dg.cook(7)
# 9. 添加调料
dg.add_condiment('芥末/辣根')
dg.add_condiment('折耳根')
dg.add_condiment('豆汁')
dg.add_condiment('鲱鱼罐头')
# 10. 打印地瓜状态.
print(dg)
更多推荐


所有评论(0)