首页 > 编程语言 >python面向对象的三大特性:封装性、继承性、多态性

python面向对象的三大特性:封装性、继承性、多态性

时间:2023-09-25 09:55:05浏览次数:53  
标签:__ python 多态性 self 三大 print class def 属性

python面向对象的三大特性:封装性、继承性、多态性

一、python中的封装

在python代码中,封装具有两层含义:

① 在把现实世界中的实体中的属性和方法写到类的里面的操作即为封装。

class Person(object):
    # 封装属性
    # 封装方法

② 封装可以为属性和方法添加私有权限(属性和方法的封装)

封装中的私有属性和私有方法

在面向对象代码中,我们可以把属性和方法分为两大类,公有(属性,方法)、私有(属性,方法)

Python:公有(属性,方法)、私有(属性,方法)

Java:公有:(属性,方法)、受保护(属性,方法)、私有(属性,方法)

公有属性或公有方法:无论在类的内部还是在类的外部我们都可以对属性和方法进行操作

但是在有些情况下,我们不希望在类的外部对类内部的属性和方法进行操作。我们就可以将这些属性和方法封装为私有形式

  • 只能在类的内部访问,而不能在类的外部访问

私有属性和私有方法的目的:保护数据,过滤掉异常数据!

通过__定义的属性就是私有属性
class Person(object):
    def __init__(self, name, age):
        self.name = name
        self.__age = age  # 私有属性

    # 在类的内部,私有属性可以访问的(只是针对外部无法访问而已)
    # 接口
    def getage(self):
        return self.__age


p1 = Person('赵薇', 18)
print(p1.name)
print(p1.age)  # 报错,在类的外部不能访问私有属性
print(p1.getage())  # 通过接口进行访问私有属性

  • 在实际工作中,所有的属性都应该封装为私有形式,保证数据的安全。

为私有属性添加设置与获取公共接口

class Girl(object):
    def __init__(self, name):
        self.name = name
        self.__age = 18  # 私有属性

    # 给__age私有属性添加一个访问的’接口‘
    def get_age(self):
        # 获取属性之前
        # 1、检验用户是否有查看属性的权限
        # 2、如果有,则返回私有属性,如果没有,则直接禁止访问
        return self.__age

    # 给__age私有属性添加一个设置的’接口‘
    def set_age(self, age):
        # 在设置之前
        # 1、首先要对age进行判断,判断是否是一个合理的数据
        if not isinstance(age, int):  # 判断age是否为int,否则直接退出该函数
            print('很抱歉,您设置的age参数非int类型!')
            return
        if age < 0 or age > 200:
            print('很抱歉,您设置的age参数范围不合理!')

        # 如果是一个合理的参数,则允许设置,否则直接禁止!
        self.__age = age

g1 = Girl('赵薇')

g1.set_age(20)   # 通过set_age函数来设置私有属性
  • 封装数据的属性:明确的区分内外,控制外部对隐藏属性的操作行为(过滤异常数据)

私有方法的定义与使用

私有方法并不是用来保护数据的,而是可以简化程序的复杂度

基本语法:

def __方法名称(self):
    私有方法
# 银行取款
class ATM(object):
    # 1、插卡
    def card(self):
        print("取款")

    def auth(self):
        print('用户验证')

    def input(self):
        print('请输入取款金额:')

    def take_money(self):
        print('取款')

    def print_bill(self):
        print('打印账单')


# 实例化ATM类,进行取款操作
atm = ATM()
atm.card()
atm.auth()
atm.input()
atm.take_money()
atm.print_bill()
  • 需要调用太多方法,增加了程序的复杂度,有没有办法只调用一个方法就实现了取款操作呢
# 银行取款
class ATM(object):
    # 1、插卡
    def __card(self):  # 定义为私用方法
        print("取款")

    def __auth(self):  # 私有方法
        print('用户验证')

    def __input(self):
        print('请输入取款金额:')

    def __take_money(self):
        print('取款')

    def __print_bill(self):
        print('打印账单')
        
    # 定义一个统一的接口,专门用于实现取款操作
    def withdraw(self):
        self.__card()
        self.__auth()
        self.__input()
        self.__take_money()
        self.__print_bill()

# 实例化ATM类,进行取款操作
atm = ATM()
atm.withdraw()

二、python中的继承

1、什么是继承

生活中的继承,一般指的是子女继承父辈的财产。

在python代码中,类是用来描述现实世界中同一组事务的共有特性的抽象模型,但是类也有上下级和范围之分,比如:生物 => 动物 => 哺乳动物 => 灵长型动物 => 人类 => 黄种人

其实就是个性与共性之间的关系,在OOP代码中,也一样要体现出类与类之间的共性与个性的关系,这里就需要通过类的继承来体现了。简单来说,如果一个类A使用了另一个类B的成员(属性和方法),我们就可以说A类继承了B类,同时这也体现了代码重用的特性。

2、继承的基本语法

基本语法:

# 父类B
class B(object):
    pass

# 子类A
class A(B):
    pass
  • 在python3中,所有类默认继承object类,object是顶级类或者基类;其他子类也叫派生类。
  • A类的实例化对象会自动拥有B类的所有公共属性和公共方法。

与继承相关的概念

继承:一个类从另一个已有类获得其成员(属性和方法)的相关特性,就叫作继承。

派生:从一个已有的类产生一个新的类,就叫作派生。

如上述:A类继承了B类 或者说 B类派生了A类

很显然,继承和派生就是从不同的方向描述相同的概念而已,其本质是一样的。

父类:也叫作基类,就是指已有被继承的类。

子类:也叫作派生类和扩展类

扩展:在子类中添加一些自己特有的特性,就叫作扩展,没有扩展,继承也就没有了意义。

单继承:一个类只能继承来自一个其他的类,不能继承多个类,单继承也是大多面向对象语言的特性。

多继承:一个类同时继承多个父类(C++,Python等语言都支持多继承)

3、单继承

class Car(object):
    # 定义公共属性
    def __init__(self, brand, model):
        self.brand = brand
        self.model = model

    # 定义公共方法
    def run(self):
        print('I can run!')


# 定义一个汽油车类(继承汽车类)
class GasolineCar(Car):
    # 继承了汽车类的所有公共属性和方法
    pass


bwm = GasolineCar('宝马', 'X5')  # 继承了汽车类所有公共属性和方法
print(bwm.brand)
print(bwm.model)
bwm.run()

4、单继承特性(多层继承):传递性

在python继承中,如A类继承了B类,B类又继承了C类。根据继承的传递性,A也会自动继承C类的所有公共属性和方法。

class C(object):
    def func(self):
        print('我是C类中的公共方法!')


class B(C):
    pass


class A(B):
    pass


a = A()
a.func()  # C -> B -> A

5、多继承

python是为数不多支持多继承的面向对象的编程语言。所谓多继承就是一个类可以同时继承多个类的公共特性。

# 定义一个汽油车类
class GasolineCar(object):
    def run_with_gasoline(self):
        print('I run with Gasoline!')


# 定义一个电动车类
class ElectricCar(object):
    def run_with_electric(self):
        print('I run with electric!')


# 定义一个混动汽车类
class HybridCar(GasolineCar, ElectricCar):  # 同时继承汽油车类与电动车类
    pass


byd = HybridCar()
byd.run_with_gasoline()  # 汽油车的方法
byd.run_with_electric()  # 电动车的方法

6、MRO属性或MRO方法:方法解析顺序

MRO(method Resolution Order):方法解析顺序,我们可以通过类名.__mro__类名.mro()获得“类的层次结构”,方法解析顺序也是按照这个“类的层次结构”寻找到。

一个class如何去从他的父类里面找,应该优先使用哪个父类函数,这个顺序就叫MRO。我们提到的MRO是每一个类会把它所有的父类和他自己做一个线性化;也就是把它继承的所有类和它自己做一个排队,这个排队保证自己是最高优先级。在它想调用一个方法和数据时候,它会按照这个队列的优先级顺序从前往后找。

class A:
    def say(self):
        print("A")

class B:
    def say(self):
        print("B")

class C(A):
    pass

class M(C, B):
    pass

m = M()
m.say() # 输出A 根据MRO
print(M.mro())

image-20230923000039385

  • 当m调用say方法时候,优先从M类中寻找有没有say方法,依次往后M -> C -> A ->B

多继承中的覆盖问题

继承的多个父类中含义相同的属性或方法,那么子类会继承哪个父类中的成员方法呢?

# 定义一个汽油车类
class GasolineCar(object):
    def run(self):
        print('I run with Gasoline!')


# 定义一个电动车类
class ElectricCar(object):
    def run(self):  # 同样定义一个run方法
        print('I run with electric!')


# 定义一个混动汽车类
class HybridCar(GasolineCar, ElectricCar):  # 同时继承汽油车类与电动车类
    pass


byd = HybridCar()
byd.run()  # I run with Gasoline! 继承了GasonlineCar类中的run方法
print(HybridCar.__mro__)  # 子类调用__mro__查看类的层次结构
print(HybridCar.mro())   # 通过子类调用mro()方法查看类的层次结构

image-20230920084450036

  • 通过子类类名.__mro__类名.mro()获得类的层次结构是一样的,只不过两者返回值不同,一个是元组,一个是列表
  • 从类的层次结构中获知,优先继承HybridCar(自己)中的成员,其次GasolineCar,然后是ElectricCar,最后是object(基类)中的成员方法。

7、子类扩展:重写1父类的属性和方法

什么是重写与扩展

重写也叫作覆盖,就是当子类成员和父类成员名字相同的时候,真正启作用的是子类中的成员!

扩展:子类在继承父类的同时,还可以编写一些属于自己的属性和方法。甚至重写父类的属性和方法,我们把这种形式称为扩展。

继承的意义:① 实现代码的重用 ② 子类应该在继承的同时,拥有一些自己的特性(扩展)

class Animal(object):
    def eat(self):
        print('I can eat!')

    def call(self):
        print('I can call')


class Dog(Animal):
    # 重写父类中的call方法
    def call(self):
        print('I can wang wang wang!')


dog = Dog()
dog.eat()  # 继承父类中的方法
dog.call()  # 重写父类中的方法 I can wang wang wang!

思考:重写父类中的call方法之后,此时父类中的call方法还在不在?

答:还在,只不过是在其子类中找不到了。类方法的调用顺序,当我们在子类中重构父类的方法后,Dog子类的实例先会在自己的类Dog中查找该方法,当找不到该方法时才会去父类Animal中查找对应的方法。

8、super() : 调用父类属性和方法

在python代码中,如果在继承重写的基础上,我们还需要强制调用父类中的属性或方法,可以使用super()

  • super是一个类class,super()建立一个super对象,在super中的两个参数,第一个参数是一个class,决定了在mro链上从哪个class(当前类的后一个)开始往后找。

基本语法:

Python2版本中:

super.(当前类名,self).属性或方法

Python3版本中:

super().属性
super().方法
class Car(object):
    def __init__(self, brand, model, color):
        self.brand = brand
        self.model = model
        self.model = model

    def run(self):
        print('I can run!')


# 定义一个汽油车类
class GasolineCar(Car):
    # 继承Car中属性
    # 重写Car中的方法
    def run(self):
        print('I can run with gasoline!')


class EletricCar(Car):
    # 强制继承父类中的公共属性
    def __init__(self, brand, model, color, battery):
        # 强制继承父类中的brand,model,color
        super().__init__(brand, model, color)
        self.battery = battery

    # 重写父类中的run方法
    def run(self):
        print('I can run with eletric1')


car1 = EletricCar('tesla', 'model Y', 'red', '80%')
print(car1.battery)
print(car1.brand)
class A(object):
    def __init__(self, brand, model):
        self.brand = brand
        self.model = model


class B(object):
    def __init__(self, brand, color):
        self.brand = brand
        self.color = color


class C(A, B): # 根据mro方法解析顺序 继承类为 C->A->B->object
    def __init__(self, brand, model, color):
        super(C, self).__init__(brand, model)  # C 代表从C之后的类开始往后寻找 init方法继承
        self.color = color


print(C.mro())
c = C('byd', 123, 'red')
print(c.model, c.color, c.brand)

三、Python中的多态

多态指的是一种事物具有多种形态

定义:多态是一种使用对象的方法,子类重写父类方法,调用不同子类的相同父类方法,可以产生不用的执行结果

① 多态依赖继承

② 子类必须重写父类方法

好处:调用灵活,有了多态,更容易编写出通用的代码,做出通用的编程,以适应需求的不断变化。

image-20230925092020290

class Fruit(object):
    # 定义一些公共属性和方法
    def makejuice(self):
        pass


class Apple(Fruit):
    # 重写父类中的方法
    def makejuice(self):
        print('I can make apple juice!')


class Orange(Fruit):
    def makejuice(self):
        print('I can make orange juice!')


class Banana(Fruit):
    def makejuice(self):
        print('I can make banana juice!')


# 定义一个公共借口,根据传入不同的对象,调用相同的方法产生不同的结果
def service(obj):
    obj.makejuice()


# 比如
service(Banana())  # I can make banana juice!
apple = Apple()
service(apple)  # I can make apple juice!
service(Orange())  # I can make orange juice!

案例:

class Dog(object):
    def work(self):
        pass


class ArmyDog(Dog):
    def work(self):
        print('追击敌人...')


class DrugDog(Dog):
    def work(self):
        print('追查毒品...')


class Person(object):
    def work_with_dog(self, dog):
        dog.work()


police = Person()
police.work_with_dog(ArmyDog())
police.work_with_dog(DrugDog)

加号 + 的多态案例:

当加号两边的对象为两个 数值型时 ,实现运算符的操作 1+2 = 3

当加号两边为 两个字符串的时候,实现字符串的拼接: 'a' + 'b' = 'ab'

当加号两边为两个列表的时候,实现列表的拼接:[1,2,3] + [4, 5, 6] = [1, 2, 3, 4, 5, 6]

标签:__,python,多态性,self,三大,print,class,def,属性
From: https://www.cnblogs.com/luoluoange/p/17727230.html

相关文章

  • Python 基本语法
    在开始学习Python编程语言之前,首先要掌握基本的语法。本文将介绍Python编程语言的基本语法,帮助初学者顺利进入Python编程世界。一、Python编程语言概述Python是一种高级编程语言,具有简单易学、语法简洁、功能强大等特点。Python支持多种编程范式,包括面向对象、面向......
  • 如何在python代码中自动插入时间和作者信息
    在编程的过程中,为养成良好的写代码习惯,很多人通常喜欢将一些作者信息以及编码信息存储在代码中,以便于后期的查阅,也可帮助后来者进行快速入手,那么如何才能让他自动出现在我们的代码中呢,我们可按照下面的方式进行设置,希望可以帮到你!在python编程工具pycharm中按照以下路径打开:File......
  • 小白学Python:提取Word中的所有图片,只需要1行代码
    大家好,这里是程序员晚枫,全网同名。最近在小破站账号:Python自动化办公社区更新一套课程:给小白的《50讲Python自动化办公》在课程群里,看到学员自己开发了一个功能:从word里提取图片。这个功能非常实用。我在征求开发者:王鹏大哥的同意后,把这行代码集成到了python-office这个库里,实现......
  • python pip Fatal error in launcher:
    执行pip命令,提示Fatalerrorinlauncher原因:是不是修改过python.exe的名字。因为pip在生成的时候,就把Pythone.exed绝对路径写到了文件里,而pip执行又依赖python,所以执行报错。系统里是否装了多个版本的python,同上一条原因,因为写了绝对路径,导致文件寻找时,有可能交叉......
  • 结对项目:用Python实现四则运算
    这个作业属于哪个课程计科1/2班这个作业要求在哪里结对项目这个作业的目标实现一个自动生成小学四则运算题目的命令行程序团队成员姓名学号梁昊东3121005000李铭伟3121004145github链接:https://github.com/e1ecb0t/e1ecb0t/tree/main/cacul......
  • python教程:调用svn status命令对提交的文件进行add状态过滤(只保存新增加的文件)
    需求说明编写一段python程序,用于对svnadd状态的文件进行过滤,并用列表对这些文件进行保存。代码实现以下是一个示例的Python程序,用于对SVN的svnstatus命令中状态为“A”(新增)的文件进行过滤,并将它们存储在一个列表中:importsubprocessdefget_added_files():added_fi......
  • python教程:解决报错:ERROR: THESE PACKAGES DO NOT MATCH THE HASHES FROM THE REQUIRE
    从以下两种途径来解决。清除缓存这个错误通常表示安装的软件包与要求文件中的哈希值不匹配。这可能是由于要求文件被更改或软件包被篡改引起的。为了解决这个问题,你可以尝试以下几个步骤:清理缓存:运行以下命令清理pip缓存:pipcachepurge```更新要求文件:如果你更新了软件包的版本......
  • python.exe get-pip.py安装失败
    装pip要用get-pip.py来安装,但安装时还要下载whl文件,如果系统中没有设置国内镜像源,从国外下,会经常失败。原因:大部分失败都是因为网络问题才失败的。解决方法:使用国内源,在C:\Users\你的用户名\pip文件夹下,把以下内容保存到pip.ini里。[global]index-url=http://mir......
  • Python分享
    Python斗地主不完全代码importrandom#定义扑克牌的花色和大小suits=["♠","♥","♦","♣"]ranks=["A","2","3","4","5","6","7","8","9",......
  • python列表
    追加appemd("")插入insert(位置,"")合并extend("")嵌套names.insert(2,[1,2,3])names[2][1]2删除del()pop() 默认删除最后一个,并返回删除值,可以指定,但是要输入索引remove("")  指定元素名,其中有重复会从左边开始删第一个clear()  清空修改names[0]="你好"......