个人简介
作者简介:大家好,我是W_chuanqi,一个编程爱好者
个人主页:W_chaunqi
支持我:点赞+收藏⭐️+留言
愿你我共勉:“若身在泥潭,心也在泥潭,则满眼望去均是泥潭;若身在泥潭,而心系鲲鹏,则能见九万里天地。”✨✨✨
Python从设计之初就已经是一门面向对象的语言,正因为如此,在Python中创建一个类和对象是很容易的。
面向过程: 分析出解决问题所需要的步骤,然后用函数把这些步骤一一实现,使用的时候依次调用就可以了。
面向对象: 把构成问题的事务按照一定规则划分为多个独立的对象,然后通过调用对象的方法来解决问题。
面向对象是一种符合人类思维习惯的编程思想。现实生活中存在各种形态不同的事物,这些事物之间存在着各种各样的联系。在程序中使用对象映射现实中的事物,使用对象的关系描述事物之间的联系,这种思想就是面向对象。
封装是面向对象的核心思想,它有两层含义,一是指把对象的属性和行为看成是一个密不可分的整体,将这两者“封装”在一起(即封装在对象中);另外一层含义指“信息隐藏”,将不想让外界知道的信息隐藏起来。例如,驾校的学员学开车,只需要知道如何操作汽车,无需知道汽车内部是如何工作的。
继承性主要描述的是类与类之间的关系,通过继承,可以在无需重新编写原有类的情况下,对原有类的功能进行扩展。例如,有一个汽车类,该类描述了汽车的普通特性和功能。进一步再产生轿车类,而轿车类中不仅应该包含汽车的特性和功能,还应该增加轿车特有的功能,这时,可以让轿车类继承汽车类,在轿车类中单独添加轿车特性和方法就可以了。继承不仅增强了代码的复用性、提高开发效率,还降低了程序产生错误的可能性,为程序的维护以及扩展提供了便利。
多态性指的是在一个类中定义的属性和方法被其它类继承后,它们可以具有不同的数据类型或表现出不同的行为,这使得同一个属性和方法在不同的类中具有不同的语义。例如,当听到“Cut” 这个单词时,理发师的行为是剪发,演员的行为表现是停止表演,不同的对象,所表现的行为是不一样的。多态的特性使程序更抽象、便捷,有助于开发人员设计程序时分组协同开发。
在面向对象中,为了做到让程序对事物的描述与事物在现实中的形态保持一致,面向对象思想中提出了两个概念,即类和对象。
在⾯向对象编程过程中,有两个重要组成部分:类 和 对象。类和对象的关系:⽤类去创建⼀个对象。
类是对⼀系列具有相同特征和⾏为的事物的统称,是⼀个抽象的概念,不是真实存在的事物。
类⽐如是制造洗⾐机时要⽤到的图纸,也就是说类是⽤来创建对象。
对象是类创建出来的真实存在的事物,例如:洗⾐机。
注意:开发中,先有类,再有对象。
✳语法
class 类名():
代码
......
注意:类名要满⾜标识符命名规则,同时遵循⼤驼峰命名习惯。
✳体验
class Washer():
def wash(self):
print('我会洗⾐服')
对象⼜名实例。
✳语法
对象名 = 类名()
✳体验
# 创建对象
haier1 = Washer()
# <__main__.Washer object at 0x0000018B7B224240>
print(haier1)
# haier对象调⽤实例⽅法
haier1.wash()
注意:创建对象的过程也叫实例化对象。
self指的是调⽤该函数的对象。
# 1. 定义类
class Washer():
def wash(self):
print('我会洗⾐服')
# <__main__.Washer object at 0x0000024BA2B34240>
print(self)
# 2. 创建对象
haier1 = Washer()
# <__main__.Washer object at 0x0000018B7B224240>
print(haier1)
# haier1对象调⽤实例⽅法
haier1.wash()
haier2 = Washer()
# <__main__.Washer object at 0x0000022005857EF0>
print(haier2)
注意:打印对象和self得到的结果是⼀致的,都是当前对象的内存中存储地址。
属性即是特征,⽐如:洗⾐机的宽度、⾼度、重量…
对象属性既可以在类外⾯添加和获取,也能在类⾥⾯添加和获取。
✳语法
对象名.属性名 = 值
✳体验
haier1.width = 500
haier1.height = 800
✳语法
对象名.属性名
✳实例
print(f'haier1洗⾐机的宽度是{haier1.width}')
print(f'haier1洗⾐机的⾼度是{haier1.height}')
✳语法
self.属性名
✳实例
# 定义类
class Washer():
def print_info(self):
# 类⾥⾯获取实例属性
print(f'haier1洗⾐机的宽度是{self.width}')
print(f'haier1洗⾐机的⾼度是{self.height}')
# 创建对象
haier1 = Washer()
# 添加实例属性
haier1.width = 500
haier1.height = 800
haier1.print_info()
class Dog(object):
tooth = 10
wangcai = Dog()
xiaohei = Dog()
print(Dog.tooth) # 10
print(wangcai.tooth) # 10
print(xiaohei.tooth) # 10
类属性的优点
- 类的实例 记录的某项数据 始终保持⼀致时,则定义类属性。
- 实例属性 要求 每个对象 为其 单独开辟⼀份内存空间 来记录数据,⽽ 类属性 为全类所共有,仅占⽤⼀份内存,更加节省内存空间。
类属性只能通过类对象修改,不能通过实例对象修改,如果通过实例对象修改类属性,表示的是创建了⼀个实例属性。
class Dog(object):
tooth = 10
wangcai = Dog()
xiaohei = Dog()
# 修改类属性
Dog.tooth = 12
print(Dog.tooth) # 12
print(wangcai.tooth) # 12
print(xiaohei.tooth) # 12
# 不能通过对象修改属性,如果这样操作,实则是创建了⼀个实例属性
wangcai.tooth = 20
print(Dog.tooth) # 12
print(wangcai.tooth) # 20
print(xiaohei.tooth) # 12
class Dog(object):
def __init__(self):
self.age = 5
def info_print(self):
print(self.age)
wangcai = Dog()
print(wangcai.age) # 5
# print(Dog.age) # 报错:实例属性不能通过类访问
wangcai.info_print() # 5
class Dog(object):
__tooth = 10
@classmethod
def get_tooth(cls):
return cls.__tooth
wangcai = Dog()
result = wangcai.get_tooth()
print(result) # 10
class Dog(object):
@staticmethod
def info_print():
print('这是⼀个狗类,⽤于创建狗实例....')
wangcai = Dog()
# 静态⽅法既可以使⽤对象访问⼜可以使⽤类访问
wangcai.info_print()
Dog.info_print()
在Python中, _xx_() 的函数叫做魔法⽅法,指的是具有特殊功能的函数。
方法 | 作用 |
---|---|
_init_ | 构造函数,在生成对象时调用 |
_del_ | 析构函数,释放对象时使用 |
_repr_ | 打印,转换 |
_setitem_ | 按照索引赋值 |
_getitem_ | 按照索引获取值 |
_len_ | 获得长度 |
_cmp_ | 比较运算 |
_call_ | 函数调用 |
_add_ | 加运算 |
_sub_ | 减运算 |
_mul_ | 乘运算 |
_truediv_ | 除运算 |
_mod_ | 求余运算 |
_pow_ | 乘方 |
_init_() ⽅法的作⽤:初始化对象。
class Washer():
# 定义初始化功能的函数
def __init__(self):
# 添加实例属性
self.width = 500
self.height = 800
def print_info(self):
# 类⾥⾯调⽤实例属性
print(f'洗⾐机的宽度是{self.width}, ⾼度是{self.height}')
haier1 = Washer()
haier1.print_info()
注意:
_init_() ⽅法,在创建⼀个对象时默认被调⽤,不需要⼿动调⽤
_init_(self) 中的self参数,不需要开发者传递,python解释器会⾃动把当前的对象引⽤传递过去。
class Washer():
def __init__(self, width, height):
self.width = width
self.height = height
def print_info(self):
print(f'洗⾐机的宽度是{self.width}')
print(f'洗⾐机的⾼度是{self.height}')
haier1 = Washer(10, 20)
haier1.print_info()
haier2 = Washer(30, 40)
haier2.print_info()
当使⽤print输出对象的时候,默认打印对象的内存地址。如果类定义了 str ⽅法,那么就会打印从在这个⽅法中 return 的数据。
class Washer():
def __init__(self, width, height):
self.width = width
self.height = height
def __str__(self):
return '这是海尔洗⾐机的说明书'
haier1 = Washer(10, 20)
# 这是海尔洗⾐机的说明书
print(haier1)
当删除对象时,python解释器也会默认调⽤ del() ⽅法。
class Washer():
def __init__(self, width, height):
self.width = width
self.height = height
def __del__(self):
print(f'{self}对象已经被删除')
haier1 = Washer(10, 20)
# <__main__.Washer object at 0x0000026118223278>对象已经被删除
del haier1
需求主线:
需求涉及⼀个事物: 地⽠,故案例涉及⼀个类:地⽠类。
1.定义类
2.创建对象,调⽤相关实例
# 定义类
class SweetPotato():
def __init__(self):
# 被烤的时间
self.cook_time = 0
# 地⽠的状态
self.cook_static = '⽣的'
# 调料列表
self.condiments = []
def cook(self, time):
"""烤地⽠的⽅法"""
self.cook_time += time
if 0 <= self.cook_time < 3:
self.cook_static = '⽣的'
elif 3 <= self.cook_time < 5:
self.cook_static = '半⽣不熟'
elif 5 <= self.cook_time < 8:
self.cook_static = '熟了'
elif self.cook_time >= 8:
self.cook_static = '烤糊了'
def add_condiments(self, condiment):
"""添加调料"""
self.condiments.append(condiment)
def __str__(self):
return f'这个地⽠烤了{self.cook_time}分钟, 状态是{self.cook_static}, 添加的调料有{self.condiments}'
digua1 = SweetPotato()
print(digua1)
digua1.cook(2)
digua1.add_condiments('酱油')
print(digua1)
digua1.cook(2)
digua1.add_condiments('辣椒⾯⼉')
print(digua1)
digua1.cook(2)
print(digua1)
digua1.cook(2)
print(digua1)
将⼩于房⼦剩余⾯积的家具摆放到房⼦中
需求涉及两个事物:房⼦ 和 家具,故被案例涉及两个类:房⼦类 和 家具类。
1.定义类
2.创建对象并调⽤相关⽅法
#家具类
class Furniture():
def __init__(self, name, area):
# 家具名字
self.name = name
# 家具占地⾯积
self.area = area
#房子类
class Home():
def __init__(self, address, area):
# 地理位置
self.address = address
# 房屋⾯积
self.area = area
# 剩余⾯积
self.free_area = area
# 家具列表
self.furniture = []
def __str__(self):
return f'房⼦坐落于{self.address}, 占地⾯积{self.area}, 剩余⾯积{self.free_area}, 家具有{self.furniture}'
def add_furniture(self, item):
"""容纳家具"""
if self.free_area >= item.area:
self.furniture.append(item.name)
# 家具搬⼊后,房屋剩余⾯积 = 之前剩余⾯积 - 该家具⾯积
self.free_area -= item.area
else:
print('家具太⼤,剩余⾯积不⾜,⽆法容纳')
bed = Furniture('双⼈床', 6)
jia1 = Home('北京', 1200)
print(jia1)
jia1.add_furniture(bed)
print(jia1)
sofa = Furniture('沙发', 10)
jia1.add_furniture(sofa)
print(jia1)
ball = Furniture('篮球场', 1500)
jia1.add_furniture(ball)
print(jia1)
⽣活中的继承,⼀般指的是⼦⼥继承⽗辈的财产。
# ⽗类A
class A(object):
def __init__(self):
self.num = 1
def info_print(self):
print(self.num)
# ⼦类B
class B(A):
pass
result = B()
result.info_print() # 1
在Python中,所有类默认继承object类,object类是顶级类或基类;其他⼦类叫做派⽣类。
故事主线:⼀个煎饼果⼦⽼师傅,在煎饼果⼦界摸爬滚打多年,研发了⼀套精湛的摊煎饼果⼦的技术。师⽗要把这套技术传授给他的唯⼀的最得意的徒弟。
分析:徒弟是不是要继承师⽗的所有技术?
# 1. 师⽗类
class Master(object):
def __init__(self):
self.kongfu = '[古法煎饼果⼦配⽅]'
def make_cake(self):
print(f'运⽤{self.kongfu}制作煎饼果⼦')
# 2. 徒弟类
class Prentice(Master):
pass
# 3. 创建对象daqiu
daqiu = Prentice()
# 4. 对象访问实例属性
print(daqiu.kongfu)
# 5. 对象调⽤实例⽅法
daqiu.make_cake()
故事推进:daqiu是个爱学习的好孩⼦,想学习更多的煎饼果⼦技术,于是,在百度搜索到⿊⻢程序员,报班学习煎饼果⼦技术。
所谓多继承意思就是⼀个类同时继承了多个⽗类。
class Master(object):
def __init__(self):
self.kongfu = '[古法煎饼果⼦配⽅]'
def make_cake(self):
print(f'运⽤{self.kongfu}制作煎饼果⼦')
# 创建学校类
class School(object):
def __init__(self):
self.kongfu = '[⿊⻢煎饼果⼦配⽅]'
def make_cake(self):
print(f'运⽤{self.kongfu}制作煎饼果⼦')
class Prentice(School, Master):
pass
daqiu = Prentice()
print(daqiu.kongfu)
daqiu.make_cake()
注意:当⼀个类有多个⽗类的时候,默认使⽤第⼀个⽗类的同名属性和⽅法。
故事:daqiu掌握了师⽗和培训的技术后,⾃⼰潜⼼钻研出⾃⼰的独⻔配⽅的⼀套全新的煎饼果⼦技术。
class Master(object):
def __init__(self):
self.kongfu = '[古法煎饼果⼦配⽅]'
def make_cake(self):
print(f'运⽤{self.kongfu}制作煎饼果⼦')
class School(object):
def __init__(self):
self.kongfu = '[⿊⻢煎饼果⼦配⽅]'
def make_cake(self):
print(f'运⽤{self.kongfu}制作煎饼果⼦')
# 独创配⽅
class Prentice(School, Master):
def __init__(self):
self.kongfu = '[独创煎饼果⼦配⽅]'
def make_cake(self):
print(f'运⽤{self.kongfu}制作煎饼果⼦')
daqiu = Prentice()
print(daqiu.kongfu)
daqiu.make_cake()
print(Prentice.__mro__)
⼦类和⽗类具有同名属性和⽅法,默认使⽤⼦类的同名属性和⽅法。
故事:很多顾客都希望也能吃到古法和⿊⻢的技术的煎饼果⼦。
class Master(object):
def __init__(self):
self.kongfu = '[古法煎饼果⼦配⽅]'
def make_cake(self):
print(f'运⽤{self.kongfu}制作煎饼果⼦')
class School(object):
def __init__(self):
self.kongfu = '[⿊⻢煎饼果⼦配⽅]'
def make_cake(self):
print(f'运⽤{self.kongfu}制作煎饼果⼦')
class Prentice(School, Master):
def __init__(self):
self.kongfu = '[独创煎饼果⼦配⽅]'
def make_cake(self):
# 如果是先调⽤了⽗类的属性和⽅法,⽗类属性会覆盖⼦类属性,故在调⽤属性前,先调⽤⾃⼰⼦类的初始化
self.__init__()
print(f'运⽤{self.kongfu}制作煎饼果⼦')
# 调⽤⽗类⽅法,但是为保证调⽤到的也是⽗类的属性,必须在调⽤⽅法前调⽤⽗类的初始化
def make_master_cake(self):
Master.__init__(self)
Master.make_cake(self)
def make_school_cake(self):
School.__init__(self)
School.make_cake(self)
daqiu = Prentice()
daqiu.make_cake()
daqiu.make_master_cake()
daqiu.make_school_cake()
daqiu.make_cake()
故事:N年后,daqiu⽼了,想要把所有技术传承给⾃⼰的徒弟。
class Master(object):
def __init__(self):
self.kongfu = '[古法煎饼果⼦配⽅]'
def make_cake(self):
print(f'运⽤{self.kongfu}制作煎饼果⼦')
class School(object):
def __init__(self):
self.kongfu = '[⿊⻢煎饼果⼦配⽅]'
def make_cake(self):
print(f'运⽤{self.kongfu}制作煎饼果⼦')
class Prentice(School, Master):
def __init__(self):
self.kongfu = '[独创煎饼果⼦配⽅]'
def make_cake(self):
self.__init__()
print(f'运⽤{self.kongfu}制作煎饼果⼦')
def make_master_cake(self):
Master.__init__(self)
Master.make_cake(self)
def make_school_cake(self):
School.__init__(self)
School.make_cake(self)
# 徒孙类
class Tusun(Prentice):
pass
xiaoqiu = Tusun()
xiaoqiu.make_cake()
xiaoqiu.make_school_cake()
xiaoqiu.make_master_cake()
class Master(object):
def __init__(self):
self.kongfu = '[古法煎饼果⼦配⽅]'
def make_cake(self):
print(f'运⽤{self.kongfu}制作煎饼果⼦')
class School(Master):
def __init__(self):
self.kongfu = '[⿊⻢煎饼果⼦配⽅]'
def make_cake(self):
print(f'运⽤{self.kongfu}制作煎饼果⼦')
# ⽅法2.1
# super(School, self).__init__()
# super(School, self).make_cake()
# ⽅法2.2
super().__init__()
super().make_cake()
class Prentice(School):
def __init__(self):
self.kongfu = '[独创煎饼果⼦技术]'
def make_cake(self):
self.__init__()
print(f'运⽤{self.kongfu}制作煎饼果⼦')
# ⼦类调⽤⽗类的同名⽅法和属性:把⽗类的同名属性和⽅法再次封装
def make_master_cake(self):
Master.__init__(self)
Master.make_cake(self)
def make_school_cake(self):
School.__init__(self)
School.make_cake(self)
# ⼀次性调⽤⽗类的同名属性和⽅法
def make_old_cake(self):
# ⽅法⼀:代码冗余;⽗类类名如果变化,这⾥代码需要频繁修改
# Master.__init__(self)
# Master.make_cake(self)
# School.__init__(self)
# School.make_cake(self)
# ⽅法⼆: super()
# ⽅法2.1 super(当前类名, self).函数()
# super(Prentice, self).__init__()
# super(Prentice, self).make_cake()
# ⽅法2.2 super().函数()
super().__init__()
super().make_cake()
daqiu = Prentice()
daqiu.make_old_cake()
注意:使⽤super() 可以⾃动查找⽗类。调⽤顺序遵循 mro 类属性的顺序。⽐较适合单继承使⽤。
在Python中,可以为实例属性和⽅法设置私有权限,即设置某个实例属性或实例⽅法不继承给⼦类。
故事:daqiu把技术传承给徒弟的同时,不想把⾃⼰的钱(2000000个亿)继承给徒弟,这个时候就要为 钱 这个实例属性设置私有权限。
设置私有权限的⽅法:在属性名和⽅法名 前⾯ 加上两个下划线 __。
class Master(object):
def __init__(self):
self.kongfu = '[古法煎饼果⼦配⽅]'
def make_cake(self):
print(f'运⽤{self.kongfu}制作煎饼果⼦')
class School(object):
def __init__(self):
self.kongfu = '[⿊⻢煎饼果⼦配⽅]'
def make_cake(self):
print(f'运⽤{self.kongfu}制作煎饼果⼦')
class Prentice(School, Master):
def __init__(self):
self.kongfu = '[独创煎饼果⼦配⽅]'
# 定义私有属性
self.__money = 2000000
# 定义私有⽅法
def __info_print(self):
print(self.kongfu)
print(self.__money)
def make_cake(self):
self.__init__()
print(f'运⽤{self.kongfu}制作煎饼果⼦')
def make_master_cake(self):
Master.__init__(self)
Master.make_cake(self)
def make_school_cake(self):
School.__init__(self)
School.make_cake(self)
# 徒孙类
class Tusun(Prentice):
pass
daqiu = Prentice()
# 对象不能访问私有属性和私有⽅法
# print(daqiu.__money)
# daqiu.__info_print()
xiaoqiu = Tusun()
# ⼦类⽆法继承⽗类的私有属性和私有⽅法
# print(xiaoqiu.__money) # ⽆法访问实例属性__money
# xiaoqiu.__info_print()
注意:私有属性和私有⽅法只能在类⾥⾯访问和修改。
class Master(object):
def __init__(self):
self.kongfu = '[古法煎饼果⼦配⽅]'
def make_cake(self):
print(f'运⽤{self.kongfu}制作煎饼果⼦')
class School(object):
def __init__(self):
self.kongfu = '[⿊⻢煎饼果⼦配⽅]'
def make_cake(self):
print(f'运⽤{self.kongfu}制作煎饼果⼦')
class Prentice(School, Master):
def __init__(self):
self.kongfu = '[独创煎饼果⼦配⽅]'
self.__money = 2000000
# 获取私有属性
def get_money(self):
return self.__money
# 修改私有属性
def set_money(self):
self.__money = 500
def __info_print(self):
print(self.kongfu)
print(self.__money)
def make_cake(self):
self.__init__()
print(f'运⽤{self.kongfu}制作煎饼果⼦')
def make_master_cake(self):
Master.__init__(self)
Master.make_cake(self)
def make_school_cake(self):
School.__init__(self)
School.make_cake(self)
# 徒孙类
class Tusun(Prentice):
pass
daqiu = Prentice()
xiaoqiu = Tusun()
# 调⽤get_money函数获取私有属性money的值
print(xiaoqiu.get_money())
# 调⽤set_money函数修改私有属性money的值
xiaoqiu.set_money()
print(xiaoqiu.get_money())
多态指的是⼀类事物有多种形态,(⼀个抽象类有多个⼦类,因⽽多态的概念依赖于继承)。
class Dog(object):
def work(self): # ⽗类提供统⼀的⽅法,哪怕是空⽅法
print('指哪打哪...')
class ArmyDog(Dog): # 继承Dog类
def work(self): # ⼦类重写⽗类同名⽅法
print('追击敌⼈...')
class DrugDog(Dog):
def work(self):
print('追查毒品...')
class Person(object):
def work_with_dog(self, dog): # 传⼊不同的对象,执⾏不同的代码,即不同的work函数
dog.work()
ad = ArmyDog()
dd = DrugDog()
daqiu = Person()
daqiu.work_with_dog(ad)
daqiu.work_with_dog(dd)
Python同样支持运算符重载,我们可以对类的专有方法进行重载,实例如下:
#!/usr/bin/python3
class Vector:
def __init__(self, a, b):
self.a = a
self.b = b
def __str__(self):
return 'Vector (%d, %d)' % (self.a, self.b)
def __add__(self,other):
return Vector(self.a + other.a, self.b + other.b)
v1 = Vector(2,10)
v2 = Vector(5,-2)
print (v1 + v2)
以上代码执行结果如下所示:
python中需要利用abc模块实现抽象类
import abc #利用abc模块实现抽象类
class shuiguo(metaclass=abc.ABCMeta):
all_type='sg'
@abc.abstractmethod #定义抽象方法,无需实现功能
def name(self):
pass
@abc.abstractmethod #定义抽象方法,无需实现功能
def func(self):
pass
class Apple(shuiguo): #子类继承抽象类,可是必须定义read和write方法
def name(self):
print('我是苹果')
def func(self):
print('好吃')
class Pear(shuiguo): #子类继承抽象类,可是必须定义read和write方法
def name(self):
print('我是梨子')
def func(self):
print('yunfeizhike')
apple =Apple()
pear=Pear()
apple.func()
pear.name()
print(pear.all_type)
print(apple.all_type)
注意:
- dir([obj]):调用这个方法将返回包含obj大多数属性名的列表(会有一些特殊的属性不包含在内)。obj的默认值是当前的模块对象。
- hasattr(obj, attr):这个方法用于检查obj是否有一个名为attr的值的属性,返回一个布尔值。
- getattr(obj, attr):调用这个方法将返回obj中名为attr值的属性的值,
- setattr(obj, attr, val):调用这个方法将给obj的名为attr的值的属性赋值为val。
- type(obj):判断对象类型,使用type()函数
class Pear():
def name(self):
print('我是梨子')
def func(self):
print('yunfeizhike')
import types
p = Pear()
print(dir(p))
print(type(p))