python中的继承与多态,dir()函数
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"
在上面的示例代码中,我们定义了两个父类A
和B
,分别有相同的方法名hello
,同时我们分别创建了两个子类C
和D
,并使用多继承方式分别继承了A
和B
。
在子类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()
方法,并打印出一条通用的动物发声信息。然后我们定义了两个派生类 Dog
和 Cat
,它们都继承了 Animal
的 sound()
方法,但改写了此方法以打印自己的声音信息。最后,我们编写了一个函数 do_sound()
,它接受一个 Animal
类型的参数,并调用它的 sound()
方法。
当我们创建一个实例 dog
或 cat
时,它们分别是 Dog
和 Cat
类型的对象,同时也都是 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()
方法,但没有实现任何具体逻辑。然后我们定义了两个派生类 Rectangle
和 Circle
,它们分别重写了 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
此时我们可以看到,不同类型的操作数 v1
和 v2
都支持加法操作符,而且在 Vector
类中,加法的行为也是自定义的。这正是多态的体现。
除了上述例子中的加法操作符,Python还支持许多其他运算符的重载,例如减法、乘法、除法、位运算等等。在自定义类的操作中,运算符的重载让代码变得更具可读性和灵活性。
另外,在Python中,运算符重载也可以应用于内置的数据类型,比如数字、字符串、列表等,这使得开发者可以更自由地使用这些数据类型。
相关文章:
python中的继承与多态,dir()函数
Python继承 在继承关系中,已有的、设计好的类称为父类或基类,新设计的类称为子类或派生类。派生类可以继承父类的公有成员,但是不能继承其私有成员。如果需要在派生类中调用基类的方法,可以使用内置函数super()或者通过“基类名.…...

C++练级之初级:第五篇
C练级之初级:第五篇 第五篇 C练级之初级:第五篇1.auto关键字2.for循环改进3.指针空值nullptr4.内联函数4.1内联函数的概念4.2内联函数的注意点 总结 1.auto关键字 🤔什么是auto(automatic的缩写,自动的意思)关键字? au…...

JMeter的使用(二)
九、直连数据库 通过直连数据库让程序代替接口访问数据库,如果二者预期结果不一致,就找到了程序缺陷。 获取某条学院的名字,放在百度搜索: JMeter 不具备直连数据库功能,必须整合第三方(jar包)实现配置数据库的连接通过JDBC Re…...

C/C++文件操作/IO流
学习任务: ⭐认识文件。⭐学习C语言中文件如何打开和关闭。⭐学习C语言中文件的读写方法(包括顺序读写和随机读写)。⭐学习C语言文件操作中如何判断文件读取结束。⭐简单了解FILE缓冲区。⭐认识流。⭐学习C的IO流,包括标准IO流和文…...

推荐 7 个超牛的 Spring Cloud 实战项目
个 把一个大型的单个应用程序和服务拆分为数个甚至数十个的支持微服务,这就是微服务架构的架构概念,通过将功能分解到各个离散的服务中以实现对解决方案的解耦。 关于微服务相关的学习资料不多,而 GitHub 上的开源项目可以作为你微服务之旅…...

Linux信号:信号 信号集 信号集函数
1. 信号的概念 Linux进程间通信的方式之一。信号也称为“软件中断”。 信号特点: 简单;携带信息有限;满足特定条件才发送信号;可进行用户空间和内核空间进程的交互; 信号4要素: (1…...

详解八大排序算法-附动图和源码(插入,希尔,选择,堆排序,冒泡,快速,归并,计数)
目录 🍏一.排序的概念及应用🍏 1.排序的概念 2.排序的应用 3.常用的排序算法 🍎二.排序算法的实现🍎 1.插入排序 1.1直接插入排序 1.2希尔排序(缩小增量排序) 2.选择排序 2.1直接选择排序 2.2堆排序…...
网络编程--协议、协议族、地址族
写在前面 这里先介绍下socket函数(Windows版本)的函数声明,后续内容均围绕该声明展开: #include <winsock2.h> //af: 指定该套接字的协议族 //type: 指定该套接字的数据传输方式 //protocol: 指定该套接字的最终协议 //返…...

Linux入门操作
pwd 查看当前目录 与 自动补全 文件详情 drwxrwxr-x d代表文件夹 -代表文件 其中rwx rwx r-x r是可读 w是可写 x 执行 第一组(前三个)指文件拥有者的权限 第二组(中三个)代表文件拥有的组的权限 第三组(后三个&am…...

1。C语言基础知识回顾
学习嵌入式的C基础知识,主要包括几个核心知识点:三大语法结构、常用的数据类型、函数、结构体、指针、文件操作。 一、顺序结构 程序自上而下依次执行、没有分支、代码简单。 常见顺序结构有:四则运算:,-࿰…...

学习如何通过构建一个简单的JavaScript颜色游戏来操作DOM
学习如何通过构建一个简单的JavaScript颜色游戏来操作DOM 题目要求 我们将构建一个简单的颜色猜谜游戏。每次游戏启动时,都会选择一个随机的RGB颜色代码。根据游戏模式,我们将在屏幕上提供三个(简单)或六个(困难&…...

【算法学习】—n皇后问题(回溯法)
【算法学习】—n皇后问题(回溯法) 1. 什么是回溯法? 相信"迷宫"是许多人儿时的回忆,大家小时候一定都玩过迷宫游戏。我们从不用别人教,都知道走迷宫的策略是: 当遇到一个岔路口,会有以下两种情况…...
万亿OTA市场进入新爆发期,2025或迎中国汽车软件付费元年
伴随智能汽车市场规模发展,越来越多的汽车产品具备OTA能力,功能的优化、以及服务的差异化,成为了车企竞争的新战场。 例如,今年初,问界M5 EV迎来了首次OTA升级,升级内容覆盖用户在实际用车中的多个场景&am…...

Android硬件通信之 蓝牙Mesh通信
一,简介 蓝牙4.0以下称为传统蓝牙,4.0以上是低功耗蓝牙,5.0开始主打物联网 5.0协议蓝牙最重要的技术就是Mesh组网,实现1对多,多对多的无线通信。即从点对点传输发展为网络拓扑结构,主要领域如灯光控制等&…...
PG数据库实现bool自动转smallint的方式
删除函数: 语法: DROP FUNCTION IF EXISTS your_schema_name.function_name(arg_type1, arg_type2) CASCADE RESTRICT; 实例: DROP FUNCTION IF EXISTS platformyw.boolean_to_smallint(bool) CASCADE RESTRICT; 查询是否存在函数 语法: SELE…...

易观千帆 | 2023年3月证券APP月活跃用户规模盘点
易观:2023年3月证券服务应用活跃人数14131.58万人,相较上月,环比增长0.61%,同比增长0.60%;2023年3月自营类证券服务应用Top10 活跃人数6221.44万人,环比增长0.08%;2023年3月第三方证券服务应用T…...

2023年江苏专转本成绩查询步骤
2023年江苏专转本成绩查询时间 2023年江苏专转本成绩查询时间预计在5月初,参加考试的考生,可以关注考试院发布的消息。江苏专转本考生可在规定时间内在省教育考试院网,在查询中心页面中输入准考证号和身份证号进行查询,或者拨…...
JavaScript中sort()函数
sort()函数是javascript中自带函数,这个函数的功能是排序。 使用sort()函数时,函数参数如果不设置的话,以默认方式进行排序,就是以字母顺序进行排序,准确的讲就是按照字符编码的顺序进行排序。 var arr [3,2,3,34,1…...

泰克Tektronix DPO5204B混合信号示波器
特征 带宽:2 GHz输入通道:4采样率:1 或 2 个通道上为 5 GS/s、10 GS/s记录长度:所有 4 个通道 25M,50M:1 或 2 个通道上升时间:175 皮秒MultiView zoom™ 记录长度高达 250 兆点>250,000 wf…...

突破传统监测模式:业务状态监控HM的新思路
作者:京东保险 管顺利 一、传统监控系统的盲区,如何打造业务状态监控。 在系统架构设计中非常重要的一环是要做数据监控和数据最终一致性,关于一致性的补偿,已经由算法部的大佬总结过就不在赘述。这里主要讲如何去补偿ÿ…...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...

通过Wrangler CLI在worker中创建数据库和表
官方使用文档:Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后,会在本地和远程创建数据库: npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库: 现在,您的Cloudfla…...

CMake基础:构建流程详解
目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...

【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...
Java 加密常用的各种算法及其选择
在数字化时代,数据安全至关重要,Java 作为广泛应用的编程语言,提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景,有助于开发者在不同的业务需求中做出正确的选择。 一、对称加密算法…...

(转)什么是DockerCompose?它有什么作用?
一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器。 Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...

Linux --进程控制
本文从以下五个方面来初步认识进程控制: 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程,创建出来的进程就是子进程,原来的进程为父进程。…...
C#中的CLR属性、依赖属性与附加属性
CLR属性的主要特征 封装性: 隐藏字段的实现细节 提供对字段的受控访问 访问控制: 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性: 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑: 可以…...
多模态图像修复系统:基于深度学习的图片修复实现
多模态图像修复系统:基于深度学习的图片修复实现 1. 系统概述 本系统使用多模态大模型(Stable Diffusion Inpainting)实现图像修复功能,结合文本描述和图片输入,对指定区域进行内容修复。系统包含完整的数据处理、模型训练、推理部署流程。 import torch import numpy …...

手机平板能效生态设计指令EU 2023/1670标准解读
手机平板能效生态设计指令EU 2023/1670标准解读 以下是针对欧盟《手机和平板电脑生态设计法规》(EU) 2023/1670 的核心解读,综合法规核心要求、最新修正及企业合规要点: 一、法规背景与目标 生效与强制时间 发布于2023年8月31日(OJ公报&…...