问题标签 [method-resolution-order]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
1 回答
606 浏览

python - 在一般情况下,Python 的 super() 是如何工作的?

上有很多很棒的资源super(),包括弹出很多很棒的博客文章,以及有关 Stack Overflow 的许多问题。但是我觉得他们都没有解释它在最一般的情况下是如何工作的(使用任意继承图),以及引擎盖下发生了什么。

考虑这个菱形继承的基本示例:

如果您从此类来源阅读 Python 的方法解析顺序规则或查找 C3 线性化的维基百科页面,您将看到 MRO 必须是(D, B, C, A, object). 这当然得到证实D.__mro__

印刷

与 MRO 匹配。但是,请考虑上面super(B, self).foo()inB实际调用C.foo,而 inb = B(); b.foo()它会直接转到A.foo。显然,使用super(B, self).foo()不仅仅是A.foo(self)有时被教导的捷径。

super()然后显然知道之前的呼叫以及该链试图遵循的整体 MRO。我可以看到这可能实现的两种方式。第一种是做一些事情,比如将super对象本身作为self参数传递给链中的下一个方法,它的行为类似于原始对象,但也包含此信息。然而,这似乎也会破坏很多东西(super(D, d) is d是错误的)并且通过做一些实验我可以看到情况并非如此。

另一种选择是使用某种全局上下文来存储 MRO 和其中的当前位置。我想算法super类似于:

  1. 目前有我们正在工作的环境吗?如果没有,请创建一个包含队列的队列。获取类参数的 MRO,将除第一个元素之外的所有元素推入队列。
  2. super从当前上下文的 MRO 队列中弹出下一个元素,在构造实例时将其用作当前类。
  3. 当从super实例访问方法时,在当前类中查找它并使用相同的上下文调用它。

但是,这并不能解释奇怪的事情,比如使用不同的基类作为调用的第一个参数super,甚至调用不同的方法。我想知道这个的一般算法。另外,如果这个上下文存在于某个地方,我可以检查它吗?我可以玩弄它吗?当然,这个想法很糟糕,但 Python 通常希望你成为一个成熟的成年人,即使你不是。

这也引入了很多设计考虑。如果我写B时只考虑它与 的关系A,然后其他人写C,第三人写D,我的方法必须以兼容的方式B.foo()调用,即使它在我写它的时候不存在!如果我希望我的类易于扩展,我需要考虑这一点,但我不确定它是否比简单地确保所有版本具有相同的签名更复杂。还有一个问题是何时在调用 之前或之后放置代码,即使仅考虑 的基类并没有任何区别。superC.foo()foosuperB

0 投票
1 回答
1063 浏览

python - 为什么元类上的 .mro() 有不同的签名?'type'对象的'descriptor'mro'需要一个参数`

在 Python 中的大多数类型/类上,我可以.mro()不带参数地调用。但不是 ontype及其后代:

看来我可以得到我想要的东西type(type(4)).mro(type(4)),但为什么我不能mro()像在其他地方一样直接打电话呢?

0 投票
0 回答
40 浏览

python - Python中抽象基类创建方法的区别

这些是创建抽象基类并将其注册到具体类的不同方法:

进口:

方法一:

方法二:

方法三:

方法四:

方法五:

问题:

  1. 除了MRO,它们之间有什么区别?
  2. 他们有不同的用例吗?
  3. 在他们之间是否有一种首选或更 Pythonic 的方式来做到这一点?

PS:请注意,只有 #2 也适用于 Python 2

0 投票
1 回答
292 浏览

openerp - Odoo 8 方法解析顺序

我在理解 odoo 中的继承时遇到了问题。考虑模块 1 中的以下代码

与模块 2 相同,仅打印 2。首先安装模块 1,然后安装模块 2。正如您在两者中看到的那样,pos_order 使用自定义 create_from_ui 函数进行了扩展。如果现在调用 create_from_ui,则调用 module2 order,然后调用 module1 order,然后调用 original。我现在怎么能只调用原件(可以说我不想在某些情况下打印“1”)?

干杯,非常感谢所有的帮助

0 投票
1 回答
487 浏览

python - 对新样式类使用多重继承时如何确定执行顺序?

我正在阅读 Effective Python 书,我找到了以下代码

我期望 foo 的值是27( 5 * 5 + 2)。但事实证明是35。输出如下

我可以理解MRO,但我没有得到执行命令……不应该TimesFiveCorrect先调用吗?

0 投票
1 回答
647 浏览

python - 方法解析顺序和元类

为什么元类没有出现在 MRO 中?

例如:

另外,我在其他地方看到 Python 使用 C3 线性化来计算 MRO,但这种线性化不处理元类。那么在这种情况下,Python 使用什么算法呢?

0 投票
1 回答
174 浏览

python - 用 Super 构建正确的 Python 门面类?

我以为我用 Super() 处理了多重继承,并试图在 Facade 类中使用它,但我遇到了一个奇怪的错误。我正在使用一个名为 Fireworks 的制作精良的 Python 工作流软件,但是类和工作流任务的结构非常严格,所以我创建了一个外观类以方便使用。

以下是工作流任务的基本结构:

我用super以下方式构建了我的 Facade 类:

这很好用,除了一个让我困惑的小警告。创建 的新实例时BgwInput,它不会创建空实例。以前实例中设置的输入集参数以某种方式被传递到新实例,但不是kpointsor qshift。例如:

但是,如果我将self.__dict__['isp'] = ispFacade 类更改为self.__dict__['isp'] = isp if isp else {}一切似乎都按预期工作。在先前实例中设置的参数不会转移到新实例中。那么,为什么 Facade 类不默认为 isp={} (假设这是 __ init __ 中的默认值),因为如果在创建时没有给出输入集参数,它应该是什么?由于默认应该是空白字典,它从哪里提取先前的参数?

为了清楚起见,我有一个解决方案可以使 Facade 类按预期发挥作用(通过将ispFacade 更改为self.__dict__['isp'] = isp if isp else {}),但我试图弄清楚为什么需要这样做。我相信我缺少一些基本的东西super或 Python 中的方法解析顺序。我很好奇为什么会发生这种情况并试图扩大我的知识库。

下面是门面类的方法解析顺序。

0 投票
1 回答
78 浏览

python - Python 类继承

我在理解 python 的 mro(方法解析顺序)时遇到了一些麻烦。Python 从左到右运行。因此,根据我的理解,调用 M 的顺序应该是。M、B、A、Z、X、Y

但正确的调用顺序是。

任何人都可以解释订购并帮助我理解这一点。谢谢

0 投票
1 回答
127 浏览

python - python - 如何在python多重继承中将方法解析限制为只有一个父级?

可以说我有,

我怎样才能做到这一点?准确地说,我想创建一个派生自两个类的类,但根据输入参数,我想禁用其中一个类并仅使用另一个类的属性。所以我得到这个,

0 投票
2 回答
139 浏览

c# - 具有泛型和类型推断的 C# 方法解析

今天我对方法解析的工作方式感到惊讶。

下面以代码为例:

如您所见,方法 Map 有两种重载,一种是属性类型相同时,另一种是源属性是可枚举且正确的属性是数组时。

然后,当我在两侧调用带有数组的方法时,它调用第二个重载,但由于类型完全相同,我希望调用第一个重载。

我认为第一个重载会有更好的得分,因为它依赖的泛型参数比第二个少,而且它更适合我传递给方法的参数类型。

有人可以解释为什么编译器选择调用第二个重载而不是第一个重载吗?

谢谢。