python中的继承与多态,dir()函数

news/2024/3/28 20:06:12/文章来源:https://blog.csdn.net/qq_51641495/article/details/130349521

Python继承

在继承关系中,已有的、设计好的类称为父类或基类,新设计的类称为子类或派生类。派生类可以继承父类的公有成员,但是不能继承其私有成员。如果需要在派生类中调用基类的方法,可以使用内置函数super()或者通过“基类名.方法名()”的方式来实现这一目的。

在Python中,如果一个类需要继承另一个类的成员,可以使用以下方式进行定义:

class BaseClass:def __init__(self):self.public_member = "I am a public member"self.__private_member = "I am a private member"  # 双下划线开头的成员变量为私有成员def public_method(self):print("This is a public method")def __private_method(self):print("This is a private method")class DerivedClass(BaseClass):def derived_method(self):# 调用从父类继承的公共成员print(self.public_member)# 无法调用父类的私有成员# print(self.__private_member)# 调用从父类继承的公共方法self.public_method()# 通过super()函数调用父类的方法super().public_method()# 无法直接调用基类的私有方法# self.__private_method()

在以上代码中,BaseClass 是一个基类,DerivedClass 是一个派生类。在 BaseClass 中,定义了一个公有成员 public_member 和一个私有成员 __private_member,以及一个公有方法 public_method 和一个私有方法 __private_method。在 DerivedClass 中,继承了 BaseClass 的公有成员 public_member 和公有方法 public_method,并且定义了一个派生类方法 derived_method

在派生类中,我们可以通过继承来使用从基类继承的公共成员和方法,但是无法直接调用基类中的私有成员或方法。如果需要在派生类中调用基类的方法,可以使用内置函数 super() 或者通过“基类名.方法名()”的方式来实现这一目的。在 derived_method 中,我们展示了如何使用 super().public_method() 来调用基类的 public_method 方法。

Python支持多继承,如果父类中有相同的方法名,而在子类中使用时没有指定父类名,则Python解释器将从左向右按顺序进行搜索。

以下是一个简单的示例代码,用于说明Python支持多继承时的方法解析顺序(MRO)问题:

class A:def hello(self):print("Hello from A")class B:def hello(self):print("Hello from B")class C(A, B):passclass D(B, A):pass# 创建子类C的实例
obj_c = C()
obj_c.hello()  # 输出 "Hello from A"# 创建子类D的实例
obj_d = D()
obj_d.hello()  # 输出 "Hello from B"

在上面的示例代码中,我们定义了两个父类AB,分别有相同的方法名hello,同时我们分别创建了两个子类CD,并使用多继承方式分别继承了AB

在子类C中,我们没有定义hello方法,因此当我们创建obj_c实例后,调用hello方法时,Python解释器按照继承顺序从左到右进行搜索,首先找到A类中的hello方法,并执行。

而在子类D中,我们同样也没定义hello方法,但我们将B类放在A类前面来继承,因此当我们创建obj_d实例后,调用hello方法时,Python解释器按照继承顺序从左到右进行搜索,首先找到B类中的hello方法,因此执行结果输出"Hello from B"。

这就是Python多继承时的方法解析顺序(MRO)问题,如果父类中有相同的方法名,而在子类中没有指定父类名,则Python解释器会按照子类继承父类的先后顺序从左到右进行搜索,找到第一个匹配的方法并执行。当然,我们也可以通过显式地指定父类名来调用指定的父类中的方法,避免方法名冲突问题。

在Python中,私有变量是可以继承的。但是,子类无法直接访问父类的私有属性,因为私有属性在父类实例化之后会被转成一个新的名称,子类中也无法访问这个名称。但如果需要子类能够访问父类的私有变量,可以通过调用父类的get和set方法来实现。

以下是一个简单的示例代码,用于说明在Python中,子类无法直接访问父类的私有属性,但可以通过调用父类的get和set方法来实现:

class Parent:def __init__(self):self.__private_var = "I am a private variable in parent class"def get_private_var(self):return self.__private_vardef set_private_var(self, value):self.__private_var = valueclass Child(Parent):def __init__(self):super().__init__()self.__private_var_in_child = "I am a private variable in child class"def print_private_var(self):# 子类无法直接访问父类的私有属性# print(self.__private_var)  # 这里会出错# 如果需要访问父类的私有属性,可以通过调用父类的get方法来实现print(self.get_private_var())# 子类可以访问自己的私有属性print(self.__private_var_in_child)# 创建子类的实例
child_obj = Child()# 调用子类的方法来访问私有变量
child_obj.print_private_var()# 调用父类的方法来修改私有变量的值
child_obj.set_private_var("Modified private var in parent class")# 再次调用子类的方法来访问私有变量
child_obj.print_private_var()

运行上面的代码,输出结果如下:

I am a private variable in parent class
I am a private variable in child class
Modified private var in parent class
I am a private variable in child class

从输出结果可以看出,在子类中无法直接访问父类的私有变量__private_var,但可以通过调用父类的公共方法get_private_var()来获取私有变量的值,并且可以通过调用父类的公共方法set_private_var()来修改私有变量的值。同时,子类也可以定义自己的私有变量,对于这些私有变量,则可以直接在子类中访问和修改。

dir()函数

dir() 函数是Python内置函数之一,它返回一个列表,包含当前作用域内的所有可用属性和方法的名称。它可以接受一个参数,表示要查询的对象或模块,也可以不传递参数,此时会返回当前作用域内的所有全局名称。

以下是一个示例:

class MyClass:def __init__(self):self.my_attribute = 42def my_method(self):passmy_object = MyClass()print(dir(my_object))

输出结果:

['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'my_attribute', 'my_method']

此处我们定义了一个 MyClass 类和一个 my_object 实例,并使用 dir() 函数来探索 my_object 的属性和方法。可以看到,除了我们在 MyClass 中定义的 "my_attribute""my_method" 之外,还有许多其他属性和方法在这个对象里面,例如 "__class__", "__dict__", "__doc__", "__hash__", 等等。

值得注意的是,这些以双下划线开头和结尾的名称都是对象所继承的一些特殊属性和方法,它们在Python中被称为“魔术方法”或“特殊方法”。它们在Python中有特殊的语法和行为,可用于实现一些特殊的功能,比如重载操作符。

另外,还有一些内置模块和函数也可以通过 dir() 函数进行探索。例如:

import mathprint(dir(math))

输出结果:

['__doc__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'comb', 'copysign', 'cos', 'cosh', 'degrees', 'dist', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', 'isinf', 'isnan', 'isqrt', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'modf', 'nan', 'nextafter', 'perm', 'pi', 'pow', 'prod', 'radians', 'remainder', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'tau', 'trunc', 'ulp']

可以看到,在数学模块中,有许多不同的常量、函数和方法可供使用,例如符号常数 pi 或 tau,三角函数 sin 和 cos,还有一些数学运算和工具函数,例如 factorial 和 gcd 等,它们都可以通过 dir() 函数进行探索。

dir() 函数是一个十分强大的工具,它可以帮助我们快速了解和理解Python中可用的函数、模块、类、对象、方法等,并对我们在开发和调试代码时带来很多便利。

多态

在Python中,多态(polymorphism)是面向对象编程的一个重要概念,它指的是基类的同一方法在不同派生类对象中具有不同的表现和行为。也就是说,同样的方法名可以被派生类重写,从而实现不同的行为或逻辑。

下面我们来举一个简单的例子:

class Animal:def sound(self):print("The animal makes a sound.")class Dog(Animal):def sound(self):print("The dog barks.")class Cat(Animal):def sound(self):print("The cat meows.")def do_sound(animal):animal.sound()dog = Dog()
cat = Cat()do_sound(dog)
do_sound(cat)

在这个例子中,我们定义了一个基类 Animal,它包含一个 sound() 方法,并打印出一条通用的动物发声信息。然后我们定义了两个派生类 DogCat,它们都继承了 Animalsound() 方法,但改写了此方法以打印自己的声音信息。最后,我们编写了一个函数 do_sound(),它接受一个 Animal 类型的参数,并调用它的 sound() 方法。

当我们创建一个实例 dogcat 时,它们分别是 DogCat 类型的对象,同时也都是 Animal 类型的对象。当我们调用 do_sound(dog)do_sound(cat) 时,它们都会被传递给 do_sound() 函数,该函数会调用它们各自的 sound() 方法。由于派生类重写了基类方法,因此每个对象的 sound() 方法的行为都是不同的。

另外,需要注意的是,多态还可以用于参数和返回值的类型注解。例如:

from typing import Unionclass Shape:def area(self) -> float:passclass Rectangle(Shape):def __init__(self, width: float, height: float):self.width = widthself.height = heightdef area(self) -> float:return self.width * self.heightclass Circle(Shape):def __init__(self, radius: float):self.radius = radiusdef area(self) -> float:return 3.14 * self.radius ** 2def get_shape_area(shape: Union[Shape, Rectangle, Circle]) -> float:return shape.area()rectangle = Rectangle(5, 10)
circle = Circle(4)print(get_shape_area(rectangle))
print(get_shape_area(circle))

在这个例子中,我们定义了一个 Shape 基类,它包含一个 area() 方法,但没有实现任何具体逻辑。然后我们定义了两个派生类 RectangleCircle,它们分别重写了 area() 方法以计算自己的面积。最后,我们编写了一个函数 get_shape_area(),它接受一个 Shape 或其子类类型的参数,并调用它们的 area() 方法来获取它们的面积。

在这个例子中,我们使用了 Union 类型注解来指定函数参数的类型,表示它可以是 Shape 或其子类类型。这样,我们就可以在函数中以相同的方式处理不同类型的对象,并获得不同的结果。

需要注意的是,多态最大的好处之一是提高了代码的重用性和可扩展性。通过继承和多态,我们可以在不修改原有代码的情况下,轻松地添加新的行为和属性,或者修改现有的行为和属性,从而达到更好的代码复用和更好的系统扩展。

Python的运算符重载功能,是通过实现特殊方法(也称为魔术方法)来支持。这些特殊方法是以双下划线开头和结尾的,例如 __add__ 是用来重载加法操作符 + 的。

在多态方面,Python中大多数运算符可以作用于多种不同类型的操作数,并且对于不同类型的操作数往往有不同的表现,这本身就是多态的体现。比如,在数字中,加号运算符用于执行加法操作,而在字符串中,加号运算符则用于字符串连接。

举个例子,我们定义一个自定义的类 Vector,它代表二维向量,并希望支持向量的加法操作。为了支持加法操作符 +,我们需要实现特殊方法 __add__,并在其中定义加法操作的行为。

class Vector:def __init__(self, x, y):self.x = xself.y = y# 重载加法操作符def __add__(self, other):return Vector(self.x + other.x, self.y + other.y)

现在我们可以创建两个 Vector 对象,然后使用 + 运算符将它们相加:

v1 = Vector(2, 3)
v2 = Vector(4, 5)
v3 = v1 + v2
print(v3.x, v3.y) # 输出 6 8

此时我们可以看到,不同类型的操作数 v1v2 都支持加法操作符,而且在 Vector 类中,加法的行为也是自定义的。这正是多态的体现。

除了上述例子中的加法操作符,Python还支持许多其他运算符的重载,例如减法、乘法、除法、位运算等等。在自定义类的操作中,运算符的重载让代码变得更具可读性和灵活性。

另外,在Python中,运算符重载也可以应用于内置的数据类型,比如数字、字符串、列表等,这使得开发者可以更自由地使用这些数据类型。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_103138.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据库管理新定义:一款纯Web化免费SQL开发工具,免安装

SQL Studio是一款由麦聪软件研发的多数据库管理工具,提供Windows、Linux 和 MacOS三种版本的软件包,支持中英文两种语言。SQL Studio是用Java编写的,默认使用 JDK 8进行编译。 下载看这里: [SQLStudio] (http://www.maicongs.com/#/home/web)…

地热井监测控制系统解决方案

概述 地热井监测控制系统主要是对地热井采水和回灌进行流量、温度、水位(压力)等参数的实时监测,对地热站现场环境进行实时视频监控。地热井现场和取水井、回灌井安装监测装置,通过无线传输设备将数据实时传输至自然资源局已建中…

上海车展:预售价109.8万元,仰望U8见证国产品牌崛起

如果要评选2023上海车展上比亚迪展台“最亮的星”,估计很多媒体和观众都会毫不迟疑地把票投给仰望U8。 没办法,因为在本届车展上,仰望U8的表现实在是太吸睛了。 作为比亚迪旗下的高端新能源品牌,仰望汽车在上海车展上携两款车型—…

【Leetcode -141.环形链表 -2.两数相加】

Leetcode Leetcode -141.环形链表Leetcode -2.两数相加 Leetcode -141.环形链表 题目:给你一个链表的头节点 head ,判断链表中是否有环。 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给…

测试Ocr工具IronOCR(续2:编写圈选图片识别文本的程序)

上篇文章介绍了加载图片并圈选图片中文字区域的程序实现方式,本文基于此实现识别圈选区域文字内容的程序。主要识别语言包括英文和中文。IronOCR包中自带英文语言包,项目还需安装中文语言包,建议直接安装IronOcr.Languages.Chinese语言包&…

什么样的测试才是优秀的测试

什么样的测试才是优秀的测试 优秀的测试应该包括以下要素: 测试代码的可读性和可维护性 代码在项目中及特定源代码中的组织方式 测试所检查的内容 测试的可靠性及可重复性 测试对测试替身的使用 可读的代码才是可维护的代码 代码较差的可读性与缺陷密度密切相…

软件测试技术那么多,我们该如何分辨?

经典软件测试技术分类: 测试技术是指顺利完成测试的一系列相关过程,有很多可能的分类方式,表2-1就是其中的一种。表中列出了流行的测试技术,也按照上面的讨论对其进行分类:手工测试、自动测试、静态测试、动态测试、功…

今年SMETA审核费用即将涨价

【今年SMETA审核费用即将涨价】 SMETA全称( Sedex Members Ethical Trade Audit ),即Sedex会员社会道德贸易审核,它是Sedex发起的一种负责任的供应链审计方法/项目。 Sedex是一个全球性的责任商业平台,SMETA是审核方法…

手推FlinkML2.2(三)

SQLTransformer(SQL转换器)是一种数据预处理方法,允许您使用SQL语句对数据进行转换和操作。SQL转换器通常用于数据清洗、特征工程和数据聚合等任务,以提高数据分析和机器学习模型的性能。它可以与各种数据处理和存储系统&#xff…

本地搭建属于自己的ChatGPT:基于PyTorch+ChatGLM-6b+Streamlit+QDrant+DuckDuckGo

本地部署chatglm及缓解时效性问题的思路: 模型使用chatglm-6b 4bit,推理使用hugging face,前端应用使用streamlit或者gradio。 微调对显存要求较高,还没试验。可以结合LoRA进行微调。 缓解时效性问题:通过本地数据库…

你的车有通风座椅吗?新款奔驰S400升级原厂主副驾座椅通风

大家好,我是奔之升小志(bzs878),专注名车原厂升级,欢迎戳戳右上角“”号关注一下,持续为您带来精彩改装案例。 座椅通风有什么用?能改善身体与座椅接触面空气流通,达到不出汗的效果…

选择美国虚拟主机需注意的安全问题

在选择美国虚拟主机时,安全性应该是您首要关注的问题。虚拟主机通常是网站托管的最便宜和最方便的方式之一,但也存在安全问题。在本文中,我们将讨论一些您应该注意的安全问题,并提供一些解决方案来保护您的网站。 一、了解虚拟主机…

C++(继承(上))

目录 : 1.引出继承的概念 2.继承的关系和方式 3.继承中的作用域 ------------------------------------------------------------------------------------------------------------------------------ 1.引出继承的概念 这些学生、老师、后勤都具有相同的特征&…

elementUI-el-table组件使用总结

一、背景 vue2项目中用到el-table这个组件&#xff0c;但基础的功能不够用&#xff0c;所以需要自定义 二、表头自定义 比如要让表头展现出下面的形式&#xff1a; 只需使用 slot"header" slot-scope"scope" 对插槽进行定义&#xff0c;并绑定变量 <…

CPU Cache:访问存储速度是如何大幅提升的?

我们了解到不同的物理器件&#xff0c;它们的访问速度是不一样的&#xff1a;速度快的往往代价高、容量小&#xff1b;代价低且容量大的&#xff0c;速度通常比较慢。为了充分发挥各种器件的优点&#xff0c;计算机存储数据的物理器件不会只选择一种&#xff0c;而是以 CPU 为核…

java的validation框架(参数校验)

一.bean validation和hibernate validator参数校验常用约束注解&#xff1a; 空值校验类&#xff1a;Null&#xff0c;NotNull&#xff0c;NotEmpty&#xff0c;NotBlank等 范围校验类&#xff1a;Min&#xff0c;Size&#xff0c;Digits&#xff0c;Future&#xff0c;Negati…

微信小程序自定义搜索标题栏

一&#xff1a;需求 把微信小程序标题栏处变成搜索栏。自定义返回上级页面。 二&#xff1a;需求分析 首先要把小程序标题栏设置为可自定义。然后计算原标题栏的高度组成结构。根据计算高度设置搜索框和返回按钮的布局。最后进行代码功能实现。 三&#xff1a;功能实现 1&…

4月19号软件更新资讯合集....

JavaWeb 微服务前后端分离 EurekaEleVue 版 v1.5.0 发布 v1.5.0 更新如下&#xff1a; 1、解决 token 过期无法跳转至登录页的问题&#xff1b; 2、授权服务进行重构与优化&#xff1b; 一款 Java 语言基于 SpringCloud、SpringSecurity、OAuth2、Eureka、Vue、ElementUI、…

Go Fuzzing:发现你未曾发现的漏洞

文章目录 Fuzzing(模糊测试)要求示例模拟crash 总结参考资料 Fuzzing(模糊测试) go fuzz文档 对于软件开发者而言&#xff0c;一项重要的任务就是确保程序的安全性。而其中一种风险就是软件中可能存在的漏洞。传统的测试方法往往需要耗费大量的时间和人力&#xff0c;而使用F…

4月21号软件更新资讯合集.....

PlayEdu v1.0-beta.3 发布&#xff0c;视频培训解决方案 PlayEdu 是基于 SpringBoot3 Java17 React18 开发的企业内部培训系统。它专注于提供私有化部署方案&#xff0c;包括视频&#xff0c;图片等资源的内网部署。目前主要支持有本地视频上传播放、学员邮箱登录、无限级部门…