当前位置:首页 » 编程语言 » python多重继承

python多重继承

发布时间: 2022-08-02 21:18:25

1. python的多重继承问题

楼上的回答的很正确,简单来说:在对类D进行实例化的时候,你依次对类C和类A进行了初始化,结果就会以后初始化的B为准了

实际上在子类里并不需要去初始化父类,你在实例化子类的同时,继承自父类的对象都会被创建

classA(object):
def__init__(self):
self.a=1

classB(A):
def__init__(self):
self.a=2
self.b=2
classC(B,A):
pass

>>> c = C()

>>> c.a

>>> 2

另外补充一下。父类为新式类的情况下,继承顺序是有影响的。继承顺序上,经典类是深度优先,新式类是广度优先,两种混用的话,分分钟就晕乎了。可以去多做做实验,好好了解。

2. Python有哪些技术上的优点比其他语言好在哪儿

Python有哪些技术上的优点


1. 面向对象和函数式

从根本上讲,Python是一种面向对象的语言。它的类模型支持多态、运算符重载和多重继承等高级概念,并且以Python特有的简洁的语法和类型为背景,OOP十分易于使用。事实上,即使你不懂这些术语,仍会发现学习Python比学习其他OOP语言要容易得多。

除了作为一种强大的代码组织和重用手段以外,Python的OOP本质使它成为其他面向对象系统语言的理想脚本工具。例如,通过适当的粘接代码,Python程序可以对C++、Java和C#的类进行子类的定制。

OOP只是Python的一个选择而已,这一点非常重要。即使不能立马成为一个面向对象高手,但你同样可以继续深入学习。就像C++一样,Python既支持面向对象编程也支持面向过程编程的模式。如果条件允许,其面向对象的工具可以立即派上用场。这对策略开发模式十分有用,该模式常用于软件开发的设计阶段。

除了最初的过程式(语句为基础)和面向对象(类为基础)的编程范式,Python在最近几年内置了对函数式编程的支持——一个多数情况下包括生成器、推导、闭包、映射、装饰器、匿名lambda函数和第一类函数对象的集合。这是对其本身OOP工具的补充和替代。

2. 免费

Python的使用和分发是完全免费的。就像其他的开源软件一样,例如,Tcl、Perl、Linux和Apache。你可以从Internet上免费获得Python的源代码。你可以不受限制地复制Python,或将其嵌入你的系统或者随产品一起发布。实际上,如果你愿意的话,甚至可以销售它的源代码。

但请别误会:“免费”并不代表“没有支持”。恰恰相反,Python的在线社区对用户需求的响应和商业软件一样快。而且,由于Python完全开放源代码,提高了开发者的实力,并产生了一个很大的专家团队。

尽管研究或改变一种程序语言的实现并不是对每一个人来说都那么有趣,但是当你知道如果需要的话可以做到这些,该是多么的令人欣慰。你不需要去依赖商业厂商的智慧,因为最终的文档和终极的净土(源码)任凭你的使用。

Python的开发是由社区驱动的,是Internet大范围的协同合作努力的结果。Python语言的改变必须遵循一套规范而有约束力的程序(称作PEP流程),并需要经过规范的测试系统进行彻底检查。正是这样才使得Python相对于其他语言和系统可以保守地持续改进。

尽管Python 2.X和Python 3.X版本之间的分裂有力并蓄意地破坏了这项传统,但通常它仍然体现在Python的这两个系列内部。

3. Python继承中有两个基类方法重名的问题。在线求解答~~~

1:在DerivedClass2
中,执行init
用了2个函数
BaseClass1.__init__(self)
BaseClass2.__init__(self)
所以
self.name
最后是
'BaseClass2_Name'
2:
调用class3.getname()
根据python多重继承规则,从左到右,深度优先,调用的是BaseClass1的getname方法。
因此输出这个结果。

4. python中super为什么能解决多重继承问题

1. super 并不是一个函数,是一个类名,形如 super(B, self) 事实上调用了 super 类的初始化函数,产生了一个 super 对象;

2. super 类的初始化函数并没有做什么特殊的操作,只是简单记录了类类型和具体实例;
3. super(B, self).func 的调用并不是用于调用当前类的父类的 func 函数;
4. Python 的多继承类是通过 mro 的方式来保证各个父类的函数被逐一调用,而且保证每个父类函数只调用一次(如果每个类都使用 super);

5. 混用 super 类和非绑定的函数是一个危险行为,这可能导致应该调用的父类函数没有调用或者一个父类函数被调用多次。
6. 用 super,遇到修改父类的名字时等情况

5. python 多重继承,继承的几个父类都需要传递参数,怎么在子类计算出父类传递的参数总和呢

运行你的代码:出错位置: c = C()

出错结果:TypeError: __init__() missing 1 required positional argument: ' num1 '

先来看你的程序__main()__部分:a = A(2) 和 b = B(5) 这是类A和类B的一个实例。在python中实例变量是用于每个实例的唯一数据,这就说明你这里的传递参数2或者是5只能用在实例化的 a 或者是 b 下才有作用。 那么重点看c = C( ) ,c是类对象C的实例化,c 只能用自身实例变量才有用,因此前面的实例 a 下的变量 num1=2 和 实例 b 下的变量 num1=5对实例c是无用的。所以,出错结果很明显了缺少传递的位置参数了。这为什么提示缺少1个位置参数呢?下面为你简单讲解一下吧。你也可以用内置方法__mro__() :查看方法或者属性的调用路径——print(类名.__mro__)

类C是多继承类A和类B的,多继承(不存在super()重写方法下),类C的实例化c是怎么工作的——对于实例c调用方法或属性过程是这样的:查找当前类C中是否存在,然后在多个父类中按照从左往右顺序查找(类A中先查找,类B中后查找),只要在这个过程中找到就退出了,后面的就不再查找了。

好吧,给你分析一下你程序的过程:类A和类B中都有__init__()同一个方法,方法相同那首先就查找呗——先查找类C(没有对__init__()进行修改,那就是跳过了),然后再去类A查找,好嘛这就找到了__init__(self, num1),找到了就退出了。所以这样一看对类C进行实例化就需要传递一个参数给num1就够了。你也可以交换继承位置class C(B, A),这样就是类C实例化需要传递一个参数给num2就够了。这样过程就清晰了。

好第三个问题来了:你类C中有两个参数呀num1和num2,而实例化又仅需要一个参数就够了,这样就肯定会产生问题了。

不信你试试给c = C(2)产生错误:AttributeError: 'C' object has no attribute 'num2'

解决方法1:既然没有属性num2就在类C中删掉就是了,然后c = C(2)就可以运行成功了。

解决方案2:类变量用于类的所有实例共享的属性和方法。因此,要想共用这两个变量num1和num2,就得让搜索的时候不要进到类A和类B中前提下,将它们变成对应的类变量就可以了。第一个前提很好实现:在类C下 定义:def __init__(self) : pass 第二个条件也比较好实现:将类A或类B的 __init__(self, num) : X.num = num X为对应的类名。(说明:self表示类实例化对象,即self.num 表示实例变量;X表示类对象,则X.num表示类变量),这样就可以共享类A和类B的变量了。

classA:
def__init__(self,num1):
A.num1=num1


classB:
def__init__(self,num2):
B.num2=num2


classC(A,B):

def__init__(self):
pass

defnum_sum(self):
returnself.num2+self.num1


if__name__=='__main__':
a=A(2)
b=B(5)
c=C()
print(c.num_sum())

6. python的简单问题

要把代码发现来才知道,以下是常见的错误下面终于要讲到当你用到更多的Python的功能(数据类型,函数,模块,类等等)时可能碰到的问题了。由于篇幅有限,这里尽量精简,尤其是对一些高级的概念。要想了解更多的细节,敬请阅读Learning Python, 2nd Edition的逗小贴士地以及逗Gotchas地章节。 打开文件的调用不使用模块搜索路径当你在Python中调用open()来访问一个外部的文件时,Python不会使用模块搜索路径来定位这个目标文件。它会使用你提供的绝对路径,或者假定这个文件是在当前工作目录中。模块搜索路径仅仅为模块加载服务的。不同的类型对应的方法也不同列表的方法是不能用在字符串上的,反之亦然。通常情况下,方法的调用是和数据类型有关的,但是内部函数通常在很多类型上都可以使用。举个例子来说,列表的reverse方法仅仅对列表有用,但是len函数对任何具有长度的对象都适用不能直接改变不可变数据类型记住你没法直接的改变一个不可变的对象(例如,元组,字符串): T = (1, 2, 3) T[2] = 4 # 错误 用切片,联接等构建一个新的对象,并根据需求将原来变量的值赋给它。因为Python会自动回收没有用的内存,因此这没有看起来那么浪费: T = T[:2] + (4,) # 没问题了: T 变成了 (1, 2, 4) 使用简单的for循环而不是while或者range 当你要从左到右遍历一个有序的对象的所有元素时,用简单的for循环(例如,for x in seq:)相比于基于while-或者range-的计数循环而言会更容易写,通常运行起来也更快。除非你一定需要,尽量避免在一个for循环里使用range:让Python来替你解决标号的问题。在下面的例子中三个循环结构都没有问题,但是第一个通常来说更好;在Python里,简单至上。 S = "lumberjack" for c in S: print c # 最简单 for i in range(len(S)): print S[i] # 太多了 i = 0 # 太多了 while i len(S): print S[i]; i += 1 不要试图从那些会改变对象的函数得到结果诸如像方法list.append()和list.sort()一类的直接改变操作会改变一个对象,但不会将它们改变的对象返回出来(它们会返回None);正确的做法是直接调用它们而不要将结果赋值。经常会看见初学者会写诸如此类的代码: mylist = mylist.append(X) 目的是要得到append的结果,但是事实上这样做会将None赋值给mylist,而不是改变后的列表。更加特别的一个例子是想通过用排序后的键值来遍历一个字典里的各个元素,请看下面的例子: D = {...} for k in D.keys().sort(): print D[k] 差一点儿就成功了——keys方法会创建一个keys的列表,然后用sort方法来将这个列表排序——但是因为sort方法会返回None,这个循环会失败,因为它实际上是要遍历None(这可不是一个序列)。要改正这段代码,将方法的调用分离出来,放在不同的语句中,如下: Ks = D.keys() Ks.sort() for k in Ks: print D[k] 只有在数字类型中才存在类型转换在Python中,一个诸如123+3.145的表达式是可以工作的——它会自动将整数型转换为浮点型,然后用浮点运算。但是下面的代码就会出错了: S = "42" I = 1 X = S + I # 类型错误 这同样也是有意而为的,因为这是不明确的:究竟是将字符串转换为数字(进行相加)呢,还是将数字转换为字符串(进行联接)呢看在Python中,我们认为逗明确比含糊好地(即,EIBTI(Explicit is better than implicit)),因此你得手动转换类型: X = int(S) + I # 做加法: 43 X = S + str(I) # 字符串联接: "421" 循环的数据结构会导致循环尽管这在实际情况中很少见,但是如果一个对象的集合包含了到它自己的引用,这被称为循环对象(cyclic object)。如果在一个对象中发现一个循环,Python会输出一个[…],以避免在无限循环中卡住: >>> L = ['grail'] # 在 L中又引用L自身会 >>> L.append(L) # 在对象中创造一个循环 >>> L ['grail', [...]] 除了知道这三个点在对象中表示循环以外,这个例子也是很值得借鉴的。因为你可能无意间在你的代码中出现这样的循环的结构而导致你的代码出错。如果有必要的话,维护一个列表或者字典来表示已经访问过的对象,然后通过检查它来确认你是否碰到了循环。赋值语句不会创建对象的副本,仅仅创建引用这是Python的一个核心理念,有时候当行为不对时会带来错误。在下面的例子中,一个列表对象被赋给了名为L的变量,然后L又在列表M中被引用。内部改变L的话,同时也会改变M所引用的对象,因为它们俩都指向同一个对象。 >>> L = [1, 2, 3] # 共用的列表对象 >>> M = ['X', L, 'Y'] # 嵌入一个到L的引用 >>> M ['X', [1, 2, 3], 'Y'] >>> L[1] = 0 # 也改变了M >>> M ['X', [1, 0, 3], 'Y'] 通常情况下只有在稍大一点的程序里这就显得很重要了,而且这些共用的引用通常确实是你需要的。如果不是的话,你可以明确的给他们创建一个副本来避免共用的引用;对于列表来说,你可以通过使用一个空列表的切片来创建一个顶层的副本: >>> L = [1, 2, 3] >>> M = ['X', L[:], 'Y'] # 嵌入一个L的副本 >>> L[1] = 0 # 仅仅改变了L,但是不影响M >>> L [1, 0, 3] >>> M ['X', [1, 2, 3], 'Y'] 切片的范围起始从默认的0到被切片的序列的最大长度。如果两者都省略掉了,那么切片会抽取该序列中的所有元素,并创造一个顶层的副本(一个新的,不被公用的对象)。对于字典来说,使用字典的dict.()方法。静态识别本地域的变量名 Python默认将一个函数中赋值的变量名视作是本地域的,它们存在于该函数的作用域中并且仅仅在函数运行的时候才存在。从技术上讲,Python是在编译def代码时,去静态的识别本地变量,而不是在运行时碰到赋值的时候才识别到的。如果不理解这点的话,会引起人们的误解。比如,看看下面的例子,当你在一个引用之后给一个变量赋值会怎么样: >>> X = 99 >>> def func(): ... print X # 这个时候还不存在 ... X = 88 # 在整个def中将X视作本地变量 ... >>> func( ) # 出错了! 你会得到一个逗未定义变量名地的错误,但是其原因是很微妙的。当编译这则代码时,Python碰到给X赋值的语句时认为在这个函数中的任何地方X会被视作一个本地变量名。但是之后当真正运行这个函数时,执行print语句的时候,赋值语句还没有发生,这样Python便会报告一个逗未定义变量名地的错误。事实上,之前的这个例子想要做的事情是很模糊的:你是想要先输出那个全局的X,然后创建一个本地的X呢,还是说这是个程序的错误看如果你真的是想要输出这个全局的X,你需要将它在一个全局语句中声明它,或者通过包络模块的名字来引用它。默认参数和可变对象在执行def语句时,默认参数的值只被解析并保存一次,而不是每次在调用函数的时候。这通常是你想要的那样,但是因为默认值需要在每次调用时都保持同样对象,你在试图改变可变的默认值(mutable defaults)的时候可要小心了。例如,下面的函数中使用一个空的列表作为默认值,然后在之后每一次函数调用的时候改变它的值: >>> def saver(x=[]): # 保存一个列表对象 ... x.append(1) # 并每次调用的时候 ... print x # 改变它的值 ... >>> saver([2]) # 未使用默认值 [2, 1] >>> saver() # 使用默认值 [1] >>> saver() # 每次调用都会增加! [1, 1] >>> saver() [1, 1, 1] 有的人将这个视作Python的一个特点——因为可变的默认参数在每次函数调用时保持了它们的状态,它们能提供像C语言中静态本地函数变量的类似的一些功能。但是,当你第一次碰到它时会觉得这很奇怪,并且在Python中有更加简单的办法来在不同的调用之间保存状态(比如说类)。要摆脱这样的行为,在函数开始的地方用切片或者方法来创建默认参数的副本,或者将默认值的表达式移到函数里面;只要每次函数调用时这些值在函数里,就会每次都得到一个新的对象: >>> def saver(x=None): ... if x is None: x = [] # 没有传入参数看 ... x.append(1) # 改变新的列表 ... print x ... >>> saver([2]) # 没有使用默认值 [2, 1] >>> saver() # 这次不会变了 [1] >>> saver() [1] 其他常见的编程陷阱下面列举了其他的一些在这里没法详述的陷阱:在顶层文件中语句的顺序是有讲究的:因为运行或者加载一个文件会从上到下运行它的语句,所以请确保将你未嵌套的函数调用或者类的调用放在函数或者类的定义之后。 reload不影响用from加载的名字:reload最好和import语句一起使用。如果你使用from语句,记得在reload之后重新运行一遍from,否则你仍然使用之前老的名字。在多重继承中混合的顺序是有讲究的:这是因为对superclass的搜索是从左到右的,在类定义的头部,在多重superclass中如果出现重复的名字,则以最左边的类名为准。在try语句中空的except子句可能会比你预想的捕捉到更多的错误。在try语句中空的except子句表示捕捉所有的错误,即便是真正的程序错误,和sys.exit()调用,也会被捕捉到。

7. 如何进行创建Python 多重继承求解

然而,当项目达到某种程度的复杂性之后,过程代码通常会暴露出其根本缺陷。下面让我们直接进入上一个示例的面向对象版本,并看看这样有何变化。 #!/usr/bin/env python from subprocess import Popen, PIPE import re class DiskMonitor(): """Disk Monitoring Class""" def __init__(self, pattern="2[0-9]%", message="CAPACITY WARNING", cmd = "df -h"): self.pattern = pattern self.message = message self.cmd = cmd def disk_space(self): """Disk space capacity flag method""" ps = Popen(self.cmd, shell=True,stdout=PIPE,stderr=PIPE) output_lines = ps.stdout.readlines() for line in output_lines: lineline = line.strip() if re.search(self.pattern,line): print "%s %s" % (self.message,line) class MyDiskMonitor(DiskMonitor): """Customized Disk Monitoring Class""" def disk_space(self): ps = Popen(self.cmd, shell=True,stdout=PIPE,stderr=PIPE) print "RAW DISK REPORT:" print ps.stdout.read() if __name__ == "__main__": d = MyDiskMonitor() d.disk_space() 查看该代码的面向对象版本,可以看到代码变得更加抽象。有时,太多的抽象会导致设计问题,但是在此例中,它允许您将问题分离为更多可重用的部分。DiskMonitor 类具有 __init__ method,您可以在其中定义新的参数,并且 disk_space 函数现在是该类中的一个方法。 使用这种新的样式,您无需更改原始代码即可容易地重用和自定义各个部分,而使用过程代码时则通常必须更改原始代码。Python 多重继承面向对象的设计的一个更加功能强大、通常也被过度使用的方面是继承。继承允许您在新的类中重用和自定义现有的代码。让我们在下一个示例中看看继承可能像什么样子。 此输出与前面带标记的版本区别非常大,因为它只是使用顶部注入的 print 语句来打印的未经筛选的 df –h 命令结果。通过重写 MyDiskMonitor 类中的方法,您能够完全改变 disk_space 方法的意图。 有关Python 解释器说明介绍如何创建Python多线程环境浅析Python多线程问题如何进行建立Python主线程?执行Python 解释器相关说明允许您重用其他类中的属性的 Python 多重继承是这个“MyDiskMonitor(DiskMonitor)”语句。您只需在定义新类的名称时,将先前的类的名称放在括号内。一旦完成此步骤,您立即可以访问其他类属性来做自己希望的事情。但是乐趣不仅于此。通过添加另一个通过电子邮件来发送标记消息的方法。也许是将其命名为 disk_alert(self),这样就可以进一步自定义新类。这是面向对象的设计的美妙之处;它允许有经验的开发人员不断重用已编写的代码,从而节省大量的时间。 遗憾的是,面向对象的编程也有其不利的一面。所有这些抽象都是以复杂性为代价的,如果抽象过度,可能会彻底地弄巧成拙。由于Python 多重继承,抽象可以达到相当有害的复杂程度。您是否能够想象只是为了编写一个方法也要查看多个文件的情况?无论相信与否,这种情况的确会发生,并且代表了面向对象编程的不幸现实。

热点内容
怎么看笔记本配置好坏怎么对比 发布:2025-01-23 08:50:00 浏览:514
安卓q用起来怎么样 发布:2025-01-23 08:49:14 浏览:294
foreach数据库 发布:2025-01-23 08:49:05 浏览:741
什么是车棚配置 发布:2025-01-23 08:42:58 浏览:312
智能电视盒子无线网密码在哪里 发布:2025-01-23 08:42:14 浏览:277
代理提取源码 发布:2025-01-23 08:41:35 浏览:62
nas网络服务器为什么贵 发布:2025-01-23 08:00:00 浏览:941
语音服务器未连接如何连接视频 发布:2025-01-23 07:59:11 浏览:883
日流量10万需要什么类型服务器 发布:2025-01-23 07:58:27 浏览:501
服务器获取地址失败 发布:2025-01-23 07:55:18 浏览:850