目录
Python之第十一章 面向对象 --- 三大特征
面向对象三大特征 --- 封装
1.在Python代码中,封装有两层含义:
2.封装中的私有属性和私有方法
3.私有属性的访问限制
4.私有属性设置与访问接口
5.私有方法
6.封装的意义
7.@property装饰器封装
面向对象三大特征 --- 继承
1.继承的基本概念
2.名词解释
3.继承的基本语法
4.单继承
5.多继承
6.方法重写
7.super关键字
面向对象三大特征 --- 多态
1.概念
2.实例
3.优点
Python之第十一章 面向对象 --- 三大特征
面向对象三大特征 --- 封装
1.在Python代码中,封装有两层含义:
把现实世界中的主体中的属性和方法书写到类的里面的操作,这种操作称为封装
class Person():
# 封装属性
# 封装方法
注意:
封装可以为属性和方法添加私有权限
2.封装中的私有属性和私有方法
属性和方法分类 ---
公有(属性、方法):无论在类的内部还是外部都可以对属性和方法进行操作
私有(属性、方法):外部直接应用或修改类内部的数据不安全,所以不允许在类的外部对类内部的属性和方法进行操作 --- 通过封装私有属性或方法实现
3.私有属性的访问限制
方法 --- 在属性名或方法名前面增加两个下划线
例:
class Girl():
def __init__(self, name):
self.name = name
self.__age = 18 # 私有属性
fangfang = Girl('方方')
print(fangfang.name)
print(fangfang.__age) # 报错 无法访问
注意:
以上代码运行可知,私有属性不能在类的外部访问,若需要在外部访问私有属性可以通过定义访问接口(函数)来实现
类中的私有属性和方法不能被类继承
4.私有属性设置与访问接口
Python中一般定义函数名为‘get_xx’都是用来获取私有属性,通过‘set_xxx’来修改私有属性
例:
class Girl():
def __init__(self, name):
self.name = name
self.__age = 18 # 私有属性
def get_age(self): # 用于引用访问属性
# 本人访问时直接访问
# 外人访问时加上限制条件
return self.__age
def set_age(self, age): # 用于修改属性
self.__age = age
fangfang = Girl('方方')
fangfang.set_age(19)
print(fangfang.name)
print(fangfang.get_age())
5.私有方法
定义方式与私有属性基本一致,在方法名前面增加两个下划线 _ _ 方法名()
6.封装的意义
封装数据属性 --- 明确区分内外,控制外部对隐藏的属性进行操作
例:
class People():
def __init__(self, name, age):
self.__name = name
self.__age = age
def tell_info(self):
print('Name:<%s> Age:<%s>' % (self.__name, self.__age))
def set_info(self, name, age):
if not isinstance(name, str): # isinstance()判断name是否为字符串
print('名字必须为字符串类型')
return
if not isinstance(age, int): # 判断age是否为整数型
print('年龄必须为数字')
self.__name = name
self.__age = age
p = People('jack', 18)
p.tell_info()
p.set_info('andy', 10)
p.tell_info()
p.set_info(123, 19)
p.tell_info()
结果:
Name:<jack> Age:<18>
Name:<andy> Age:<10>
名字必须为字符串类型
Name:<andy> Age:<10>
封装方法的意义 --- 降低程序复杂度
class Atm:
def __card(self):
print('请插卡')
def __auth(self):
print('用户认证')
def __input(self):
print('请输入取款金额:')
def __print_bill(self):
print('打印账单')
def __take_money(self):
print('取款')
def withdraw(self): # 定义一个对外提供服务的公共方法
self.__card()
self.__auth()
self.__input()
self.__print_bill()
self.__take_money()
atm = Atm()
atm.withdraw()
7.@property装饰器封装
作用 --- 通过@property装饰器讲一个方法转为属性,从而实现用于计算的属性,转换后可以通过方法名来访问,不需要小括号,代码更简洁
格式 ---
@property
def 方法名(self):
方法体
方法名要求小写,最后作为属性名存在
方法体中一般return结束
例
class Rect():
def __init__(self, width, height):
self.width = width
self.height = height
@property
def area(self):
return self.width * self.height
rect = Rect(600, 800)
print('面积为:', rect.area) # 调用时方法名变为属性,不需要小括号
面向对象三大特征 --- 继承
1.继承的基本概念
类是用来描述现实世界中同一组事物的共有性的抽象模型
类也有上下级和范围之分,如:生物->动物->不如动物->灵长类动物->人类->黄种人
描述共性和个性之间的关系
2.名词解释
继承 --- 一个类从另一个已有的类获得其他成员的相关特性,称为继承
派生 -- 从一个已有的类产生一个新的类,称为派生
注意:
继承和派生其实是从不同角度方向来描述相同的概念,本质上为一个东西
父类 --- 也称为基类,就是指已有被继承的类
子类 --- 也称为派生类和扩展类
扩展 --- 在子类中增加一些自己特有的特性,称为扩展,没有扩展则继承无意义
单继承 --- 一个类只能继承自一个其他的类,不能继承多个其他类。使用较多
多继承 --- 一个类共同继承了多个父类
3.继承的基本语法
假设A类要继承B类中的所有属性和方法(私有除外)
class B(object):
pass
class A(B): # A继承B
pass
a = A()
例:Person类与Teacher、Student类之间的继承
class Person(object):
def eat(self):
print('i an eat food !')
def speak(self):
print('i can speak !')
class Teacher(Person): # 继承Person类
pass
class Student(Person):
pass
teacher1 = Teacher()
teacher1.eat()
teacher1.speak()
student1 = Student()
student1.eat()
student1.speak()
4.单继承
单继承 --- 一个类能继承自一个其他类,不能多继承
格式 ---
1.定义一个父类
class Person(object):
pass
2.定义一个子类
class Teacher(Person):
pass
类object --- 类object是所有类的父类,在该类中定义了所有类的公有默认方法,如:new( )、 init( ),当定义类时,只有类名没有继承相关参数,此时可以省略object
单继承 --- 具有传递性 如:A类继承B类,B类继承C类,根据传递性,A类也就会自动继承C类中的所有公共属性和方法。
5.多继承
定义 --- Python少数几个支持多继承的语言,允许一个类继承多个类
格式 ---
class B(object):
pass
class C(object):
pass
class A(B,C):
pass
例:
class GasolineCar(object): # 汽油车
def run_with_gasoline(self):
print('I can with gasoline')
class EletriCar(object): # 电动车
def run_with_eletric(self):
print('I can with eletric')
class HybridCar(GasolineCar, EletriCar):
pass
tesla = HybridCar()
tesla.run_with_eletric()
tesla.run_with_gasoline()
注意:
尽量少用多进程,容易造成名称冲突
6.方法重写
扩展特性 --- 继承让子类拥有了父类的所有公共属性和方法,但如果仅仅是为了继承属性和方法就失去了继承的意义,应该子类拥有自己的属性和方法
重写 --- 也叫做覆盖,子类成员与父类成员名字相同时,从父类继承的成员会重新定义,此时起效的为子类中定义的成员
注意:
类方法的调用顺序 --- 先在子类中查找,若找不到则在父类中查找
7.super关键字
super()--- 调用父类属性和方法
完整的写法:
super(当前类名称,self).属性或方法()
Python3版本以后
super().属性
# 或
super()方法名()
例:Car
class Car(object):
def __init__(self, brand, model, color):
self.brand = brand
self.model = model
self.color = color
def run(self):
print('I can run')
class GasolineCar(Car): # 继承Car类
def __init__(self, brand, model, color):
super().__init__(brand, model, color) # 调用父类Car的__init__()方法
def run_with_gasoline(self):
print('I can with gasoline')
class EletriCar(Car): # 电动车父类
def __init__(self, brand, model, color):
super().__init__(brand, model, color)
self.battery = 70
def run(self):
print(f'I can run with eetric,remain:{self.battery}')
bmw = GasolineCar('宝马', 'x5', '白色')
bmw.run()
tesla = EletriCar('特斯拉', 'Model S', '黑色')
tesla.run()
MRO属性或方法
作用 --- 获得类的层次结构
格式 ---
类名.__mro_ _
#或
类名.mro()
例:上述Car的例子
class Car(object):
def __init__(self, brand, model, color):
self.brand = brand
self.model = model
self.color = color
def run(self):
print('I can run')
class GasolineCar(Car): # 继承Car类
def __init__(self, brand, model, color):
super().__init__(brand, model, color) # 调用父类Car的__init__()方法
def run_with_gasoline(self):
print('I can with gasoline')
class EletriCar(Car): # 电动车父类
def __init__(self, brand, model, color):
super().__init__(brand, model, color)
self.battery = 70
def run(self):
print(f'I can run with eetric,remain:{self.battery}')
print(EletriCar.__mro__) # 查看集成化层次结构
print(EletriCar.mro())
结果:
(<class '__main__.EletriCar'>, <class '__main__.Car'>, <class 'object'>)
[<class '__main__.EletriCar'>, <class '__main__.Car'>, <class 'object'>]
面向对象三大特征 --- 多态
1.概念
指事物的多种状态,是一种适用对象的放射式,子类重写了父类方法,调用不同子类对象时的相同父类方法,可以产生不同的执行结果。
-
多态依赖于继承
-
子类方法必须重写父类方法
过程 --- 首先定义一个父类,其可能拥有多个子类对象,当调用一个公共方法时,传递的对象不同则返回结果不同
公共接口 --- 是多态的体现,随着传入参数不同,返回结果不同
2.实例
class Fruit(object):
# 公共方法
def makejuice(self):
print('I can make juice')
class Apple(Fruit):
def makejuice(self):
print('I can make apple juice')
class Banana(Fruit):
def makejuice(self):
print('I can make banana juice')
class Orange(Fruit):
def makejuice(self):
print('I can make orange juice')
class Peach(Fruit):
def makejuice(self):
print('I can make peach juice')
# 定义公共接口,相当于上述类的进入接口
def servce(obj):
obj.makejuice()
apple = Apple()
banana = Banana()
orange = Orange()
peach = Peach()
for i in (apple, banana, orange, peach):
servce(i)
结果:
I can make apple juice
I can make banana juice
I can make orange juice
I can make peach juice
3.优点
调用灵活,有了多态,更容易编写通用代码,实现通用的编程,适应不同变化需求