目录
面向对象
面向对象就是将编程当成一个事物, 对外界来说事物就是直接使用的,而事物的构成我们不需要理解,编程上的理解就是设置该事物能做什么事情。
类和基本对象
然后面向对象编程过程中,有两个组成部分类和对象,类和对象的关系:用类去创建一个对象,类好比洗衣机图纸!也就是说类是用来创造对象的基础,然后被创造出来的洗衣机就是对象,这个对象名是洗衣机的编码,按照这种理解,类是一张洗衣机图纸,那对象就是无限台洗衣机。
类内部包括:特征和行为,也就是说为属性和方法,编程上就是变量和函数。
1.创建类
语法:class 类名():
类变量名 = 值
def __init__(self): # 对象属性
self.属性名 = 变量
.........
def 函数名(self): # 对象可调用方法
代码
......
# 注意:self指的是调用该函数或属性的对象
2.创建对象
语法:对象名 = 类名()
3.调用属性和函数
对象名.属性
对象名.函数名()
4.一个类可以创建多个对象
对象名1 = 类名()
对象名2 = 类名()
对象名2 = 类名()
........
5.对类 添加属性
对象名.属性名 = 值
# 注意:外部修改类内部顺序性,需要确定对象,或者属性需要为类属性,才可进行赋值。
注意:类命名和对象名依旧要遵循标识符命名规则。self只是指调用该类中方法的对象。
示例代码
# 创建类
class Washer():
def wash(self):
print("能洗衣服")
print(self)
# 创建对象
haier1 = Washer()
# 调用对象方法
haier1.wash()
# 创建多个对象
haier2.wash()
haire3.wash()
haire4.wash()
# 判断self是不是对象
print(haier1) # 输出的内存地址 一致
haier1.wash() # 输出的内存地址 一致
# 添加属性
harier1.width = 400
print(harier1.width) # 输出 400
魔法方法
在python的类中,有一个__xx__(self)格式的函数,这种统称为魔法方法,指的是具备特定功能的类内置函数。
1.init(self)方法
作用:初始化对象。
示例代码:
class Washer():
def __init__(self,width,height): # 设置属性 形参
# 添加实例属性
self.width = width # 将传入实际参数
self.heigh = height # 将传入实际参数
def print_info(self):
# 类里面调用实例属性
print(f"洗衣机的宽度是{self.width},高度{self.height}")
haier1 = Washer(30,40) # 在类里传入实际参数
haier1.print_info() # 洗衣机的宽度是30,高度40
# 注意:每个对象都是独立的
haier2 = Washer(100,500) # 在类里传入实际参数
haier2.print_info() # 洗衣机的宽度是100,高度500
注意:init(self)中的self参数,不需要开发者传递,python解释器,会自动把当前的对象应用传递过去,并且在创建一个对象时默认被调用,不需要手动调用。
2.str(self)方法
作用:改变打印内存地址的方式,return返回的定义的内容。
示例代码:
class Washer():
def __init__(self):
self.width = 300
def __str__(self):
return "解释说明:类的说明或者对象状态的说明"
haier = Washer()
print(haier)
# 你可以尝试把__str__(self)方法删除,然后再打印对象,看是不是内存地址!
3.del(self)方法
作用:但删除对象时,python解释器也会默认调用__del__(self)方法。
class Washer():
def __init__(self,width,height):
self.width = width
self.height = height
def __del__(self):
print(f"{self}对象已经被删除")
haier1 = Washer(10,20)
print(haier1)
del haier1
以上是常用的魔法方法,至于还有其他的魔法方法,可以自行搜索文档了解。
面向对象案例
1.烤地瓜
需求主线:
1. 被烤的时间和对应的地瓜状态:
0~3分钟:生的
3~5分钟:半生不熟
5~8分钟:烤糊了
超过8分钟:烤糊了
2. 添加的调料
用户可以按自己的意愿添加调料
定义类:
- 地瓜的属性
1.1 被烤的时间
1.2 地瓜的状态
1.3 添加的调料 - 地瓜的方法
2.1 被烤
2.1.1 用户根据自己意愿设定每次烤地瓜的时间
2.1.2 判断地瓜被烤的总时间是在哪个区间,修改地瓜状态
2.2 添加调料
2.2.1 用户根据医院设定添加的调料
2.2.2 将用户添加的调料存储 - 显示对象信息
# 定义类:初始化属性、被烤和添加调料的方法,显示对象信息的str
class SweetPotato():
def __init__(self):
# 被烤的时间
self.cook_time = 0
# 烤的状态
self.cook_state = '生的'
# 调料列表
self.condiments = []
def cook(self,time):
# 1. 计算地瓜整体烤过的时间
self.cook_time += time
# 2. 用整体烤过的时间在判断地瓜的状态
if 0 <= self.cook_time < 3:
# 状态
self.cook_state = "生的"
elif 3 <= self.cook_time < 6:
# 状态
self.cook_state = "半生不熟"
elif 6 <= self.cook_time < 8:
# 状态
self.cook_state = "全熟"
elif 8 <= self.cook_time :
# 状态
self.cook_state = "烤糊了"
def add_condiments(self,condiment):
# 用户意愿的调料追加到调料列表
self.condiments.append(condiment)
def __str__(self):
return f"这个地瓜考了{self.cook_time}分钟,状态是{self.cook_state},调料是{self.condiments}"
# 2.创建对象并调用对应的实例方法
CookingDiGua = SweetPotato()
print(CookingDiGua)
CookingDiGua.cook(1)
CookingDiGua.add_condiments("盐巴")
print(CookingDiGua)
CookingDiGua.cook(2)
CookingDiGua.add_condiments("酱油")
print(CookingDiGua)
2.烤地瓜
需求主线:将小于房子剩余面积的家具摆放的房子中需求涉及两个事物:房子 和 加剧,故被案例涉及两个雷: 房子类 和家具类
房子类
-
实例属性
1. 房子地理位置 2. 房子占用面积 3. 房子剩余面积 4. 房子内家具列表
-
实例方法
1. 容纳家具
-
显示房屋信息
家具类
- 家具名称
- 家具占地面积
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("无法容纳更多的家具")
F1 = Furniture("沙发",10)
F2 = Furniture("双人床",30)
AddHome = Home("天堂",200)
AddHome.add_furniture(F1)
print(AddHome)
AddHome.add_furniture(F2)
print(AddHome)
对象继承
基本概念
继承这个词汇就知道是父子关系,那一般子都会继承父亲一切内容,然后也会拥有自己的一些独特内容,就叫做继承。
格式:
class 类名(): # 经典类(旧式类)
代码
代码
......
class 类名(object) # 新式类
代码
代码
.......
示例代码
class A(object): # 父类
def __init__(self):
self.num = 1
def info_print(self):
print(self.num)
class B(A): # 子类
pass # 避免错误 需要加上pass
result = B()
result.info_print()
在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.创建对象tudi
tudi = Prentice()
# 4.对象访问实例属性,以及调用方法
print(tudi.kongfu)
tudi.make_cake()
多继承
可能这个这是个野孩子有两个爹!
# 1.两个父类
class Master1(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}制作无敌风火轮')
# 2.子类继承两个父类
class Prentice1(School,Master1):
pass
# 3.调用子类
daqiu = Prentice1()
print(daqiu.kongfu)
daqiu.make_cake()
# 注意:当一个类有多个父类的时候,“默认使用第一个父类的”(同名)属性和方法
子类重写父类
子类重定义父类同名属性和方法 ,就是去掉pass书写与父类相同属性和方法
注意:解释器优先调用子类中与父类同名的属性和方法
class Master(object):
def __init__(self):
self.kongfu = "[上古绝招]"
def make_cake(self):
print(f'运用{self.kongfu}制作风火轮')
# 2.子类
class Prentice(Master):
def __init__(self):
self.kongfu = "[独门上古绝招]"
def make_cake(self):
print(f'运用{self.kongfu}制作风火轮')
# 3.创建对象tudi
tudi = Prentice()
# 4.对象访问实例属性,以及调用方法
print(tudi.kongfu)
tudi.make_cake()
# 子类和父类具有同名属性和方法,默认使用子类的同名属性和方法
__mro__方法
这个方法就是用来看类所继承的所有父类,并且看他们继承的顺序。
class Master(object):
def __init__(self):
self.kongfu = "[上古绝招]"
def make_cake(self):
print(f'运用{self.kongfu}制作风火轮')
# 2.子类
class Prentice(Master):
def __init__(self):
self.kongfu = "[独门上古绝招]"
def make_cake(self):
print(f'运用{self.kongfu}制作风火轮')
# 3.创建对象tudi
tudi = Prentice()
# 4.对象访问实例属性,以及调用方法
print(tudi.kongfu)
tudi.make_cake()
print(Prentice.__mro__) # 可以知道 父类和子类之间的层级关系 结果:(<class '__main__.Prentice'>, <class '__main__.Master'>, <class 'object'>)
子类调用父类属性和方法
其实就在子类里面,重新定义个一个调用父类的函数。
定义的函数格式为:
父类类名.函数()
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}制作煎饼果子')
# 2.定义徒弟类,继承师傅类和学校类,添加和父类同名的属性和方法
class Prentice(School,Master):
def __init__(self):
self.kongfu = '[独创煎饼果子配方]'
def make_cake(self):
# 加自己的初始化的原因:如果不加这个自己的初始化,kongfu属性是上一次调用的init内的kongfu属性值
self.__init__()
print(f'运用{self.kongfu}制作煎饼果子')
def make_master_cake(self):
# 父类类名.函数()
# 再次调用初始化的原因:这里想要调用父类的同名方法和属性,属性在init初始化位置,所以需要再次调用init
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()
多层继承
这个更简单了,之前前面的多继承吗?就是一个儿子有两个野爹,然后这个儿子又有了孩子,这个孩子继承了他两个野爷爷和爹的所有内容。
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}制作煎饼果子')
# 2.定义徒弟类,继承师傅类和学校类,添加和父类同名的属性和方法
class Prentice(School,Master):
def __init__(self):
self.kongfu = '[独创煎饼果子配方]'
def make_cake(self):
# 加自己的初始化的原因:如果不加这个自己的初始化,kongfu属性是上一次调用的init内的kongfu属性值
self.__init__()
print(f'运用{self.kongfu}制作煎饼果子')
def make_master_cake(self):
# 父类类名.函数()
# 再次调用初始化的原因:这里想要调用父类的同名方法和属性,属性在init初始化位置,所以需要再次调用init
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()
print(Tusun.__mro__)
super()的用法
super()主要是为了简化调用父类函数的函数,另外这个函数的适用范围在于单继承!
格式:super(父类名,self).父类函数()
定义徒弟类,继承师傅类和学校类,添加和父类同名的属性和方法
class Prentice(School,Master):
def __init__(self):
self.kongfu = '[独创煎饼果子配方]'
def make_cake(self):
# 加自己的初始化的原因:如果不加这个自己的初始化,kongfu属性是上一次调用的init内的kongfu属性值
self.__init__()
print(f'运用{self.kongfu}制作煎饼果子')
# def make_master_cake(self):
# 父类类名.函数()
# 再次调用初始化的原因:这里想要调用父类的同名方法和属性,属性在init初始化位置,所以需要再次调用init
# Master.__init__(self)
# Master.make_cake(self)
#
# def make_school_cake(self):
# School.__init__(self)
# School.make_cake(self)
def old_make_cake(self):
super(Master, self).__init__()
super(Master, self).make_master_cake()
# super().old_make_cake() 注意:使用super()可以自动查找到父类。
# 调用顺序遵循__mro__类属性的顺序。比较合适单继承使用。
私有属性
我们在做类的时候,其实是很忌讳类内部的属性和方法被外部调用后改动,这样很容易造成程序不可逆的破坏,所以是有属性就是起到这么一个作用,私有属性没有设定获取函数和修改函数无法在外部调用和更改,只能在内部使用。
格式:__变量名 __函数名()
class Washer():
def __init__(self):
vars = 100 # 类属性
self.varc = 100 # 对象属性
self.__var = 100 # 私有属性
def wash(self): # 普通方法
print("我会洗衣服")
print(self)
def _wash(self): # 普通方法
print("我会洗衣服")
print(self)
def __wash(self): # 私有方法
print("我会洗衣服")
print(self)
def set_test(self): # 修改私有属性
self.__var = 600
def get_test(self): # 获取私有属性
return self._var
def get_tests(self): # 获取私有方法
self.__test()
print('测试成功')
# 2.创建对象
haier = Washer()
# 3.私有属性和私有方法调用
haier.get_tests() # 调用私有方法
print(haier.get_test()) # 调用私有属性
# 4.私有属性修改
haier.set_test() # 调用设置属有属性修改
print(haier.get_test()) # 验证私有属性修改情况
多态
多态指的是一类事物有多种形态,一个抽象类的有多个子类,婴儿多态的概念依赖于继承。
定义:多态是一种使用对象的方式子类,重写父类方法,屌样不同之类对象的相同父类方法,可以产生不同的执行结果。
好处:调用灵活,有了多态,更加容易编写出通用的代码,做出通用的编程,以适应需求的不断变化。
实现步骤:
- 定义父类,并提供公共方法
- 设定子类,并重写父类方法
- 传递子类对象给调用者,可以看到不同子类执行效果不同
示例代码
# 定义父类:提供公共方法 警犬
class Dog(object):
def work(self):
print('指哪打哪') # 父类提供统一方法,哪怕是pass
# 定义子类:子类重写父类的方法,定义两个类表示不同的警犬
class ArmyDog(Dog): 继承父类Dog
def work(self): # 子类重写父类同名方法
print('追击敌人')
class DrugDog(Dog): 继承父类Dog
def work(self): # 子类重写父类同名方法
print('稽查毒物')
# 定义父类: 提供公共方法 警察
class Person(object):
def work_with_dog(self,dog): # 将对象作为参数传入,执行不同的工作
dog.work()
# 创建对象:调用不同功能,传入不同对象,观察执行后的结果
aa = ArmyDog()
dd = DrugDog() # 创建了两条狗
daqiu = Person() # 创建了一个人
daqiu.work_with_dog(aa) # 这人带着一条追踪狗
daqiu.work_with_dog(dd) # 这人带着一条查毒狗
类属性和实例属性
类属性前面没有self 就是一个普通变量,实例属性就是创建的对象变量。类属性作为公共属性,可以被类或对象调用。
类和实例属性特点
- 记录的某项数据始终保持一致时,则定义类属性。
- 类属性仅占一份内存,为全局变量,节省空间。
- 实例属性要求每个对象都要单独开辟一份内存在存放数据
- 类属性只能通过类修改,不能通过对象属性修改,对象属性修改或赋值,只是创建一个新的对象属性。
示例代码
# 1. 定义类:定义类属性
class Dog(object):
too = 10
# 2.创建对象
wc = Dog()
wb = Dog()
# 3.范围类属性:类和对象
print(wc.too) # 结果 10
print(wb.too) # 结果 10
# 修改类属性
Dog.too = 50
print(Dog.too) # 结果 50
print(wc.too) # 结果 50
print(wb.too) # 结果 50
# 对象不可修改类属性,修改只是创建新对象属性
wc.too = 900
print(Dog.too) # 结果 10
print(wc.too) # 结果 900
print(wb.too) # 结果 10
类方法和静态方法
当类中的方法需要使用类属性时,需要对方法进行重定义,将对象方法改为类方法。而类方法一般和类属性配合使用。
类方法示例代码
class Dog(object):
__tooth = 10
# 定义类方法
@classmethod
def get_tooth(cls):
return cls.__tooth
# 创建对象进行调用
wc = Dog()
result = wc.get_tooth()
print(result)
print(Dog.get_tooth())
静态方法主要是不用床底参数,没有self和cls,使用了静态方法,对象和类都可以访问该方法。
特点:有利于减少不必要的内存占用和性能消耗。
静态方法示例代码
# 定义类:定义静态方法
class Dog(object):
@staticmethod
def info_print():
print('这是静态方法的狗类实例')
#创建对象
wc = Dog()
wc.info_print()
Dog.info_print()
总结
以上就是python面向对象的全部内容。