Python面向对象详解(4-4)

举报
乂氼S 发表于 2023/05/28 13:32:36 2023/05/28
【摘要】 Python面向对象详解(4-4)

 目录


一.继承

1.什么是继承?

2.父类与子类的关系

3.Python中类的继承

 4.实战

二.类的多态 

1.什么是类的多态?

2.为什么要使用多态?为什么要去继承父类?

3.多态的用法

4.实战

三.python中的super函数

1.super函数的作用

2.super函数的用法

3.实战

四.类的多重继承

1.什么是多重继承?

2.多重继承的方法

3.实战

五.类中的高级函数 

1.__str__函数

 2.__getattr__函数

3.__setattr__函数

 4.__call__函数

 5.实战



一.继承

  • 什么是继承?
  • 父(基)类与子(派生)类
  • 继承的用法

1.什么是继承?

  • 通过继承基类来得到基类的功能
  • 所以我们把被继承的类称作父类或基类,继承者被称作子类或派生类
  • 代码的重用

2.父类与子类的关系

  • 子类拥有父类的所有属性和方法
  • 父类不具备子类自有的属性和方法

3.Python中类的继承

  • 定义子类时,将父类传入子类的参数括弧内
  • 子类的实例化可以调用自己与父类的函数与变量

编辑

 4.实战

# 定义一个父类Animal
class Animal:
    def __init__(self, name):
        self.name = name

    def eat(self):
        print(f"{self.name}正在吃东西")

    def sleep(self):
        print(f"{self.name}正在睡觉")


# 定义一个子类Dog,继承自Animal类
class Dog(Animal):
    def __init__(self, name, breed):
        # 调用父类Animal的初始化方法,传递name参数
        super().__init__(name)
        self.breed = breed

    def bark(self):
        print(f"{self.name}正在汪汪叫")


# 定义另一个子类Cat,也继承自Animal类
class Cat(Animal):
    def __init__(self, name, color):
        # 调用父类Animal的初始化方法,传递name参数
        super().__init__(name)
        self.color = color

    def purr(self):
        print(f"{self.name}正在咕噜咕噜叫")


# 创建一个Dog实例并调用其方法
my_dog = Dog("旺财", "拉布拉多")
my_dog.eat()  # 继承自父类Animal的eat方法
my_dog.sleep()  # 继承自父类Animal的sleep方法
my_dog.bark()  # Dog类自己定义的bark方法

# 创建一个Cat实例并调用其方法
my_cat = Cat("咪咪", "白色")
my_cat.eat()  # 继承自父类Animal的eat方法
my_cat.sleep()  # 继承自父类Animal的sleep方法
my_cat.purr()  # Cat类自己定义的purr方法

输出结果:


旺财正在吃东西
旺财正在睡觉
旺财正在汪汪叫
咪咪正在吃东西
咪咪正在睡觉
咪咪正在咕噜咕噜叫

进程已结束,退出代码0

 在上面的代码中,我们定义了一个父类 Animal 和两个子类 DogCat。子类通过 class 子类名(父类名): 的方式继承父类的属性和方法。

子类可以在继承父类的基础上定义自己的属性和方法。在子类的 __init__ 方法中,我们使用 super().__init__(参数) 来调用父类的 __init__ 方法,以便子类可以继承父类的属性。

在主程序中,我们分别创建了一个 Dog 对象和一个 Cat 对象,并调用了它们的继承自父类的方法,以及子类自己定义的方法。可以看到,子类 DogCat 成功继承了父类 Animal 的方法,并且可以使用自己定义的方法。这展示了Python中类继承的基本概念和用法。


二.类的多态 

  • 什么是类的多态?
  • 为什么要使用多态?为什么要去继承父类?
  • 多态的用法

1.什么是类的多态?

  • 同一个功能的多状态化

2.为什么要使用多态?为什么要去继承父类?

  • 答案:为了使用已经写好的类的函数,为了保留子类中某个和父类名称一样的函数功能,这时候,我们就用到了多态,可以帮助我们保留子类中的函数功能

3.多态的用法

  • 子类中重写父类的方法

4.实战

# coding:utf-8

# 书写一个父类
class Father(object):
    def talk(self):
        print('小白的爸爸说了一句话')

    @staticmethod
    def jump():
        print('大家都可以跳')


# 书写一个子类,并且继承一个父类
class Brother(Father):
    @staticmethod
    def run():
        print('小白的哥哥在奔跑着')

    # 重写父类函数
    def talk(self):
        print('小白的哥哥在说话')


"""
    为什么要使用多态?
    为什么要继承父类?
    答:
        为了使用已经写好的类的函数
        为了保留子类中某个和父类名称一样的函数功能,这时候,我们就用到了多态,
        可以帮助我们保留子类中的函数功能
"""


class XiaoShu(Father):
    def talk(self):
        print('小白也可以表达自己的观点')


if __name__ == '__main__':
    brother = Brother()
    brother.run()
    brother.talk()
    brother.jump()
    print('----------')
    father = Father()
    father.talk()
    father.jump()
    print('----------')

    xiaoshu = XiaoShu()
    xiaoshu.talk()
    xiaoshu.jump()
    print('----------')

  输出结果:

小白的哥哥在奔跑着
小白的哥哥在说话
大家都可以跳
----------
小白的爸爸说了一句话
大家都可以跳
----------
小白也可以表达自己的观点
大家都可以跳
----------

进程已结束,退出代码0

三.python中的super函数

  • super函数的作用
  • super函数的用法

1.super函数的作用

  • python子类继承父类的方法而使用的关键字,当
    子类继承父类后,就可以通过super函数调用父类中的方法

2.super函数的用法

  • 编辑
  •  python3.0后,super()函数括弧内不用传参数也能执行
  • 通过super函数可以让子类完全执行父类相同函数的业务逻辑

3.实战

# coding:utf-8

class Parent(object):
    def __init__(self, p):
        print('hello i am parent %s' % p)


class Child(Parent):
    def __init__(self, c, p):
        print('hello i am child %s' % c)
        super(Child, self).__init__(p)  # 这两种方法都可以实现,python3.0后。super括弧内不用传参数,也能执行
        super().__init__(p)  # 这两种方法都可以实现,python3.0后。super括弧内不用传参数,也能执行


if __name__ == '__main__':
    c = Child(c='child', p='parent')

  输出结果:

hello i am child child
hello i am parent parent
hello i am parent parent

进程已结束,退出代码0

四.类的多重继承

  • 什么是多重继承?
  • 多重继承的方法

1.什么是多重继承?

  • 可以继承多个基(父)类

2.多重继承的方法

  • class Child(Parent1, Parent2, Parent3....):
  • 将被继承的类放入子类的参数位中,参数之间用逗号隔开
  • 从左到右依次继承
  • 如果父类中有相同的函数,在子类中调用此函数则以继承时从左到右的顺序执行,可以调用__mro__函数(method resolution order 方法解析顺序)来查看继承的顺序
  • 通过多重继承的方法,可以使用多个父类中的函数。如果继承的多个父类中有相同的函数,最开始继承的这个父类中的函数将会发生作用。

3.实战

# coding:utf-8

class Point(object):
    # 自定义Point类的构造(初始化)方法
    def __init__(self, x, y):
        self.x = x
        self.y = y

    # 自定义Point类对象的格式化输出函数(string())
    def string(self):
        print(f'x:{self.x}, y:{self.y}')


class Circle(Point):
    # 自定义Circle类的构造(初始化)方法
    def __init__(self, x, y, radius):
        super().__init__(x, y)
        self.r = radius

    # 自定义Circle类对象的格式化输出函数(string())
    def string(self):
        print(f'该图形初始化点为:{{X:{self.x}, Y:{self.y}; {{半径为:{self.r}}}')


class Size(object):
    # 自定义Size类的构造(初始化)方法
    def __init__(self, width, height):
        self.width = width
        self.height = height

    # 自定义Size类对象的格式化输出函数(string())
    def string(self):
        print(f'{{Width:{self.width}, Height:{self.height}}}')


class Rectangle(Point, Size):
    # 自定义Rectangle类的构造(初始化)方法,并在方法中调用父类的初始化方法以完成初
    def __init__(self, x, y, width, height):
        # Point.__init__(self, x, y)  # 多重继承中调用不同类中的相同方法时所采用的格式(法一)
        # Size.__init__(self, width, height)  # 多重继承中调用不同类中的相同方法时所采用的格式(法一)
        super(Rectangle, self).__init__(x, y)  # 多重继承中调用不同类中的相同方法时所采用的格式(法二)super() 函数调用的是Rectangle类在其所在的 MRO 表(方法解析顺序)中的下一个类,也就是Point
        super(Point, self).__init__(width, height)  # 多重继承中调用不同类中的相同方法时所采用的格式(法二)super() 函数调用的是类在其所在的 MRO 表(方法解析顺序)中的下一个类
        """
            当前类所在的MRO表为 Rectangle>Point>Size>object,可以调用__mro__来查看方法解析顺序表,其中调用__mro__的类将作为MRO顺序表中的第一个类
            super() 函数调用的是当前类在方法解析顺序(MRO)中的下一个类,也就是在MRO列表中当前类的下一个类。MRO 是一种确定多重继承中继承顺序的算法,Python 中采用的是 C3 算法。在 Python 中,
            每个类都有一个 MRO,可以通过查看类属性 __mro__ 来获取其 MRO。在调用 super() 函数时,Python 会自动根据 MRO 找到下一个类。
        """

    # 自定义Rectangle类对象的格式化输出函数(string()
    def string(self):
        print(f'该图形初始化点为:{{X:{self.x}, Y:{self.y}}}; 长宽分别为:{{Width:{self.width}, Height:{self.height}}}')


if __name__ == "__main__":
    # 实例化Circle对象,圆心为(5,5),半径为8
    c = Circle(5, 5, 8)
    c.string()
    # 实例化Rectangle对象,顶点位置(15,15),长和宽
    r1 = Rectangle(15, 15, 15, 15)
    r1.string()
    # 实例化Rectangle对象,顶点位置(40,30),长和宽
    r2 = Rectangle(40, 30, 11, 14)
    r2.string()
    print('MRO为:', Rectangle.__mro__)  # 返回一个包含解析顺序的元组

  输出结果:

该图形初始化点为:{X:5, Y:5; {半径为:8}
该图形初始化点为:{X:15, Y:15}; 长宽分别为:{Width:15, Height:15}
该图形初始化点为:{X:40, Y:30}; 长宽分别为:{Width:11, Height:14}
MRO为: (<class '__main__.Rectangle'>, <class '__main__.Point'>, <class '__main__.Size'>, <class 'object'>)

进程已结束,退出代码0

五.类中的高级函数 

  • __str__
  • __getattr__
  • __setattr__
  • __call__

1.__str__函数

  • 如果定义了该函数,当print当前实例化对象的时候,会返回该函数的return信息
  • 可用于定义当前类的描述信息
  • 用法:

编辑

  •  参数:无
  • 返回值:一般用于返回对于该类的描述信息
  • 编辑

 2.__getattr__函数

  • 当调用的属性或者方法不存在时,会返回该方法定义的信息
  • 用法:
  • 编辑
  •  参数:key:调用的任意的不存在的属性名
  • 返回值:可以是任意类型也可以不进行返回

编辑编辑

3.__setattr__函数

  • 拦截当前类中给属性赋值的操作,在Python中,__setattr__是一个特殊方法(也称为魔术方法魔术函数),用于设置属性的值。当你尝试给一个对象的属性赋值时,__setattr__方法会被自动调用。

编辑

  •  参数:key:需要修改值属性名value 当前的参数所需要设置的对应的值
  • 返回值:无

编辑

 4.__call__函数

  • 本质上是将一个类变成一个函数
  • 用法:

编辑

  •  参数:可传任意参数
  • 返回值:与函数情况相同可有可无

编辑

 5.实战

# coding:utf-8


class Test(object):
    # 当打印实例对象本身的时候,用于返回一个对象的字符串表示形式
    def __str__(self):
        return 'this is a test class'

    # 用于访问一个不存在的属性时进行拦截和处理
    def __getattr__(self, item):
        return f'这个{item},不存在'

    # 用于拦截属性赋值的
    def __setattr__(self, key, value):
        """
        __setattr__方法是用于拦截属性赋值的,而不是拦截不存在的属性或值。当我们给一个对象的属性赋值时,Python会自动调用该对象的__setattr__方法来设置属性。

        :param key: 需要赋值的属性,如果该属性已经存在,则会更新它的值;如果该属性不存在,则会创建一个新属性,并将其值设置为赋值的值。
        :param value:需要传入的值
        """
        print(key, value)
        self.__dict__[key] = value
        '''
            __dict__是Python中的一个特殊属性,用于获取一个对象的所有属性和方法的字典。当我们访问一个对象的__dict__属性时,Python会返回一个字典对象,该字典的键是对象的属性名或方法名,而值是相应的属性值或方法对象。
        '''
        print(self.__dict__)
        """
        每个对象在Python中都有一个__dict__属性,它是一个字典对象,包含了某个对象的所有属性和方法以及它们所对应的值。每当我们给对象添加一个新的属性或方法时,这个属性或方法就会被添加到该对象的__dict__属性中。
        在Python中,通过访问__dict__属性,我们可以动态地添加、删除或修改对象的属性和方法,这也是Python动态语言的一个重要特性之一。
        """

    def __call__(self, *args, **kwargs):
        """
        __call__是Python中的一个特殊方法,用于让一个对象变成可调用对象(callable object)。当我们对一个对象
        使用函数调用运算符()时,如果该对象定义了__call__方法,Python会自动调用该对象的__call__方法来执行函数调用操作。

        :param args: 需要传入的多个位置参数
        :param kwargs: 需要传入的多个关键字参数
        """
        print('call is start')
        print(args, kwargs)


t = Test()
print(t)
print(t.a)  # 不存在的对象会直接打印出来而不是报错
t.name = 'xiaoshu'
t(123, name='xiaoding')
print('---------')

'''实现链式操作'''


class Test2(object):
    def __init__(self, attr=''):
        self.__attr = attr
        self(self.__attr)

    def __call__(self, name):
        print("key is {}".format(self.__attr))
        return name

    def test(self):
        print(self.b)

    def __getattr__(self, key):
        if self.__attr:
            key = '{}.{}'.format(self.__attr, key)
        else:
            key = key
        print(key)
        return Test2(key)  # 递归操作


t2 = Test2()
#  链式调用,a.c是在原有调用a的基础上调用c,链式操作就是多个点的形式
print(t2.a.c('xiaoshu'))
print('--------')
t2.test()

  输出结果:

this is a test class
这个a,不存在
name xiaoshu
{'name': 'xiaoshu'}
call is start
(123,) {'name': 'xiaoding'}
---------
key is 
a
key is a
a.c
key is a.c
key is a.c
xiaoshu
--------
b
key is b
<__main__.Test2 object at 0x000001CD81718AD0>

进程已结束,退出代码0


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。