面向对象的三大特征:封装、继承、多态
封装
概念:将一个对象的数据隐藏在对象内部,不让在外界直接访问,而是通过对象提供的方法来访问这些隐藏起来的数据,这样就可以在访问方法中添加访问条件限制,目的是对数据的有效组织和数据安全性的保护
通俗理解:就是一个东西是自己的,不让外人直接拿到,而是通过向自己借东西的行为来判断是否可以借给他人
属性私有化封装
约定私有化:加一个下划线在规范上约定不能直接访问
语法私有化:加两个下划线在语法上不能通过属性名称直接访问
属性私有化是python层面的操作,底层解释器在解释时将两个下划线开头的属性进行了自动转换变成了_类名__属性名的形式,原来的属性名已经不存在了,所以不能直接访问,但是可以通过转换后的语法来访问,但是不推荐
私有化属性数据有两个用途:
第一可以用在当前类型中的业务流程中,如对象的一个临时计数属性等
第二可以使用类型提供的访问私有化属性方法来获取数据参与类外部的运算
属性访问方法
属性私有化之后,只能在当前类内部访问,为了数据的可用性,一般会提供私有访问属性的操作方法
固定语法格式:
访问格式
修改格式
总结:封装,将对象的数据隐藏在内部,不让外界直接访问,而是通过提供的属性访问set/get方法完成数据的访问和赋值,在set/get方法中添加访问条件限制,完成私有数据的保护
继承
继承主要体现了基于类的代码复用性,通过继承关系关联两个类
有了继承关系,在子类中可以使用父类中的公共属性和方法,复用了父类的代码
基本语法:
class Father:
父类
class Son(Father):
子类
在子类中可以在父类的基础上扩展方法
扩展属性:
调用父类的初始化方法{子类中编写初始化方法,父类的方法不会直接调用,必须手动调用}
def__init__(self,name,age,gender,level)
# 初始化父类方法
super().__init__(name,age,gender)
继承关系中,子类也可以通过__bases__属性查看当前类型继承的父类信息
方法的覆盖:
在继承中,子类中可以重新编写父类中相同名称的属性或者方法,方法的重新编写称为方法的覆盖(子类的方法覆盖了父类同名的方法)或者方法重写(子类重写了父类继承过来的方法)
多继承
多继承模式下继承顺序,使用了广度优先的查询原则
python提供了mro()方法用于确认继承关系中属性和方法的查询操作顺序
在子类中使用suoer() 指向的是mro当中的顺序
class A:
def func0(self):
print("我是父类A")
class B:
def func1(self):
print("我是父类B")
class C(A,B):
def func2(self):
self.func0()
self.func1()
多态
一个对象的多种状态,多态只是一种表现形式,没有固定格式,体现的是程序运行过程中的状态改变和行为的多样性
可以通过继承关系来完成角色的关系互换
可以通过继承中的方法重写,完成行为方法的切换
可以通过代码结构的设计,完成行为的多样性
拓展
__str__与__repr__方法
这两个方法都是打印对象的方法
其两者的区别在于:
str方法是直接打印对象时调用的该方法
repr方法是在其他对象中(如列表、元组)中打印时调用
例:
class User:
def __init__(self, name, age, nickname):
self.name = name
self.age = age
self.nickname = nickname
# __str__() # 当我们打印对象时自动执行
def __str__(self):
"""在打印对象时自动调用str放法"""
return f"< User user({self.name},{self.age},{self.nickname})>"
# repr 当对象在其他对象中 打印时
def __repr__(self):
"""当对象在其他对象中(列表,元组) 打印时调用的是repr方法"""
return f"< User user({self.name},{self.age},{self.nickname})>"
# 实例化对象
xw = User('小王',18,'小王吧')
# 这里调用的是__str__方法
print(xw) # <__main__.User object at 0x0000000002662888>
# 这里调用的是__repr__方法
lis = (xw,)
print(lis)