假设你有类似的东西
class C2: pass
class C1(object): pass
class B2: pass
class B1(C1, C2): pass
class A(B1,B2): pass
Run Code Online (Sandbox Code Playgroud)
当您具有混合层次结构时,python如何相对于继承和方法解析顺序?它是否遵循旧的遍历,新的遍历,两者的混合取决于层次结构的哪个分支行走?
class MyClass(object):
pass
print MyClass.__mro__
print dir(MyClass)
Run Code Online (Sandbox Code Playgroud)
输出:
(<class '__main__.MyClass'>, <type 'object'>)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
Run Code Online (Sandbox Code Playgroud)
为什么__mro__没有列出dir()?
超级方法如何在python中实际运行?
在给定的代码中:
class A(object):
def test(self):
return 'A'
class B(A):
def test(self):
return 'B->'+super(B, self).test()
class C(A):
def test(self):
return 'C'
class D(B,C):
pass
print B().test() # B->A
print D().test() # B->C ????
# MRO of classes are as
print 'mro of A', A.__mro__ # [A,object]
print 'mro of B', B.__mro__ # [B,A,object]
print 'mro of C', C.__mro__ # [C,A,object]
print 'mro of D', D.__mro__ # [D,B,C,A,object]
Run Code Online (Sandbox Code Playgroud)
当test在D上调用时,它输出B->C而不是B->A(我期待的).
B中的超级内容如何引用C的实例?
python oop inheritance multiple-inheritance method-resolution-order
functools.singledispatch有助于定义单调度泛型方法.同时,还有super()调用方法或访问超类的属性.
是否有类似的东西super()可以使用singledispatch?我尝试了以下,但结果super(Derived, value)只是不是实例Base,所以它不能按我的预期工作:
from functools import singledispatch
@singledispatch
def hello(value):
return ['default']
@hello.register(Base)
def hello_base(value):
return hello(super(Base, value)) + ['base']
@hello.register(Derived)
def hello_derived(value):
return hello(super(Derived, value)) + ['derived']
print(hello(Derived())
# expected ['default', 'base', 'derived'],
# but actually is ['default', 'derived'].
Run Code Online (Sandbox Code Playgroud) 我有Python MRO的问题对于这段代码:
class F: pass
class G: pass
class H: pass
class E(G,H): pass
class D(E,F): pass
class C(E,G): pass
class B(C,H): pass
class A(D,B,E): pass
print(A.__mro__)
Run Code Online (Sandbox Code Playgroud)
我得到这个输出:
(<class '__main__.A'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.E'>, <class '__main__.G'>, <class '__main__.H'>, <class '__main__.F'>, <class 'object'>)
我为什么要来<class '__main__.C'>之前<class '__main__.E'>?
我以为会是:
AD,B,EE,F| C,H| G,H等等
python class multiple-inheritance method-resolution-order python-3.x
我知道标题可能有点混乱,所以让我举个例子。假设您有一个基类Base,它旨在被子类化以创建更复杂的对象。但是您还有一些可选功能,您不需要每个子类都需要这些功能,因此您将它放在一个二级类中OptionalStuffA,该二级类始终打算与基类一起进行子类化。你也应该让那个次要类成为 的子类Base吗?
这当然是唯一相关,如果你有一个以上的OptionalStuff班,你想给他们以不同的方式结合起来,否则你不需要子类均Base和OptionalStuffA(,只是有OptionalStuffA成为的一个子类Base,所以你只需要在子类OptionalStuffA)。我Base知道如果从Base.
下面是一个示例场景。我还将QObject该类作为“第三方”令牌类放入该类,其功能对于其中一个辅助类工作是必需的。我在哪里子类化它?下面的例子显示了我到目前为止是如何做到的,但我怀疑这是要走的路。
from PyQt5.QtCore import QObject
class Base:
def __init__(self):
self._basic_stuff = None
def reset(self):
self._basic_stuff = None
class OptionalStuffA:
def __init__(self):
super().__init__()
self._optional_stuff_a = None
def reset(self):
if hasattr(super(), 'reset'):
super().reset()
self._optional_stuff_a = None
def do_stuff_that_only_works_if_my_children_also_inherited_from_Base(self):
self._basic_stuff = not None
class OptionalStuffB:
def __init__(self):
super().__init__()
self._optional_stuff_b = None
def reset(self):
if hasattr(super(), 'reset'): …Run Code Online (Sandbox Code Playgroud) python3中有一个简单的程序:
from PyQt4 import QtCore
import PyQt4
class Bar(object):
def __init__(self):
print("Bar start")
super(Bar, self).__init__()
print("Bar end")
class FakeQObject(object):
def __init__(self):
print("FakeQObject start")
super(FakeQObject, self).__init__()
print("FakeQObject end")
class Foo(QtCore.QObject, Bar):
#class Foo(FakeQObject, Bar):
def __init__(self):
print("Foo start")
super(Foo, self).__init__()
print("Foo end")
print(Foo.__mro__)
print(PyQt4.QtCore.PYQT_VERSION_STR)
f = Foo()
Run Code Online (Sandbox Code Playgroud)
a)当类Foo继承自QtCore.QObject和Bar时,我们得到:
(<class '__main__.Foo'>, <class 'PyQt4.QtCore.QObject'>, <class 'sip.wrapper'>, <class 'sip.simplewrapper'>, <class '__main__.Bar'>, <class 'object'>)
4.9.4
Foo start
Foo end
Run Code Online (Sandbox Code Playgroud)
b)当类Foo继承自FakeQObject和Bar时,我们得到:
(<class '__main__.Foo'>, <class '__main__.FakeQObject'>, <class '__main__.Bar'>, <class 'object'>)
4.9.4
Foo start
FakeQObject start
Bar start …Run Code Online (Sandbox Code Playgroud) 我发现自己处于一种不寻常的情况,我需要在运行时更改类的MRO.
代码:
class A(object):
def __init__(self):
print self.__class__
print "__init__ A"
self.hello()
def hello(self):
print "A hello"
class B(A):
def __init__(self):
super(B, self).__init__()
print "__init__ B"
self.msg_str = "B"
self.hello()
def hello(self):
print "%s hello" % self.msg_str
a = A()
b = B()
Run Code Online (Sandbox Code Playgroud)
正如预期的那样,这失败了,因为__init__A 的方法(当从B调用时)调用B hello,它试图在属性存在之前访问它.
问题在于我可以做出的改变受到限制:
__init__我确实通过在运行时更改MRO来解决这个问题.简而言之,在B期间__init__,但在调用super之前__init__,MRO将被更改,以便首先搜索A的方法,从而调用A hello而不是B(因此失败).
问题是MRO是只读的(在类运行时).
还有其他方法可以实现吗?或者可能完全不同的解决方案(仍然尊重上述约束)?
我是 MRO 的新手,在弄清楚这些输出的逻辑时遇到了问题。
class A(object):
def save(self):
print "A"
class B(A):
def save(self):
print "B"
super(B, self).save()
class C(A):
def save(self):
print "C"
super(C, self).save()
class D(C, B):
def save(self):
print "D"
super(D,self).save()
D().save()
Run Code Online (Sandbox Code Playgroud)
输出:
class A(object):
def save(self):
print "A"
class B(A):
def save(self):
print "B"
super(B, self).save()
class C(A):
def save(self):
print "C"
super(C, self).save()
class D(C, B):
def save(self):
print "D"
super(D,self).save()
D().save()
Run Code Online (Sandbox Code Playgroud)
我的问题是如何super(C)调用B.save().
根据 MRO:super(C, self)不是关于“的基类C”,而是关于 MRO …
两个 mixin 类将需求指定为抽象方法。这些类共同拥有一整套具体方法。然而,它们无法组合成一个具体的类:无论我使用哪种顺序来声明具体的类,一些抽象方法都会覆盖具体的方法。
有没有办法防止抽象方法覆盖具体方法?我相信这在 Scala 中是有效的。
指定要求的替代方法有哪些?
这是一个具体的例子:
import abc
class A(abc.ABC):
@abc.abstractmethod
def x(self):
pass
def y(self):
return "A.y"
class B(abc.ABC):
@abc.abstractmethod
def y(self):
pass
def x(self):
return f"B.x"
class AB(B, A):
pass
class BA(A, B):
pass
ab = AB() # TypeError: Can't instantiate abstract class AB with abstract methods y
ba = BA() # TypeError: Can't instantiate abstract class BA with abstract methods x
Run Code Online (Sandbox Code Playgroud) python ×9
python-3.x ×3
class ×2
functools ×1
inheritance ×1
mixins ×1
oop ×1
pyqt4 ×1
super ×1