春风桃李花开夜,秋雨梧桐叶落时——python面向对象三大特征(封装、继承、多态)

九重城阙烟尘生,千乘万骑西南行。
翠华摇摇行复止,西出都门百余里。
六军不发无奈何,宛转娥眉马前死。
花钿委地无人收,翠翘金雀玉搔头。
君王掩面救不得,回看血泪相和流。
黄埃散漫风萧索,云栈萦纡登剑阁。
峨嵋山下少人行,旌旗无光日色薄。
蜀江水碧蜀山青,圣主朝朝暮暮情。
行宫见月伤心色,夜雨闻铃肠断声。
天旋日转回龙驭,到此踌躇不能去。
马嵬坡下泥土中,不见玉颜空死处。
君臣相顾尽沾衣,东望都门信马归。
归来池苑皆依旧,太液芙蓉未央柳。
芙蓉如面柳如眉,对此如何不泪垂?
春风桃李花开夜,秋雨梧桐叶落时。
西宫南苑多秋草,落叶满阶红不扫。
梨园弟子白发新,椒房阿监青娥老。
夕殿萤飞思悄然,孤灯挑尽未成眠。
迟迟钟鼓初长夜,耿耿星河欲曙天。
鸳鸯瓦冷霜华重,翡翠衾寒谁与共?
悠悠生死别经年,魂魄不曾来入梦。


封装、继承、多态是面向对象的三大特征

1 封装

  • 封装体现的是对于对象数据安全的保护性(对隐私数据的保护)
  • 封装使属性的操作更加灵活可控,可以按照需求的描述对属性进行限制性访问,提高属性的安全性

1.1 封装(私有化)语法

命名:

  • 变量使用两个下划线开头,在类型和对象的外部不能直接去访问,因为语法上该变量名称是私有的,如: __name
  • 约定语法,使用一个下划线开头,约定在类型和对象外部不要直接去访问(虽然在语法上是可以访问的),如:_name
class Person:
    """类:人"""

    def __init__(self, name, action):
        self.name = name
        self.__action = action

私有属性方法:

  • 给每个属性提供set(赋值)/get(访问)方法,通过固定语法提供给外部调用者

私有属性赋值:

def set_action(self, action):
       """设置私有属性action"""
       self.__action = action


# 也有写成双下划线的(一般用单下划线):
def set__action(self, action):
       """设置私有属性action"""
       self.__action = action

获取私有属性数据:

def get_action(self):
    """获取私有属性action"""
    return self.__action
    

# 双下划线写法(一般用单下划线)
def get__action(self):
    """获取私有属性action"""
    return self.__action

外部需要通过set和get方法调用私有属性:

class Person:
    """类:人"""

    def __init__(self, name, action):
        self.name = name
        self.__action = action

    def set_action(self, action):
        """设置私有属性action"""
        self.__action = action

    def get_action(self):
        """获取私有属性action"""
        return self.__action


# 创建对象
an = Person("安禄山", "叛乱")

# print(an.action)  # name 'action' is not defined # 私有属性不能直接访问,会报错

print(an.get_action())  # 叛乱  # 通过get方法获取

an.set_action("胡旋舞")  # 修改私有属性
print(an.get_action())  # 胡旋舞

# 用以下方法修改并不能修改原私有属性,只是新增了一个属性
an.__action = "跳舞"
print(an.get_action())  # 胡旋舞  # 属性值没有改变

set方法与__init__区别:

  • __init__:给属性赋初始值,初始化对象属性数据
  • set方法:给已有对象修改属性数据

1.2 限制条件(数据保护)

在set/get方法中添加条件限制

def set_action(self, action):

    if 2 <= len(action) <= 10:
        self.__action = action
    else:
        print("长度不符合要求")


def get_action(self, action):
    return __action

1.3 私有类属性和私有方法

  • 私有类属性用法相似,也是前面加双下划线封装,不能被外部访问,可以被类内部访问
  • 类似的,私有方法是在方法前面加两个下划线
  • 可用于保护核心代码,只能在类的内部调用,外部对象不能(直接)调用
def __test():
    pass

2 继承

通过继承语法,让两个类型之间产生继承关系,子类可以使用父类的属性和方法,达到复用目的

2.1 继承语法

父类和子类:

  • 父类:被继承的类型
  • 子类:继承其他类的当前类型
 - class 子类(父类)
class Person(object):
    """人的类"""
    pass


class Emperor(Person):
    """皇帝的类"""
    pass
  • 在python3中,如果一个类没有继承任何类,默认继承object,声明时可以不写
  • 子类只能继承父类的公共的属性和方法,以及默认的魔法方法。
  • 子类如果不写任何魔法方法,就会继承默认固定格式的魔法方法
  • 私有属性和私有方法不能被继承(理论上)

2.2 __init__()方法的继承

  • 子类不编写该方法,就会默认从父类继承默认格式的该方法__init__(self)
  • 子类编写了__init__()方法,默认继承的__init__()就会被回收
  • 一般子类中写的__init__()方法中都会显式的调用父类的__init__(),初始化父类数据

调用父类的__init__():

# 单继承时是三种写法都可以
# __init__()中需要传递父类相应参数,不需带self
super().__init__()
父类名称.__init__() (多继承用此写法) 
super(子类名称, self).__init__()  # 子类名称即当前类名

子类不写__init__()方法默认继承父类的__init__()方:

class Person(object):
    """人的类"""

    def __init__(self, name, position):
        """初始化类型"""
        self.name = name
        self.position = position


class Emperor(Person):
    """皇帝的类"""
    pass

# 子类不写__init__()方法默认继承父类
li = Emperor("李隆基", "皇帝")

子类中写的__init__()方法中,都会显式的调用父类的__init__(),初始化父类数数据,否则父类的数据就不会被 正确的继承过来:

```python
class Person(object):
    """人的类"""

    def __init__(self, name, position):
        """初始化类型"""
        self.name = name
        self.position = position

class Emperor(Person):
    """皇帝的类"""
    def __init__(self, name, position, gender):
        super().__init__(name, position)  # 主动调用父类__init__(),单继承时三种写法皆可,不需带self
        self.gender = gender  # 写新增的


# 创建子类对象按照子类的的属性
li = Emperor("李隆基", "皇帝", "男")

2.3 方法重写

即子类中重新声明定义了和父类中名称和参数相同的方法

  • 如果子类没有重写父类的方法,在调用执行方法时会找到并执行父类中声明的方法
class Person(object):
    """人的类"""

    def run(self):
        print("逃跑")



class Emperor(Person):
    """皇帝的类"""
    pass


# 创建对象
li = Emperor()
# 没有重新的方法,则使用父类的方法
li.run()  # 逃跑
  • 如果子类中重写了父类的方法,在调用执行方法时就会找到并执行子类的方法
class Person(object):
    """人的类"""

    def run(self):
        print("逃跑")



class Emperor(Person):
    """皇帝的类"""

    # 重写父类方法
    def run(self):
        print("九重城阙烟尘生,千乘万骑西南行")


# 创建对象
li = Emperor()
# 方法被重写,使用子类方法
li.run()  # 九重城阙烟尘生,千乘万骑西南行

2.4 子类访问父类(功能拓展)

  • 父类的方法中完成基础功能的处理
  • 子类重写父类方法,调用父类的方法完成基础操作,同时扩展新的功能

三种访问形式:

super().方法名称() 
super(子类名称, self).方法名称()  # 子类名称即当前类名
父类名称.方法名称()  # 注意是否需要带参数self,另外两种方法不需带
class Person(object):
    """宫殿类"""

    def dream(self):
        print("做梦")


class Emperor(Person):
    """皇帝的类"""

    # 重写父类方法
    def dream(self):
        super().dream()  # 访问类方法,并拓展功能
        print("鸳鸯瓦冷霜华重,翡翠衾寒谁与共?")
        print("悠悠生死别经年,魂魄不曾来入梦。")


# 创建对象
li = Emperor()
# 方法被重写,且在父类基础上拓展
li.dream() 

# 做梦
# 鸳鸯瓦冷霜华重,翡翠衾寒谁与共?
# 悠悠生死别经年,魂魄不曾来入梦。

2.5 多继承

  • 将继承的类型依次(有顺序)声明在类型后面的括号中,描述当前类型继承的所有类型
  • 当前类型就会拥有所有继承类型的公共的属性和公共的方法
  • 语法:class 子类(父类1, 父类2,父类3…)
  • 当多个父类中出现了相同名称的属性和方法,子类在使用时,按照广度优先进行查询(先按继承顺序在同级父类查询,然再向上一级父类查询)
  • 查询顺序:类名.mro()或类名.__mro__(),python继承顺序就是根据该方法方法解析顺序列表进行查找(子类会先于父类被检查 > 多个父类会根据他们在列表中的顺序被检查 > 如果对下一个类存在两个合法选择,选择第一个父类)
class Flower:

    def test(self):
        print("芙蓉如面柳如眉")

    def open(self):
        print("春风桃李花开夜")


class Tree:

    def test(self):
        print("对此如何不泪垂")

    def leaf(self):
        print("秋雨梧桐叶落时")


class Plant(Flower, Tree):
    pass


plant = Plant()
# 继承所有类型的公共属性和方法
plant.open()  # 春风桃李花开夜
plant.leaf()  # 秋雨梧桐叶落时
# 方法重名按继承顺序查找
plant.test()  # 芙蓉如面柳如眉

2.6 抽象类

3 多态

  • 多态是程序运行过程中,根据运行时的数据和条件的差异,产生不同的处理状态,运行不同的逻辑代码的过程
  • 多态没有固定的语法,有多种体现方式
  • 特点:拓展性强、动态调用
class Plant:

    def shape(self):
        print("不同的东西的不同状态")

    def desc(self):
        self.shape()


class Hibiscus(Plant):

    def shape(self):
        print("芙蓉如面柳如眉")


class PeachBlossom(Plant):

    def shape(self):
        print("春风桃李花开夜")


class ChineseParasol(Plant):

    def shape(self):
        print("秋雨梧桐叶落时")


# 根据不同对象调用对象里的继承的同名方法,但结果不同(类似策略模式)
plant = Plant()
plant.desc()  # 不同的东西的不同状态

flower = Hibiscus()
flower.desc()  # 芙蓉如面柳如眉

flower2 = PeachBlossom()
flower2.desc()   # 春风桃李花开夜

tree = ChineseParasol()
tree.desc()  # 秋雨梧桐叶落时
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值