Python面向对象进阶:深入解析面向对象三要素——封装、继承与多态

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: Python面向对象进阶:深入解析面向对象三要素——封装、继承与多态

前言

    Python面向对象编程的核心在于封装、继承和多态。封装隐藏细节,继承实现重用,多态提升灵活。本文将深入解析这三大要素,助您掌握面向对象编程的精髓。面向对象基础详解请看上一篇,点这!!!


一、面向对象三要素

继承:子类继承父类,子类拥有了父类的属性和方法。降低代码的重复性

封装:将对象的属性和实现细节进行封装,仅对外提供公共的访问方式。提高代码 的安全性;使用私有属性和私有方法实现封装

多态:不同的对象调用父类相同的方法获取不同的执行结果。多态实现需要:继承、方法重写


二、继承

1.概念

概念:子类继承父类,子类拥有了父类的属性和方法;降低代码的重复性

继承–>派生 子类–>派生类 父类–>基类

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
warnings.filterwarnings('ignore')
import  ssl
ssl._create_default_https_context = ssl._create_unverified_context

2.简单继承

# 简单继承
class A:
    def __init__(self):
        self.money = "一个亿"
    def car(self):
        print("一辆黑色的帕拉梅拉")
class B(A):
    pass
b = B()
print(b.money)   # 子类继承了父类,子类对象可以获取父类的属性
b.car()  # 子类继承了父类,子类对象可以调用父类的方法

3.单继承

# 单继承:一个子类继承一个父类
class Master:
    def __init__(self):
        self.kongfu = "古法煎饼果子配方"
    def make_cake(self):
        print(f"使用{self.kongfu}制作出古法煎饼果子")
class Cat(Master):
    pass
cat = Cat()
print(cat.kongfu)
cat.make_cake()

4.多继承

# 多继承:一个子类继承多个父类
class Master:
    def __init__(self):
        self.kongfu = "古法煎饼果子配方"
        self.m_money = "100"
    def make_cake(self):
        print(f"使用{self.kongfu}制作出古法煎饼果子")
    def master_house(self):
        print("老师傅的茅草屋")
class School:
    def __init__(self):
        self.kongfu = "现代煎饼果子配方"
        self.s_money = "1000"
    def make_cake(self):
        print(f"使用{self.kongfu}制作出现代煎饼果子")
    def school_house(self):
        print("学校的宿舍")
class Cat(School,Master):
    pass
cat = Cat()
print(cat.kongfu)
cat.make_cake()
cat.master_house()
cat.school_house()
print(cat.s_money)
# print(cat.m_money)
# 多继承的继承顺序   __mro__
# 语法:子类.__mro__
print(Cat.__mro__)
- 多继承可以继承多个父类,也继承了所有父类的属性和方法
- 注意:如果多个父类中有同名的 属性和方法,则默认使用第一个父类的属性和方法(根据类的魔法属性**mro**的顺序来查找)
- 多个父类中,不重名的方法,不会有任何影响。

5.单继承的多层继承

# 多继承:一个子类继承多个父类
# 单继承的多层继承:
class GrandFather:
    def __init__(self):
        self.money = "一个亿"
    def house(self):
        print("一栋中式装修风格的大别墅")
class Father(GrandFather):
    def __init__(self):
        self.money = "两个亿"
    def house(self):
        print("一栋欧式装修风格的大别墅")
    # 获取grandfather的money属性
    def get_grand_money(self):
        # 第一种方式:类名.__init__(self)
        # 第二种方式:super().__init__()
        super().__init__()
        print(f"获取父类的money值为:{self.money}")
    # 调用grandfather的house方法
    def get_grand_house(self):
        # 第一种方式:类名.方法名()
        # 第二种方式:super().方法名()
        super().house()
class Son(Father):
    def __init__(self):
        self.money = "10"
    def house(self):
        print("学校的宿舍")
    # 子类获取父类的属性
    def get_father_money(self):
        # 第一种方式:类名.__init__(self)
        # 第二种方式:super().__init__()
        super().__init__()
        print(f"获取父类的money值为:{self.money}")
    # 子类调用父类的方法
    def get_father_house(self):
        # 第一种方式:类名.方法名()
        # 第二种方式:super().方法名()
        super().house()
son = Son()
print(son.money)
son.house()
son.get_father_money()
son.get_father_house()
son.get_grand_money()
son.get_grand_house()

6.子类重写父类方法

# 子类重写父类同名方法
class Master:
    def __init__(self):
        self.kongfu = "古法煎饼果子配方"
    def make_cake(self):
        print(f"使用{self.kongfu}制作出古法煎饼果子")
class School:
    def __init__(self):
        self.kongfu = "现代煎饼果子配方"
    def make_cake(self):
        print(f"使用{self.kongfu}制作出现代煎饼果子")
class Cat(School,Master):
    # 在子类中定义与父类相同名字的属性和方法
    def __init__(self):
        self.kongfu = "猫式煎饼果子配方"
    def make_cake(self):
        print(f"使用{self.kongfu}制作出猫式煎饼果子")
# 如果子类和父类的方法名和属性名相同,则默认使用子类的
cat = Cat()
print(cat.kongfu)   # 子类与父类有相同名字的属性,默认使用子类的属性
cat.make_cake() # 子类与父类有相同名字的方法,默认调用子类的方法
# 多继承的继承顺序   __mro__
# 语法:子类.__mro__
print(Cat.__mro__)

7.子类获取父类的属性和方法

# 子类调用父类同名属性和方法
class Master:
    def __init__(self):
        self.kongfu = "古法煎饼果子配方"
    def make_cake(self):
        print(f"使用{self.kongfu}制作出古法煎饼果子")
class School:
    def __init__(self):
        self.kongfu = "现代煎饼果子配方"
    def make_cake(self):
        print(f"使用{self.kongfu}制作出现代煎饼果子")
class Cat(School,Master):
    # 在子类中定义与父类相同名字的属性和方法
    def __init__(self):
        self.kongfu = "猫式煎饼果子配方"
    def make_cake(self):
        print(f"使用{self.kongfu}制作出猫式煎饼果子")
    # 调用School类中的同名属性和方法
    # super()在多继承中只能获取第一个父类的同名属性和方法
    def get_school(self):
        # 获取父类同名属性:super().__init__()
        super().__init__()
        print(f"获取到的配方为{self.kongfu}")
        # 调用父类同名方法:super().方法名()
        super().make_cake()
    # 调用Master类中的同名属性和方法
    # 类名.的方式可以获取任意一个父类的同名属性和方法
    def get_master(self):
        # 获取父类同名属性:类名.__init__(self)
        Master.__init__(self)
        print(f"获取到的配方为{self.kongfu}")
        # 调用父类同名方法:类名.方法(self)
        Master.make_cake(self)
cat = Cat()
cat.get_school()
cat.get_master()

注意:

在不进行方法重写和获取方法之前
如果子类继承了一个父类,且子类中没有init。则初始化父类的init,获取父类的属性
如果子类继承了多个父类,且子类中没有init。则初始化第一个父类的init,获取第一个父类的属性
如果子类继承了多个父类,且子类中有init。则初始化子类本身的init,所有的父类的属性都无法获取

三、封装

1.概念

将对象的属性和实现细节隐藏起来,仅对外提供公共访问方式。提高代码的安全性

使用私有属性和私有方法实现

2.私有属性

2.1定义私有属性

class MyCls:
    def __init__(self):
        self.money = 100
        # 将属性设置为私有属性   在属性名前__
        self.__mimi = "我有一个小秘密"
my = MyCls()
print(my.__mimi)  # 对象获取不到私有属性

2.2 获取私有属性

class MyCls:
    def __init__(self):
        self.money = 100
        # 将属性设置为私有属性   在属性名前__
        self.__mimi = "我有一个小秘密"
    # 获取私有属性:通过定义公共的实例方法,在实例方法中使用私有属性
    # 私有属性只是不能在类外获取,但是可以提供在类内部进行使用;用于处理类内部的操作
    def get_mimi(self):
        print(f"获取到的私房钱为:{self.__mimi}")
my = MyCls()
my.get_mimi()

2.3 修改私有属性的值

class MyCls:
    def __init__(self):
        # 将属性设置为私有属性   在属性名前__
        self.__mimi = "我有一个小秘密"
    # 修改私有属性的值:通过定义公共的实例方法,在实例方法中获取私有属性,重新赋值
    def set_mimi(self,str1):
        self.__mimi = str1
        print(f"获取到的秘密为:{self.__mimi}")
my = MyCls()
my.set_mimi("嘿嘿嘿嘿嘿嘿")

3.私有方法

3.1 定义私有方法

class MyCls:
    # 将方法设置为私有方法    在方法名前__
    def __house(self):
        print("我有一个大别墅")
my = MyCls()
my.__house()   # 对象无法调用私有方法

3.2 调用私有方法

class MyCls:
    # 将方法设置为私有方法    在方法名前__
    def __house(self):
        print("我有一个大别墅")
    # 调用私有方法:通过定义公共的实例方法,在公共的方法中调用私有方法
    def get_house(self):
        # 调用私有方法-->实例方法
        self.__house()
my = MyCls()
my.get_house()

4.总结

关于私有属性和私有方法的总结:
私有权限:在属性和方法名前边加上两个下划线 __
1. 类的私有属性 和 私有方法,都不能通过对象直接访问,但是可以在本类内部访问;
2. 类的私有属性 和 私有方法,都不会被子类继承,子类也无法访问;
3. 私有属性 和 私有方法 往往用来处理类的内部事情,不通过对象处理,起到安全作用。

四、多态

1.概念

不同的对象调用父类相同的方法获取到不同的执行结果

多态的实现需要建立在继承方法重写的基础上

2.简单案例

class Animal:
    def bark(self):
        print("动物叫")
class Dog(Animal):
    def bark(self):
        print("小狗汪汪叫")
class Cat(Animal):
    def bark(self):
        print("小猫喵喵叫")
dog = Dog()
cat = Cat()
dog.bark()
cat.bark()

五、补充

1.类对象

# 定义一个英雄类
class Hero:
    # 定义实例属性
    def __init__(self,name):
        self.name = name
    # 定义实例方法
    def kill(self):
        print(f"{self.name}英雄会杀人")
# 实例化一个对象-->实例对象
luban = Hero("鲁班")
# 实例对象获取实例属性
print(luban.name)
# 实例对象调用实例方法
luban.kill()
# 类对象-->类本身-->类名
print(Hero)
# 类对象无法获取实例属性
# 类对象无法调用实例方法

2.类属性

# 定义一个英雄类
class Hero:
    # 类属性:直接在定义类的类名下 属性名 = 属性值
    class_name = "英雄类"
# 实例化一个对象-->实例对象
luban = Hero("鲁班")
# 实例对象获取类属性
print(luban.class_name)
# 类对象-->类本身-->类名
print(Hero)
# 类对象获取类属性
print(Hero.class_name)

3.类方法

# 定义一个英雄类
class Hero:
    # 定义类方法,需要借助装饰器 classmethod  实现定义类方法
    # 装饰器用法:想要将哪一个方法创建为类方法,在该方法上方 @装饰器
    # 创建好的类方法自带参数cls;cls-->类对象本身
    @classmethod
    def run(cls):
        print("英雄会跑")
# 实例化一个对象-->实例对象
luban = Hero("鲁班")
# 实例对象调用类方法
luban.run()
# 类对象-->类本身-->类名
print(Hero)
# 类对象调用类方法
Hero.run()

4.静态方法

# 定义一个英雄类
class Hero:
    # 定义静态方法,需要借助装饰器   staticmethod  实现定义静态方法
    @staticmethod
    def eat():
        print("英雄会吃")
# 实例化一个对象-->实例对象
luban = Hero("鲁班")
# 实例对象调用静态方法
luban.eat()
# 类对象-->类本身-->类名
print(Hero)
# 类对象调用静态方法
Hero.eat()

5.属性在方法中的使用

# 定义一个英雄类
class Hero:
    # 类属性:直接在定义类的类名下 属性名 = 属性值
    class_name = "英雄类"
    # 定义实例属性
    def __init__(self,name):
        self.name = name
    # 定义实例方法
    def kill(self):
        # 实例对象可以获取实例属性,实例方法中使用实例属性   self.实例属性名
        # 实例对象可以获取类属性,实例方法中使用类属性    self.类属性名
        print(f"{self.name}英雄属于{self.class_name}")
    # 定义类方法,需要借助装饰器 classmethod  实现定义类方法
    # 装饰器用法:想要将哪一个方法创建为类方法,在该方法上方 @装饰器
    # 创建好的类方法自带参数cls;cls-->类对象本身
    @classmethod
    def run(cls):
        # 类对象可以获取类属性但是不能获取实例属性
        # 在类方法中可以使用类属性,不能使用实例属性
        # 类方法中使用类属性   cls.类属性名
        print(f"英雄会跑,属于{cls.class_name}")
    # 定义静态方法,需要借助装饰器   staticmethod  实现定义静态方法
    # 静态方法中不提供任何对象参数,无法调用实例属性和实例方法
    @staticmethod
    def eat():
        print("英雄会吃")
# 实例化一个对象-->实例对象
luban = Hero("鲁班")
# 实例对象获取实例属性
print(luban.name)
# 实例对象调用实例方法
luban.kill()
# 实例对象获取类属性
print(luban.class_name)
# 实例对象调用类方法
luban.run()
# 实例对象调用静态方法
luban.eat()
# 类对象-->类本身-->类名
print(Hero)
# 类对象无法获取实例属性
# 类对象无法调用实例方法
# 类对象获取类属性
print(Hero.class_name)
# 类对象调用类方法
Hero.run()
# 类对象调用静态方法
Hero.eat()

6.在方法中修改属性

6.1 在实例方法中修改数据

# 定义一个英雄类
class Hero:
    # 类属性:直接在定义类的类名下 属性名 = 属性值
    class_name = "英雄类"
    # 定义实例属性
    def __init__(self,name):
        self.name = name
    # 定义实例方法
    def kill(self):
        # 在实例方法中获取属性
        # 实例对象可以获取实例属性,实例方法中使用实例属性   self.实例属性名
        # 实例对象可以获取类属性,实例方法中使用类属性    self.类属性名
        print(f"{self.name}英雄属于{self.class_name}")
        # 在实例方法中修改属性的值
        # 修改实例属性的值    self.实例属性名 = 新值
        self.name = "卤蛋"
        # 使用实例对象修改类属性的值 == 创建新的实例属性class_name
        # self.类属性名 = 新值
        self.class_name = "超人类"
# 实例化一个对象-->实例对象
luban = Hero("鲁班")
luban.kill()   # "鲁班英雄属于英雄类"
print(luban.name)   # "卤蛋"
print(luban.class_name)   # "超人类"
print(Hero.class_name)   # "英雄类"
如果需要在类外修改**类属性**,必须通过类对象去引用然后进行修改。如果通过实例对象去引用,会产生一个同名的**实例属性**,这种方式修改的是实例属性,不会影响到类属性,并且之后如果通过实例对象去引用该名称的属性,实例属性会强制屏蔽掉类属性,即引用的是**实例属性**,除非删除了该实例属性。

6.2 在类方法中修改属性

# 定义一个英雄类
class Hero:
    # 类属性:直接在定义类的类名下 属性名 = 属性值
    class_name = "英雄类"
    # 定义类方法,需要借助装饰器 classmethod  实现定义类方法
    # 装饰器用法:想要将哪一个方法创建为类方法,在该方法上方 @装饰器
    # 创建好的类方法自带参数cls;cls-->类对象本身
    @classmethod
    def run(cls):
        # 类对象可以获取类属性但是不能获取实例属性
        # 在类方法中可以使用类属性,不能使用实例属性
        # 类方法中使用类属性   cls.类属性名
        print(f"英雄会跑,属于{cls.class_name}")
        # 在类方法中修改类属性    cls.类属性名 = 属性值
        cls.class_name = "超人类"
Hero.run()    # "英雄会跑,属于英雄类"
print(Hero.class_name)   # "超人类"

7.总结

实例对象:实例属性、实例方法、类属性、类方法、静态方法
类对象:类属性、类方法、静态方法
1. 从类方法和实例方法以及静态方法的定义形式就可以看出来,类方法的第一个参数是类对象cls,那么通过cls引用的必定是类对象的属性和方法;
2. 实例方法的第一个参数是实例对象self,那么通过self引用的可能是类属性、也有可能是实例属性(这个需要具体分析),不过在存在相同名称的类属性和实例属性的情况下,实例属性优先级更高。
3. 静态方法中不需要额外定义参数,因此在静态方法中引用类属性的话,必须通过类实例对象来引用
在平时定义类中实例方法最常用
类方法-->修改类属性的值、工厂模式
静态方法-->只是想让功能代码存放在类中,使用静态方法即可
相关文章
|
3天前
|
Python
用python转移小文件到指定目录并压缩,脚本封装
这篇文章介绍了如何使用Python脚本将大量小文件转移到指定目录,并在达到大约250MB时进行压缩。
16 2
|
1月前
|
数据安全/隐私保护 Ruby
深入解析Ruby 面向对象
【8月更文挑战第28天】
36 8
|
2天前
|
关系型数据库 MySQL Python
mysql之python客户端封装类
mysql之python客户端封装类
|
1天前
|
Linux Python
linux 封装 python
linux 封装 python
|
1天前
|
Linux Python
Linux 下封装 Python
Linux 下封装 Python
|
30天前
|
数据安全/隐私保护 开发者 Python
在 Python 中定义封装?
【8月更文挑战第29天】
24 8
|
1月前
|
Java 开发者 C++
|
1月前
|
安全 Python
九:《Python基础语法汇总》— 面向对象
本篇文章讲解了何为类何为对象,以及魔法方法(具有特殊功能的函数)和面向对象编程的三个特性:封装;继承;多态
12 0
Python进阶系列(十八)
Python进阶系列(十八)
|
测试技术 Python
Python进阶系列(十七)
Python进阶系列(十七)