You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python多继承与包装类相关技术疑问咨询

Python继承与包装类入门疑问解答

第一种继承模式与疑问

先看你给出的第一种模式代码:

from api.client import Client
from api.wrapper import Wrapper

class TestClient(Client):
    def __init__(self, wrapper):
        Client.__init__(self, wrapper)
 
class TestWrapper(Wrapper):
    def __init__(self):
        Wrapper.__init__(self)

    def updateMktDepth(self, reqId: TickerId, position: int, operation: int,
                side: int, price: float, size: int):
            super().updateMktDepth(reqId, position, operation, side, price, size)
            print("UpdateMarketDepth", "ReqId:", reqId, "Position:", position, "Operation:",
                  operation, "Side:", side, "Price:", price, "Size:", size)
 
    def updateMktDepthL2(self, reqId: TickerId, position: int, marketMaker: str,
            operation: int, side: int, price: float, size: int, isSmartDepth: bool):
        super().updateMktDepthL2(reqId, position, marketMaker, operation, side,
            price, size, isSmartDepth)
        print("UpdateMarketDepthL2", "ReqId:", reqId, "Position:", position, "MarketMaker:", marketMaker, "Operation:",
            operation, "Side:", side, "Price:", price, "Size:", size, "isSmartDepth:", isSmartDepth)
 
def main():
    wrapper = TestWrapper()
    client = TestClient(wrapper)
    client.connect('127.0.0.1', 3847, 100)
    print('Connection successful')
    client.disconnect()

疑问解答:实例化TestClient传wrapper参数是否和*args/**kwargs相关?

完全无关,你可能看错了代码——TestClient的__init__方法是显式声明了wrapper参数的:def __init__(self, wrapper):。其中self是Python类方法的默认第一个参数(代表当前实例),第二个参数就是wrapper,所以实例化TestClient(wrapper)是完全匹配参数定义的正常传参操作。


第二种多继承模式与疑问

再看第二种模式的代码(包含Client类定义):

from api.client import Client
from api.wrapper import Wrapper
    
class TestApp(Client, Wrapper):
    def __init__(self):
        Client.__init__(self, self)

    def updateMktDepth(self, reqId: TickerId, position: int, operation: int, side: int, price: float, size: int):
        super.updateMktDepth(reqId, position, operation, side, price, size)
        print("UpdateMarketDepth", "ReqId:", reqId, "Position:", position, "Operation:", operation, "Side:", side, "Price:", price, "Size:", size)

    def updateMktDepthL2(self, reqId: TickerId, position: int, marketMaker: str, operation: int, side: int, price: float, size: int, isSmartDepth: bool):
        super.updateMktDepthL2(reqId, position, operation, side, price, size)
        print("UpdateMarketDepthL2", "ReqId:", reqId, "Position:", position, "MarketMaker:", marketMaker, "Operation:", 
              operation, "Side:", side, "Price:", price, "Size:", size, "isSmartDepth:", isSmartDepth)

class Client(object):
    (DISCONNECTED, CONNECTING, CONNECTED, REDIRECT) = range(4)

    def __init__(self, wrapper):
        self.msg_queue = queue.Queue()
        self.wrapper = wrapper
        self.decoder = None
        self.reset()

疑问1:多继承下super如何确定方法位置?

Python多继承靠**方法解析顺序(MRO)**来决定查找方法的顺序,你可以通过TestApp.__mro__或者TestApp.mro()打印出具体的顺序列表。当调用super().xxx()时,会严格按照MRO列表的顺序,从当前类的下一个类开始依次查找,找到第一个包含目标方法的类就调用它。

比如TestApp继承了Client和Wrapper,假设MRO是[TestApp, Client, Wrapper, object],如果updateMktDepth只在Wrapper中存在,那super就会跳过Client,直接找到Wrapper的该方法执行。

疑问2:Client.__init__(self, self)两次传self的原理?

首先,Client.__init__的第一个self是Python构造方法的常规要求——调用父类构造时必须传入当前子类的实例(也就是TestApp的实例),这是为了让父类的初始化逻辑作用在子类实例上。

而第二个self,是因为Client的构造需要一个wrapper对象(用来处理回调,比如updateMktDepth这类方法)。由于TestApp同时继承了Wrapper,它的实例本身就具备Wrapper的所有能力(包括你重写的那些回调方法),所以直接把当前实例传给Client的wrapper参数,就能让Client在触发回调时,直接调用TestApp自身实现的那些方法,不用再单独创建一个Wrapper实例,相当于把Client和Wrapper的功能合并到了同一个实例里。


内容的提问来源于stack exchange,提问作者Chris

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 08:17:54