面向对象的三大特征:封装、继承、多态
文章目录
一、封装
<1>什么是封装?
封装(Encapsulation)是将类中的某些部分(某些属性或者方法)隐藏起来。
对象不能直接使用隐藏起来的属性或者方法,具有保护功能。
格式:属性或方法前加 ‘双下划线’。(也可以叫私有属性或方法)
目的:影藏对象的属性和方法实现的细节,仅对外提供公共访问方式。
注意:私有属性/方法,只能在类的内部使用
简单实例:
#私有化封装:在属性或者方法前加下划线
class Student():
__name='小强'#私有属性
def __score(self):#私有方法
print('这是一个私有化方法,只能在对象/类中使用')
<2>私有属性
格式:__属性名=值 ()
在类的外部不能使用(对象不能调用私有属性)
<3>私有方法
私有方法:在方法前添加双下划线 例如 __send_message()
私有方法的作用:就是在开发的过程中保护核心代码。
在类的外部不能使用(对象不能调用私有方法)
以下示例:
class A():
def test1(self):
print('我是方法1:普通方法')
def __test2(self):
print('我是方法2:私有方法,只能在元素中调用')
def test3(self):
print('我是方法3:普通方法,函数内调用方法2')
self.__test2()
print(A)
a=A()
a.test1()
#输出:调用了函数内的不同方法
a.test2()
#输出:报异常(A类中没有这个方法)'A' object has no attribute 'test2'
a.test3()
#输出以下两行:
# 我是方法3:普通方法,函数内调用方法2
# 我是方法2:私有方法,只能在元素中调用
<4>私有化封装后的限制
位置 | 是否可以访问 |
---|---|
类中 | 可以访问 |
类外/对象外 | 不可以访问 |
子类/子类对象 | 不可以访问 |
查看私有属性
注意事项:
1.在python中实现的封装操作,不是通过权限限制而是通过改名(name mangling 改名策略)实现的,名字变了找不到而已。
2.可以使用 __dict__可以查看属性(包括私有属性)的值
在类的内部使用私有属性,python内部会自动进行转换成: _类名__属性名。
在类的外部不能给对象添加私有属性因为不能转换成:_类名__属性名类型。
以下实例:
#查看私有属性
class Student():
def __init__(self,name,sex,score):
self.name=name
self.sex=sex
self.__score=score
def get_info(self):
print(self.name,self.sex,self.__score)
student_1=Student('小红','女',89)
print(student_1.__dict__)#获取student_1的所有属性
#输出{'name': '小红', 'sex': '女', '_Student__score': 89}
student_1.get_info()#
#输出:小红 女 89
student_1.name='老王' #看看能不能改个名字?
student_1.get_info()
#输出:老王 女 89 #这方法可行
student_1.__score='99' #那这中方法能修改私有属性吗?
student_1.get_info()
#老王 女 89 #显然不行
调用私有属性并修改私有属性的值
#查看私有属性
class Student():
def __init__(self,name,score):
self.name=name
self.__score=score
def get_score(self):
print( self.__score)
xiaohong=Student('小红',30)#创建一个实例
#1.查看所有的属性(注意私有属性的显示格式)
print(xiaohong.__dict__)#调用/查看对象的所有属性
#输出:{'name': '小红', '_Student__score': 30}
#2.外部修改私有属性
xiaohong._Student__score=60
#3查看是否修修改成功
print(xiaohong._Student__score)
#输出:60 修改成功
二、继承
在说继承之前,咱们先看一张图:
在高中生物有学到生物在遗传学上的分类方式,自上而下分别是:界门纲目科属种。
脑海中有这个概念,对理解继承会有很大的帮助。
<1>什么是继承
继承就是让类和类之间产生父子关系,子类可以拥有父类的静态属性和方法。
[继承就是可以获取另外一个类中的静态属性和普通方法。(并非所有成员)]。
在python中,新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类。
注意:python中的继承分为:单继承和多继承。
<2>子类与父类的概念
父类:用于被继承的类,也叫做基类、超类
子类:继承父类
<3>继承的做哦那个
<3>继承的作用
在详细说明继承时我们先来看一段代码示例:
1、创建Boys类和Girls类,分别设置name 、age 、sex属性
2、Boys类定义两个方法:basketball方法、football方法
3、Girls类定义两个方法:piano方法、guitar方法
使用常规方法创建:
class Boys():
def __init__(self,name,age,sex):
self.name=name
self.age=age
self.sex=sex
def introduce_self(self):
print('我叫:%s,我的年纪是:%d岁,我是%s生'%(self.name,self.age,self.sex))
def needStudy(self):
print('好好学习,天天向上')
def basketball(self):
print('Boys %s会打篮球'%(self.name))
def football(self):
print('Boys %s会踢足球' % (self.name))
class Girls():
def __init__(self,name,age,sex):
self.name=name
self.age=age
self.sex=sex
def introduce_self(self):
print('我叫:%s,我的年纪是:%d岁,我是%s生'%(self.name,self.age,self.sex))
def needStudy(self):
print('好好学习,天天向上')
def piano(self):
print('Girls %s会弹钢琴'%(self.name))
def guitar(self):
print('Boys %s会弹吉他' % (self.name))
使用常规方法创建我们发现,Boys类与Girls类中有大量重复的代码。翘起来费事费力。
前辈们担心我们打代码太累了,开发了继承来帮我们减负。
继承最大的作用:提高代码的复用率
使用继承的方式,重写刚才的代码
class Student():
def __init__(self,name,age,sex):
self.name=name
self.age=age
self.sex=sex
def introduce_self(self):
print('我叫:%s,我的年纪是:%d岁,我是%s生'%(self.name,self.age,self.sex))
def needStudy(self):
print('好好学习,天天向上')
class Boys(Student):
def basketball(self):
print('Boys %s会打篮球' % (self.name))
def football(self):
print('Boys %s会踢足球' % (self.name))
class Girls(Student):
def piano(self):
print('Girls %s会弹钢琴' % (self.name))
def guitar(self):
print('Boys %s会弹吉他' % (self.name))
解决方法 | 代码行数 | 特点 |
---|---|---|
普通方式 | 26行 | 容易编写,但后续修改会比较麻烦 |
继承方式 | 19行 | 结构清晰 |
<4>查看继承的父类
格式:类名.bases
注意:
(1)Python3中如果一个类没有继承任何类,则默认继承object类。我们管这种类叫做新式类。
(2)object类,是python中的祖宗,所有的类都是从object类中继承下来的。
#接上文程序
#查看继承的父类
print(Student.__bases__)#(<class 'object'>,)
print(Girls.__bases__)#(<class '__main__.Student'>,)
<5>方法的覆写
子类中定义了和父类中相同的方法,我们叫做方法的复写(派生方法)。实例对象调用此方法 的时候就会调用自己类中的方法了。
例:定义一个Person类创建eat()方法,定义一个Teacher的类,创建reading()方法,规定学生去食堂吃饭,定义一个reading类创建eat()方法,规定Boss去酒店吃。
#方法覆写
class People():
def reading(self):
print('People在看书')
class Student(People):#这里继承了People类
def reading(self):#Overrides
print('Student在看书')
class Teacher(People):#这里也继承了People类
def reading(self):#Overrides
print('Teacher在看书')
human=People()
human.reading()#输出:People在看书
student_lili=Student()
student_lili.reading()#输出:Student在看书
teacher_wang=Teacher()
teacher_wang.reading()#输出:Teacher在看书
在IDE中的提示 (PyCharm):
<6>super()
super()函数是用来调用父类的一个方法
子类和父类有相同的方法,如果子类想调用父类相同的的方法。可以使用super()方法。
super 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,
会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题。
class Dog():
def bite(self):
print('汪汪汪')
class Huskie(Dog):
def bite(self):#Overrides
print('wuwuwuw')
#第一种方法 :使用super()函数
super().bite()
#第二种方法
Dog.bite(self)
huskie=Huskie()
huskie.bite()
#输出
wuwuwuw
汪汪汪
汪汪汪
在函数外部也可调用super()
格式:super(父类,子类).父类的方法
super(Huskie,huskie).bite()#可在函数外使用super()
<7>init()方法
-子类继承父类,如果子类不覆写父类的__init__()方法,创建子类对象的时候会自动调用父类的__init__()方法
-子类继承父类,如果子类覆写了父类的__init__()方法,创建子类对象时不会再覅偶用父类的__init__()方法
- **注意:**python要求复习父类的__init__()方法时,需要调用父类的__init__()
因为存在隐患,例如父类的初始化方法有参数,子类初始化无参数,子类再调用父类
的参数的时候就会报错。
<8>派生属性
pass
<9>私有属性私有方法在继承中的表现
父类中的私有方法和私有属性都是不能被子类继承。
三、多态特性
声明形参的时候是父类对象,实际运行的时候是子类对象
其实在Python中,列表,字典都是多态的体现
class Pay():
def pay(self,money):
pass
class Alipay(Pay):
'支付宝支付'
def pay(self,money):#Overrides
print('使用了支付宝支付了%s元'%money)
class Applepay(Pay):
'苹果支付'
def pay(self,money):#Overrides
print('使用了applepay支付了%s元'%money)
class Customer():
def consumption(self,pay,money):
pay.pay(money)
alipay=Alipay()
applepay=Applepay()
customer_1=Customer()
#使用支付宝支付
customer_1.consumption(alipay,100)
#使用苹果支付'
customer_1.consumption(applepay,98)