热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

39.面向对象之多态

文章目录1.调用父类方法1.1指定类名1.2super2.继承查找顺序3.组合4.多态与多态性4.1抽象化4.2鸭子类型5.一切皆对象1.调用父类方法在子类中使用父类的方法,有两

文章目录

      • 1.调用父类方法
        • 1.1指定类名
        • 1.2super
      • 2.继承查找顺序
      • 3.组合
      • 4.多态与多态性
        • 4.1抽象化
        • 4.2鸭子类型
      • 5.一切皆对象


1.调用父类方法

在子类中使用父类的方法,有两种方式:
1.指定类名
2.super()

1.1指定类名

继承或不继承都能使用,将对象作为参数传递给另一个类中,完成初始化.

class School:school &#61; &#39;xxx&#39;def __init__(self, name, age, gender):self.name &#61; nameself.age &#61; ageself.gender &#61; genderclass Student(School):def __init__(self, name, age, gender, courses):# 指定名称访问School.__init__(self, name, age, gender)# 课程self.courses &#61; courses# 学生信息def stu_info(self):print(&#39;<%s >&#39; % self.courses)# 教师类
class Teacher(School):school &#61; School.schooldef __init__(self, name, age, gender, title):# 指定名称访问School.__init__(self, name, age, gender)# 教什么self.title &#61; title# 老师的信息def Tea_info(self):print(&#39;<%s >&#39; % self.title)stu1 &#61; Student(&#39;kid&#39;, 18, &#39;male&#39;, &#39;python&#39;)
tea1 &#61; Teacher(&#39;xx&#39;, 30, &#39;male&#39;, &#39;python&#39;)
print(stu1.__dict__)
print(tea1.__dict__)
"""
{&#39;name&#39;: &#39;kid&#39;, &#39;age&#39;: 18, &#39;gender&#39;: &#39;male&#39;, &#39;courses&#39;: &#39;python&#39;}
{&#39;name&#39;: &#39;xx&#39;, &#39;age&#39;: 30, &#39;gender&#39;: &#39;male&#39;, &#39;title&#39;: &#39;python&#39;}
"""

image-20211206224613360

1.2super

调用super()放回一个特殊的对象,该对象专门用来应用父类的属性,依赖继承关系,严格按照mro的顺序查找.Python2中:
super(当前类名, self).__init__( 参数1, 参数2 ···) 完整写法。
Python3中:
super().__init__(参数1, 参数2 ···) 新增MRO,不需要写类名,并且会自动将self参数进行传递.

class School:school &#61; &#39;xxx&#39;def __init__(self, name, age, gender):self.name &#61; nameself.age &#61; ageself.gender &#61; genderclass Student(School):def __init__(self, name, age, gender, courses):# 指定名称访问super().__init__(name, age, gender)# 课程self.courses &#61; courses# 学生信息def stu_info(self):print(&#39;<%s >&#39; % self.courses)# 教师类
class Teacher(School):def __init__(self, name, age, gender, title):# 指定名称访问super().__init__(name, age, gender)# 教什么self.title &#61; title# 老师的信息def Tea_info(self):print(&#39;<%s >&#39; % self.title)stu1 &#61; Student(&#39;kid&#39;, 18, &#39;male&#39;, &#39;python&#39;)
tea1 &#61; Teacher(&#39;xx&#39;, 30, &#39;male&#39;, &#39;python&#39;)
print(stu1.__dict__)
print(tea1.__dict__)
"""
{&#39;name&#39;: &#39;kid&#39;, &#39;age&#39;: 18, &#39;gender&#39;: &#39;male&#39;, &#39;courses&#39;: &#39;python&#39;}
{&#39;name&#39;: &#39;xx&#39;, &#39;age&#39;: 30, &#39;gender&#39;: &#39;male&#39;, &#39;title&#39;: &#39;python&#39;}
"""


2.继承查找顺序

# 查找顺序练习
class A:def aaa(self):print(&#39;from - - A - - > aaa&#39;)def test(self):print(&#39;from - - A - - >test&#39;)super().aaa() # super 不会回头 往下 就直接到 B类中, 执行B.aaa() 打印 from - - B - - > aaa 又回到这里print(&#39;AAA&#39;)def aaa(self): # 上面的super() 目前是B 直接到B类去了 没造出来也没法调用,pycharm直接灰色显示print(&#39;from - - test - - > aaa&#39;)class B:def text(self):print(&#39;from - - B - - > test&#39;)def aaa(self):print(&#39;from - - B - - > aaa&#39;)class C(A, B):def aaa(self):print(&#39;from - - c - - > aaa&#39;)obj &#61; C()
print(C.mro())
obj.test()"""
[, , , ]
from - - A - - >test
from - - B - - > aaa
AAA
"""

image-20211206231902645

3.组合

在一个类中引用另一个类最为对象的数据,称为类的组合.
解决类与类之间的代码冗余问题:
1.继承: 继承是一种什么是什么的关系,
2.组合: 组合是一组什么有什么的关系.

class A():def __init__(self, x):self.x &#61; xdef func1(self):return self.xclass B():def __init__(self, y):self.y &#61; yobj1 &#61; A(10)
obj2 &#61; B(obj1)print(obj2.y) # <__main__.A object at 0x000002520F3C9240>
print(obj2.y.x) # 10

在类与类存在什么是什么关系的时候使用继承
在类与类存在什么有什么关系的时候使用组合

老师类和学生类继承人类
老师和学生就是人类

# 人类
class People:def __init__(self, name, age, gender):self.name &#61; nameself.age &#61; ageself.gender &#61; genderpass # 其他属性# 学生类
class Student(People):def __init__(self, name, age, gender):super().__init__(name, age, gender)# 老师类
class Teacher(People):def __init__(self, name, age, gender):super().__init__(name, age, gender)pass # 其他属性

现在添加需求:
给老师类和学生类添加课程.
课程包含 课程名称, 课程学习时间

# 人类
class People:def __init__(self, name, age, gender, course_name, study_time):self.name &#61; nameself.age &#61; ageself.gender &#61; genderself.course_name &#61; course_nameself.study_time &#61; study_time# 学生类
class Student(People):def __init__(self, name, age, gender, course_name, study_time):super().__init__(name, age, gender, course_name, study_time)# 老师类
class Teacher(People):def __init__(self, name, age, gender, course_name, study_time):super().__init__(name, age, gender, course_name, study_time)

这个时候学校的来个门卫大爷,守护学校的安危.给他录信息.

# 人类
class People:def __init__(self, name, age, gender, course_name, study_time):self.name &#61; nameself.age &#61; ageself.gender &#61; genderself.course_name &#61; course_nameself.study_time &#61; study_time# 学生类
class Student(People):def __init__(self, name, age, gender, course_name, study_time):super().__init__(name, age, gender, course_name, study_time)# 老师类
class Teacher(People):def __init__(self, name, age, gender, course_name, study_time):super().__init__(name, age, gender, course_name, study_time)# 守门大爷类
class Janitor_uncle(People):def __init__(self, name, age, gender, course_name, study_time):super().__init__(name, age, gender, course_name, study_time)

守门大爷要这不需要这个课程.
而人类中含有课程的属性也不合理.
将课程提出来新建一个课程类.
老师和学生有课程.

# 人类
class People:def __init__(self, name, age, gender):self.name &#61; nameself.age &#61; ageself.gender &#61; gender# 课程类
class Course():def __init__(self, course_name, study_time):self.course_name &#61; course_nameself.study_time &#61; study_time# 学生类
class Student(People):def __init__(self, name, age, gender):super().__init__(name, age, gender)# 老师类
class Teacher(People):def __init__(self, name, age, gender):super().__init__(name, age, gender)# 守门大爷类
class Janitor_uncle(People):def __init__(self, name, age, gender):super().__init__(name, age, gender)# 造学生对象和老师对象
stu1 &#61; Student(&#39;kid&#39;, 18, &#39;male&#39;)
tea1 &#61; Teacher(&#39;qq&#39;, 30, &#39;male&#39;)
jan1 &#61; Janitor_uncle(&#39;xx&#39;, 60, &#39;male&#39;)# 造课程对象
subject &#61; Course(&#39;Python&#39;, &#39;48课时&#39;)# 学学老师绑定课程信息
stu1.course &#61; subject
tea1.course &#61; subject# 查看课程名称
print(stu1.course.course_name) # Python
# 查看课程课时
print(stu1.course.study_time) # 48课时

4.多态与多态性

程序中的多态:指在子类中覆写父类的方法.类中使用多态的目的:
不是用来继承父类的属性和方法的,而是让父类来限制子类的行为.同样的名称的方法在不同的子类中会有不同的的行为,但是它们有相同的特征,可是使用相同的方法来调用它们.

4.1抽象化

多态的本质是在不同的类中定义相同的方法,
然后在父类中限制子类必须有某个方法,实现某个功能.抽象类就是从一堆类中抽取相似的功能创建一个类作为父类&#xff0c;子类继承父类&#xff0c;子类产生的对象在调用的时候&#xff0c;用法一样&#xff0c;方便使用。抽象类的定义的函数没有实现功能&#xff0c;只是规定了函数名&#xff0c;而且抽象类没法实例化。被抽象的类无法实例化
抽象化的方法在子类中必须要有重名的方法.Python不推崇这样类型.

import abc# metaclass&#61;abc.ABCMeta 抽象类
class Aniaml(metaclass&#61;abc.ABCMeta):&#64;abc.abstractmethod # s抽象化方法def talk(self):pass # 没有函数体直接pass# 继承动物类,
class Cat(Aniaml):passcat &#61; Cat()"""
TypeError: Can&#39;t instantiate abstract class Cat with abstract methods talk
TypeError: 无法用抽象方法实例化抽象类 Cat 谈话
"""

import abc# 抽象类
class Aniaml(metaclass&#61;abc.ABCMeta):&#64;abc.abstractmethod # 抽象化方法def talk(self):pass # 没有函数体直接pass# 动物
class Animal:def talk(self):print(&#39;啊喔&#39;)# 猫
class Cat(Animal):def talk(self):print(&#39;喵喵&#39;)# 狗
class Dog(Animal):def talk(self):print(&#39;汪汪&#39;)# 鸭子
class Duck(Animal):def talk(self):print(&#39;嘎嘎&#39;)# 实例化对象
cat &#61; Cat()
dog &#61; Dog()
duck &#61; Duck()# 调用talk
cat.talk()
dog.talk()
duck.talk()

4.2鸭子类型

Python崇尚鸭子类型,如果看书起来像,叫起来也像,走路也像,那它就是鸭子.
将对象的使用方法统一,做一个接口,
调用这个接口函数,传入不同的参数,可以达到不同的功能.
封装一个函数,只要有它内部执行的这个方法即可。它不依赖继承关系&#xff0c;只要这样对象看起来像鸭子&#xff0c;走起来像鸭子就可以把它当作鸭子。

# 动物
class Animal:def talk(self):print(&#39;啊喔&#39;)# 猫
class Cat(Animal):def talk(self):print(&#39;喵喵&#39;)# 狗
class Dog(Animal):def talk(self):print(&#39;汪汪&#39;)# 鸭子
class Duck(Animal):def talk(self):print(&#39;嘎嘎&#39;)# 实例化对象
cat &#61; Cat()
dog &#61; Dog()
duck &#61; Duck()# 定义函数
def talk(obj):obj.talk()# 调用
talk(cat)
talk(dog)
talk(duck)

不继承也没有约束 , 但是你自己要写
只要有相同的类型,那就是同一个类.

# 常用限制class Animal():def speak(self):raise Exception(&#39;必须实现speak方法) class People(Animal):pass
class Pig():pass
class Dog():passdef animal(animal):return animal.speak()obj1 &#61; People()
obj2 &#61; Pig()
obj3 &#61; Dog()animal(obj1)
animal(obj2)
animal(obj3)

5.一切皆对象

Python中的一切皆对象,通过多态实现.

Python3中统一了类与类型的概念。
l &#61; [1, 2, 3] 等同 l &#61; list(1, 2 ,3)
print(type(l))
<clsaa &#39;list&#39;>

l1 .append(4) ---> 将l1传入append()
对象调用方法将自己作为第一个参数传递。

list是类,类调用方法&#xff0c;方法绑定给类
l &#61; [1, 2, 3]
list.append(l, 4)
print(l) [1, 2, 3, 4]

print(isinstance(l1, list)) # True 判断某个值是否由某个类创建class AAA():passaaa &#61; AAA()print(isinstance(aaa, AAA)) # True 判断某个值是否由某个类创建

Python中所有的数据都是通过调用类实例化得来,所以一切皆对象.


推荐阅读
  • 本文介绍了Python爬虫技术基础篇面向对象高级编程(中)中的多重继承概念。通过继承,子类可以扩展父类的功能。文章以动物类层次的设计为例,讨论了按照不同分类方式设计类层次的复杂性和多重继承的优势。最后给出了哺乳动物和鸟类的设计示例,以及能跑、能飞、宠物类和非宠物类的增加对类数量的影响。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文介绍了使用kotlin实现动画效果的方法,包括上下移动、放大缩小、旋转等功能。通过代码示例演示了如何使用ObjectAnimator和AnimatorSet来实现动画效果,并提供了实现抖动效果的代码。同时还介绍了如何使用translationY和translationX来实现上下和左右移动的效果。最后还提供了一个anim_small.xml文件的代码示例,可以用来实现放大缩小的效果。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • Python语法上的区别及注意事项
    本文介绍了Python2x和Python3x在语法上的区别,包括print语句的变化、除法运算结果的不同、raw_input函数的替代、class写法的变化等。同时还介绍了Python脚本的解释程序的指定方法,以及在不同版本的Python中如何执行脚本。对于想要学习Python的人来说,本文提供了一些注意事项和技巧。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 本文介绍了RPC框架Thrift的安装环境变量配置与第一个实例,讲解了RPC的概念以及如何解决跨语言、c++客户端、web服务端、远程调用等需求。Thrift开发方便上手快,性能和稳定性也不错,适合初学者学习和使用。 ... [详细]
  • 本文介绍了在使用Python中的aiohttp模块模拟服务器时出现的连接失败问题,并提供了相应的解决方法。文章中详细说明了出错的代码以及相关的软件版本和环境信息,同时也提到了相关的警告信息和函数的替代方案。通过阅读本文,读者可以了解到如何解决Python连接服务器失败的问题,并对aiohttp模块有更深入的了解。 ... [详细]
  • 闭包一直是Java社区中争论不断的话题,很多语言都支持闭包这个语言特性,闭包定义了一个依赖于外部环境的自由变量的函数,这个函数能够访问外部环境的变量。本文以JavaScript的一个闭包为例,介绍了闭包的定义和特性。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • Oracle seg,V$TEMPSEG_USAGE与Oracle排序的关系及使用方法
    本文介绍了Oracle seg,V$TEMPSEG_USAGE与Oracle排序之间的关系,V$TEMPSEG_USAGE是V_$SORT_USAGE的同义词,通过查询dba_objects和dba_synonyms视图可以了解到它们的详细信息。同时,还探讨了V$TEMPSEG_USAGE的使用方法。 ... [详细]
author-avatar
栾先益_319
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有