Ⅰ 学明白了 python 多继承中的 MRO 算法有什么用

可能你有C++的基础吧,C++确实可以不用带上this。
我把你的代码稍微改了一下,你可以分别看看版cls1.n、cls2.n、self.n的输出权。
class cls1:
n=3
class cls2(cls1):
def __init__(self,cls1=cls1):
cls2.n += 1
self.n += 2
print 'cls1.n:%s'%cls1.n
print 'cls2.n:%s'%cls2.n
print 'self.n:%s'%self.n

cls2()
print 'cls1.n:%s'%cls1.n
可以看出两个类和一个对象都可以在这里调用它们的n属性,如果只敲一个n别人读你的代码时就比较容易产生岐义,虽然少打了5个字符,但是不符合简单明确的pythonic哲学。
当然你也可以就认为python语法规则就是这么规定的。

Ⅱ 是否有等同于局部类任何Python

1. 如果你的问题真的只是正与一大班在编辑器中,第一个解决方案,我会真正期待的是一个更好的方式来打破的问题。第二个解决方案是一个更好的编辑器,最好是有代码折叠。
这就是说,有几个方法你可能会打破一个班级分成多个文件。python让一个文件夹作为一个模块通过将一个__init__.py在里面,然后可以从其他文件中导入的东西。我们'这种能力在每一个解决方案。做一个调用,比如文件夹,bigclass第一。
在文件夹放.py文件将你的类.each人都应该包含在最终的类,而不是类函数和变量定义。在__init__.py在文件夹中写入以下加入他们一起。
class Bigclass(object):

from classdef1 import foo, bar, baz, quux
from classdef2 import thing1, thing2
from classdef3 import magic, moremagic
# unfortunately, "from classdefn import *" is an error or warning

num = 42 # add more members here if you like

这有你最终直接来源于单个类的优势object,这将很好看在你的继承图。
你的类的你多重继承的部分。在你的各个模块,你会写一个类定义Bigclass带之类的部件。然后在你的__init__.py写:
import classdef1, classdef2, classdef3

class Bigclass(classdef1.Bigclass, classdef2.Bigclass, classdef3.Bigclass):
num = 42 # add more members if desired

如果多重继承的问题,你可以使用单继承:只需每个类继承自另外一个连锁的方式。假设你没有在多个类中定义的话,就是顺序无关紧要。例如,classdef2.py会是这样的:
import classdef1
class Bigclass(classdef1.Bigclass):
# more member defs here

classdef3将进口Bigclass从classdef2并添加到它,等等。您的__init__.py将刚刚导入的最后一个:
from classdef42 import Bigclass

我一般喜欢#1它是更加明确要导入从哪个文件,但所有这些解决方案可以为你工作。
类中的任何一种情况你可以导入,使用文件夹作为模块from bigclass import Bigclass

2.
包含数百行确实发生“在野外”(我看到在类定义中流行的开放源代码的基于Python的,但我相信,如果你思考什么都做,将有可能减少到可管理的大多数类的长度。点的例子:
寻找其中大部分代码出现一次以上的地方。打破代码分解到其与调用它的每一个地方
“私人”的方法是做任何对象状态的可以带出的类作为独立的功能。
只应在特定条件下被调用的方法可能表明需要在子类的地方。
直接解决你的问题,它可以分裂一个类的定义.a种方法是“猴子补丁”之类通过定义它,然后添加外功能,它另一个是内置的type功能“手动”来创建类,其提供的任何基类,并在一本字典属性。但我不这样做,只是定义将是长期的,否则。那种治愈的是比疾病在我看来更糟。

3.
我已经有类似玩弄各地。是一个抽象语法树节点的类层次结构,然后我希望把所有的如:以漂亮的funtions在一个单独的prettyprint.py文件,但仍然有他们的班。
有一件事我想是一个装饰的放装饰的功能作为一个属性上指定的类。在我而言这是prettyprint.py包含大量的def prettyprint(self)所有装饰着不同@inclass(...)有这方面的一个问题是,必须确保该子文件总是进口的,而且它们所依赖的主类,这对于一个循环依赖,这可能
def inclass(kls):
"""
Decorator that adds the decorated function
as a method in specified class
"""
def _(func):
setattr(kls,func.__name__, func)
return func
return _

## exampe usage
class C:
def __init__(self, d):
self.d = d

# this would be in a separate file.
@inclass(C)
def meth(self, a):
"""Some method"""
print "attribute: %s - argument: %s" % (self.d, a)

i = C(10)
print i.meth.__doc__
i.meth(20)

4.
我已经,但是,这个包称为部分索赔增加的部分类别的支持。
好像还有一些其他的方法,你会这样自己也是如此。
你可以分开的类的部分作为单独的文件混入,然后将它们导入所有和继承他们。
或者,您也可以在每个类的,然后在中央文件中导入,并指定其为一个类的属性,来创建整个对象。像这样:
a.py:
def AFunc( self, something ):
# Do something
pass

b.py:
def BFunc( self, something ):
# Do something else
pass

c.py:
import a, b

class C:
AFunc = a.AFunc
BFunc = b.BFunc

你甚至可以走那么远,自动完成这个过程,如果你真的想要的-通过所有模块所提供的功能回路a和b然后将它们添加为属性上C。虽然这可能是总矫枉过正。
可能还有其他的(可能更好)的方式去了解它,但那些都是闪入脑海的2。

5.
首先,我想说,这可能不是一个好主意只是为了找到你的类中的地方更容易-这将是最好的补充高亮部分等。不过,我看你能做到这一点有两种方式:
写的类在几个文件,然后读取它们的文字,将它们连接起来,并exec结果字符串。
在每个文件创建一个单独的类,然后继承他们都为一个大师班的混入。但是,如果你继承另一个类已经就可能导致MRO问题。你能解决这个问题通过创建其手动解决MRO你的大师班,但是这可能
最简单的是第一个选项。

6.
首先,我不明白怎么分裂全班分成多个文件,使编辑变得更容易.a个体面的IDE应该能够很容易地找到是否在一个文件或多个,如果你是一个体面的IDE,分裂的维护者有猜测哪些文件是,这听起来更难,而不是更容易。
更多这个类-如此之大,你想有一个特殊的语言功能只是为了支撑其重量-破碎的声音。我们是如何多行代码在谈论什么?几乎可以肯定,这将是一个更好的主意,这样做的一个:
重构代码复制到更少的,更普遍的原语
定义一个基类和子类与扩展它作为卡罗利霍瓦特在暗示(这是最接近于“局部类”那你问我会赞同)
定义一些单独的类来封装这种不同部分
类的功能,这个类的实例的
较小的。

7.
的情况-我想slipt我班2个文件。
原因是-我想第1部分为GUI布局,只有布局
而另一个文件保存了所有的功能。
像C#的部分类.a个用于XAML和另一个用于功能。

8.
你可以做到这一点的,像这样的装饰:
class Car(object):

def start(self):
print 'Car has started'

def extends(klass):
def decorator(func):
setattr(klass, func.__name__, func)
return func
return decorator

#this can go in a different mole/file
@extends(Car)
def do_start(self):
self.start()

#so can this
car = Car()
car.do_start()

#=> Car has started

Ⅲ Python,super继承的问题,求解答。

这可能需要了解下 python 当中的:
Method Resolution Order (mro)
中文的话,应该是"方法解析顺序".我也是刚查的.
如果你在最后输出 D().__class__.__mro__
你就可以看到 python 是按什么样的顺序处理继承的了.
它给我的输出是:

(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
先 D_start - B_start - C_start - A_start - A_end - C_end - B_end - D_end

Ⅳ python类中的super,原理如何MRO是什么东东

首先得说明的是,Python的类分为经典类 和 新式类
经典类是python2.2之前的东西,但是在2.7还在兼容,但是在3之后的版本就只承认新式类了
新式类在python2.2之后的版本中都可以使用!

Ⅳ python如何进阶学习

Python进阶学习,比较高端的是Python架构师,想要成为Python架构师,不仅要技术过硬,回还要有全局意识,拥有丰富的项答目经验,这些可以从实践中来,也可以向资深架构师学习,目前,也有培训机构培训这项技能,这些都是很好的学习途径!

Ⅵ 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,遇到修改父类的名字时等情况

Ⅶ Python有什么缺点呢

Python的定位是“优雅”、“明确”、“简单”,所以Python程序看上去总是简单易懂,初学者学Python,不但入门容易,而且将来深入下去,可以编写那些非常非常复杂的程序。
python语言的优点
⑴作为初学python的科班出身的小白,python非常简单,非常适合人类阅读。阅读一个良好的Python程序就感觉像是在读英语一样,尽管这个英语的要求非常严格!Python的这种伪代码本质是它最大的优点之一。它使你能够专注于解决问题而不是去搞明白语言本身。
⑵易学。python虽然是用c语言写的,但是它摈弃了c中非常复杂的指针,简化了python的语法。
⑶Python是FLOSS(自由/开放源码软件)之一。简单地说,你可以自由地发布这个软件的拷贝、阅读它的源代码、对它做改动、把它的一部分用于新的自由软件中。Python希望看到一个更加优秀的人创造并经常改进。
⑷可移植性————由于它的开源本质,Python已经被移植在许多平台上(经过改动使它能够工作在不同平台上)。如果你小心地避免使用依赖于系统的特性,那么你的所有Python程序无需修改就可以在下述任何平台上面运行。这些平台包括Linux、Windows、FreeBSD、Macintosh、Solaris、OS/2、Amiga、AROS、AS/400、BeOS、OS/390、z/OS、Palm OS、QNX、VMS、Psion、Acom RISC OS、VxWorks、PlayStation、Sharp Zaurus、Windows CE甚至还有PocketPC、Symbian以及Google基于linux开发的Android平台!
⑸在计算机内部,Python解释器把源代码转换成称为字节码的中间形式,然后再把它翻译成计算机使用的机器语言并运行。事实上,由于你不再需要担心如何编译程序,如何确保连接转载正确的库等等,所有这一切使得使用Python更加简单。由于你只需要把你的Python程序拷贝到另外一台计算机上,它就可以工作了,这也使得你的Python程序更加易于移植。
⑹Python既支持面向过程的函数编程也支持面向对象的抽象编程。在面向过程的语言中,程序是由过程或仅仅是可重用代码的函数构建起来的。在面向对象的语言中,程序是由数据和功能组合而成的对象构建起来的。与其他主要的语言如C++和Java相比,Python以一种非常强大又简单的方式实现面向对象编程。
⑺ 可扩展性和可嵌入性。如果你需要你的一段关键代码运行得更快或者希望某些算法不公开,你可以把你的部分程序用C或C++编写,然后在你的Python程序中使用它们。你可以把Python嵌入你的C/C++程序,从而向你的程序用户提供脚本功能。
⑻丰富的库。Python标准库确实很庞大。python有可定义的第三方库可以使用。它可以帮助你处理各种工作,包括正则表达式、文档生成、单元测试、线程、数据库、网页浏览器、CGI、FTP、电子邮件、XML、XML-RPC、HTML、WAV文件、密码系统、GUI(图形用户界面)、Tk和其他与系统有关的操作。记住,只要安装了Python,所有这些功能都是可用的。这被称作Python的“功能齐全”理念。除了标准库以外,还有许多其他高质量的库,如wxPython、Twisted和Python图像库等等。
⑼ Python确实是一种十分精彩又强大的语言。它合理地结合了高性能与使得编写程序简单有趣的特色。
⑽规范的代码。Python采用强制缩进的方式使得代码具有极佳的可读性。
python语言的缺点
很多时候不能将程序连写成一行,如import sys;for i in sys.path:print i。而perl和awk就无此限制,可以较为方便的在shell下完成简单程序,不需要如Python一样,必须将程序写入一个.py文件。(对很多用户而言这也不算是限制)
⑴运行速度,有速度要求的话,用C++改写关键部分吧。不过对于用户而言,机器上运行速度是可以忽略的。因为用户根本感觉不出来这种速度的差异。
⑵既是优点也是缺点,python的开源性使得Python语言不能加密,但是目前国内市场纯粹靠编写软件卖给客户的越来越少,网站和移动应用不需要给客户源代码,所以这个问题就是问题。不过随着时间的推移,很多国内软件公司,尤其是游戏公司,也开始规模使用他。
⑶ 构架选择太多(没有像C#这样的官方.net构架,也没有像ruby由于历史较短,构架开发的相对集中。Ruby on Rails 构架开发中小型web程序天下无敌)。不过这也从另一个侧面说明,python比较优秀,吸引的人才多,项目也多。

Ⅷ 又来求助了,大神求解答 python类继承的问题

老式类就是经典类,不是继承自object类.在多继承时采用深度优先遍历父类.
新式类就是基类继承自object类 class xxx(object).多继承时采用一种新的C3 算法来遍历父类.
实例如下:

新式类的打印结果如下:

1speak: I am mother

旧式类的打印结果如下:

1speak: I am GrandFather

由此我们可以看出新式类的搜索过程为:Son-->Father-->Mother,而旧式类的搜索过程为:Son-->Father-->GrandFather

我们可以看出旧式类和我们预期的继承不太一样。

老式类就是经典类,不是继承自object类.在多继承时采用深度优先遍历父类.
新式类就是基类继承自object类 class xxx(object).多继承时采用一种新的C3 算法来遍历父类.

为什么采用C3算法呢?

C3算法最早被提出是用于Lisp的,应用在Python中是为了解决原来基于深度优先搜索算法不满足本地优先级,和单调性的问题。

本地优先级:指声明时父类的顺序,比如C(A,B),如果访问C类对象属性时,应该根据声明顺序,优先查找A类,然后再查找B类。

单调性:如果在C的解析顺序中,A排在B的前面,那么在C的所有子类里,也必须满足这个顺序。

为了解释C3算法,我们引入了mro(mro即 method resolution order (方法解释顺序),主要用于在多继承时判断属性的路径(来自于哪个类))。

我们可以通过class.mro()来查看python类的mro

C3算法
判断mro要先确定一个线性序列,然后查找路径由由序列中类的顺序决定。所以C3算法就是生成一个线性序列。
如果继承至一个基类:
class B(A)
这时B的mro序列为[B,A]

如果继承至多个基类
class B(A1,A2,A3 ...)
这时B的mro序列 mro(B) = [B] + merge(mro(A1), mro(A2), mro(A3) ..., [A1,A2,A3])


merge操作就是C3算法的核心。
遍历执行merge操作的序列,如果一个序列的第一个元素,是其他序列中的第一个元素,或不在其他序列出现,则从所有执行merge操作序列中删除这个元素,合并到当前的mro中。
merge操作后的序列,继续执行merge操作,直到merge操作的序列为空。
如果merge操作的序列无法为空,则说明不合法。

例子:
class A(O):pass
class B(O):pass
class C(O):pass
class E(A,B):pass
class F(B,C):pass
class G(E,F):pass

A、B、C都继承至一个基类,所以mro序列依次为[A,O]、[B,O]、[C,O]
mro(E) = [E] + merge(mro(A), mro(B), [A,B])
= [E] + merge([A,O], [B,O], [A,B])
执行merge操作的序列为[A,O]、[B,O]、[A,B]
A是序列[A,O]中的第一个元素,在序列[B,O]中不出现,在序列[A,B]中也是第一个元素,所以从执行merge操作的序列([A,O]、[B,O]、[A,B])中删除A,合并到当前mro,[E]中。
mro(E) = [E,A] + merge([O], [B,O], [B])
再执行merge操作,O是序列[O]中的第一个元素,但O在序列[B,O]中出现并且不是其中第一个元素。继续查看[B,O]的第一个元素B,B满足条件,所以从执行merge操作的序列中删除B,合并到[E, A]中。
mro(E) = [E,A,B] + merge([O], [O])
= [E,A,B,O]

Ⅸ 如何理解 Python 的 Descriptor

一般来说,一个描述器是一个有“绑定行为”的对象属性(object attribute),它的访问控制被描述器协议方法重写。这些方法是 __get__(), __set__(), 和 __delete__() 。有这些方法的对象叫做描述器。
默认对属性的访问控制是从对象的字典里面(__dict__)中获取(get), 设置(set)和删除(delete)它。举例来说, a.x 的查找顺序是, a.__dict__['x'] , 然后 type(a).__dict__['x'] , 然后找 type(a) 的父类(不包括元类(metaclass)).如果查找到的值是一个描述器, Python就会调用描述器的方法来重写默认的控制行为。这个重写发生在这个查找环节的哪里取决于定义了哪个描述器方法。注意, 只有在新式类中时描述器才会起作用。(新式类是继承自 type 或者 object 的类)
描述器是强大的,应用广泛的。描述器正是属性, 实例方法, 静态方法, 类方法和 super 的背后的实现机制。描述器在Python自身中广泛使用,以实现Python 2.2中引入的新式类。描述器简化了底层的C代码,并为Python的日常编程提供了一套灵活的新工具。
描述器协议

descr.__get__(self, obj, type=None) --> value
descr.__get__(self, obj, value) --> None
descr.__delete__(self, obj) --> None

一个对象如果是一个描述器,被当做对象属性(很重要)时重写默认的查找行为。
如果一个对象同时定义了__get__和__set__,它叫data descriptor。仅定义了__get__的描述器叫non-data descriptor。
data descriptor和non-data descriptor区别在于: 相对于实例的字典的优先级,如果实例字典有与描述器具同名的属性,如果描述器是data descriptor,优先使用data descriptor。如果是non-data descriptor,优先使用字典中的属性。

class B(object):

def __init__(self):
self.name = 'mink'

def __get__(self, obj, objtype=None):
return self.name

class A(object):
name = B()

a = A()
print a.__dict__ # print {}
print a.name # print mink
a.name = 'kk'
print a.__dict__ # print {'name': 'kk'}
print a.name # print kk

这里B是一个non-data descriptor所以当a.name = 'kk'的时候,a.__dict__里会有name属性, 接下来给它设置__set__

def __set__(self, obj, value):
self.name = value

... do something

a = A()
print a.__dict__ # print {}
print a.name # print mink
a.name = 'kk'
print a.__dict__ # print {}
print a.name # print kk

因为data descriptor访问属性优先级比实例的字典高,所以a.__dict__是空的。
描述器的调用
描述器可以直接这么调用: d.__get__(obj)
然而更常见的情况是描述器在属性访问时被自动调用。举例来说, obj.d 会在 obj 的字典中找 d ,如果 d 定义了 __get__ 方法,那么 d.__get__(obj) 会依据下面的优先规则被调用。
调用的细节取决于 obj 是一个类还是一个实例。另外,描述器只对于新式对象和新式类才起作用。继承于 object 的类叫做新式类。
对于对象来讲,方法 object.__getattribute__() 把 b.x 变成 type(b).__dict__['x'].__get__(b, type(b)) 。具体实现是依据这样的优先顺序:资料描述器优先于实例变量,实例变量优先于非资料描述器,__getattr__()方法(如果对象中包含的话)具有最低的优先级。完整的C语言实现可以在 Objects/object.c 中 PyObject_GenericGetAttr() 查看。
对于类来讲,方法 type.__getattribute__() 把 B.x 变成 B.__dict__['x'].__get__(None, B) 。用Python来描述就是:

def __getattribute__(self, key):
"Emulate type_getattro() in Objects/typeobject.c"
v = object.__getattribute__(self, key)
if hasattr(v, '__get__'):
return v.__get__(None, self)
return v

其中重要的几点:
描述器的调用是因为 __getattribute__()
重写 __getattribute__() 方法会阻止正常的描述器调用
__getattribute__() 只对新式类的实例可用
object.__getattribute__() 和 type.__getattribute__() 对 __get__() 的调用不一样
资料描述器总是比实例字典优先。
非资料描述器可能被实例字典重写。(非资料描述器不如实例字典优先)
super() 返回的对象同样有一个定制的 __getattribute__() 方法用来调用描述器。调用 super(B, obj).m() 时会先在 obj.__class__.__mro__ 中查找与B紧邻的基类A,然后返回 A.__dict__['m'].__get__(obj, A) 。如果不是描述器,原样返回 m 。如果实例字典中找不到 m ,会回溯继续调用 object.__getattribute__() 查找。(译者注:即在 __mro__ 中的下一个基类中查找)
注意:在Python 2.2中,如果 m 是一个描述器, super(B, obj).m() 只会调用方法 __get__() 。在Python 2.3中,非资料描述器(除非是个旧式类)也会被调用。 super_getattro() 的实现细节在: Objects/typeobject.c ,[del] 一个等价的Python实现在 Guido's Tutorial [/del] (译者注:原文此句已删除,保留供大家参考)。
以上展示了描述器的机理是在 object, type, 和 super 的 __getattribute__() 方法中实现的。由 object 派生出的类自动的继承这个机理,或者它们有个有类似机理的元类。同样,可以重写类的 __getattribute__() 方法来关闭这个类的描述器行为。
描述器例子
下面的代码中定义了一个资料描述器,每次 get 和 set 都会打印一条消息。重写 __getattribute__() 是另一个可以使所有属性拥有这个行为的方法。但是,描述器在监视特定属性的时候是很有用的。

class RevealAccess(object):
"""A data descriptor that sets and returns values
normally and prints a message logging their access.
"""

def __init__(self, initval=None, name='var'):
self.val = initval
self.name = name

def __get__(self, obj, objtype):
print 'Retrieving', self.name
return self.val

def __set__(self, obj, val):
print 'Updating' , self.name
self.val = val

>>> class MyClass(object):
x = RevealAccess(10, 'var "x"')
y = 5

>>> m = MyClass()
>>> m.x
Retrieving var "x"
10
>>> m.x = 20
Updating var "x"
>>> m.x
Retrieving var "x"
20
>>> m.y
5

这个协议非常简单,并且提供了令人激动的可能。一些用途实在是太普遍以致于它们被打包成独立的函数。像属性(property), 方法(bound和unbound method), 静态方法和类方法都是基于描述器协议的。