为什么相同的类会用不同的__init__代码被继承? 交互式经纪人API

3
我正在尝试学习这个API,但有一个细节让我感到困惑。我不习惯使用类和接口,也不理解其中的一个细节。
在这个API中,有两个非常重要的类:EClient和EWrapper。 EClient用于下订单和发送请求。 EWrapper用于处理从API接收到的消息。
在所有的书籍、网站、教程中,它们都创建了一个新类,并继承了这两个类。但我不明白的是,在不同来源中,init函数中使用的代码却不同。这怎么可能呢?
以下是示例说明:
Source 1,在他们Youtube上的视频中,这是他们如何创建一个新类(TestApp),该类继承了EClient和EWrapper类: https://www.youtube.com/watch?v=dzOilFBDmJI&list=PL71vNXrERKUpPreMb3z1WGx6fOTCzMaH1&index=4
from ibapi.client import EClient
from ibapi.wrapper import EWrapper

class TestApp (EClient, EWrapper):
    def __init__ (self): 
        EClient.__init__(self, self)

我有两个关于这个问题的疑问:

1 为什么他们要使用两次self? (self, self)

2 为什么他们不使用EWrapper init函数?

类似这样:

EWrapper.__init__(self, self)

这是一本名为《使用Python和C++进行交易算法交易的交互经纪人》的书籍中的内容。

下面介绍如何创建新类:


class SubmitOrder (EClient, EWrapper):
    def __init__ (self, addr, port, clientId):
        EWrapper.__init__(self)
        EClient.__init__(self, self)

我有2个问题:

3 为什么这里称EWrapper init函数?

4 为什么EClient有两个self(self,self),而EWrapper只有一个self(self)。

来源3,他们自己的文档:

https://interactivebrokers.github.io/tws-api/client_wrapper.html

首先,他们说您必须使用此代码实现EWrapper接口:


class TestWrapper(wrapper.EWrapper):

但是在冒号后面什么都没有,所以这里是我的问题。

5 我应该使用什么代码来实现EWrapper接口?他们谈论接口而不是类。我已经阅读过接口类似于类,但是定义的方法是抽象的,你应该重写这些方法。我明白你不需要在EClient中覆盖方法,但是你必须在EWrappper中这样做。但我不知道如何“实现EWrapper接口”。不幸的是,在每个程序中都应该有的某些步骤的非常第一步,他们的代码看起来不完整。

之后,他们解释说您必须创建一个EClient类,并在此处使用EWrapper,以便您可以接收消息:


class TestClient(EClient):
    def __init__(self, wrapper):
        EClient.__init__(self, wrapper)

以下是我的问题:

6 为什么他们使用wrapper而不是EWrapper?据我所知,wrapper是存储EWrapper类的文件。

最后,他们使用TestWrapper和TestClient创建新类。这是他们的代码:


class TestApp(TestWrapper, TestClient):
    def __init__(self):
        TestWrapper.__init__(self)
        TestClient.__init__(self, wrapper=self)

以下是我的问题:
7. 为什么一些初始化函数有一个self,而另一些则有两个?
我在这里看到TestClient中的第二个“self”等于wrapper。这是有道理的,因为根据他们的解释:
“要使用EClientSocket,首先可能需要在其构造函数参数中实现IBApi.EWrapper接口,以便应用程序可以处理所有返回的消息。从TWS发送的作为对IBApi.EClientSocket函数调用的响应的消息需要EWrapper实现,以便它们可以被处理以满足API客户端的需求。”
这表明第二个self等于wrapper,并让我想起了源代码1中的代码:

EClient.__init__(self, self)

第二个self不等于wrapper,所以这是我的最后一个问题:

8 如何在没有明确将self等于wrapper的情况下使此代码工作?

正如您所看到的,我对此非常困惑,希望有人能解释一下。

感谢您的时间。


我知道我写了一篇很长的帖子,但我真的需要理解这个。请问,有人可以帮忙吗? - pedro rodriguez
2个回答

3
请注意,我除了在这里展示IB示例之外,不使用Python... 我可能是错的。
注意,class TestApp (EClient, EWrapper) 意味着TestApp从Eclient和EWrapper继承。或者说,发送消息到TWS的客户端和接收消息的包装器都是TestApp类。
EClient.__init__(self, self) 1为什么他们两次使用self?(self, self)
类中的第一个参数始终是self来表示它自己,就像Python工作的方式一样。第二个参数是因为Python期望EClient init方法的一个参数。此参数是数据回调的包装器。
2为什么他们不使用EWrapper init函数?
它什么也没有做。如果你看源代码,它只是一堆用于被覆盖的方法。它有一个默认的实现,只是记录日志。更多我所说的接口。
3为什么这里要调用EWrapper init函数?
也许只是编程风格,它什么也没做。

4 为什么 EClient 有两个 self(self, self),而 EWrapper 只有一个 self(self)。

EWrapper 不需要参数,所以它只是传递了在所有 Python 类中使用的 self。

5 我应该使用什么代码来实现 EWrapper 接口?

有两个类,EClient 用于调用 TWS\IBG,然后 TWS 通常会调用 IB 的服务器,回复将以某种方式返回给您。TWS 唯一知道要发送回复的位置的方法是通过在 init 方法中指定 wrapper。

因此,如果您想查看数据,则重写包装器中的这些数据回调(在这些示例中称为 TestApp 或 SubmitOrder)。这很简单,只需查看稍后我将展示的一些示例,但基本上只需将 EWrapper 类中的方法复制并更改为所需内容即可。

6 为什么他们使用 wrapper 而不是 EWrapper?

class TestWrapper(wrapper.EWrapper):

在上述代码中,他们会使用 from ibapi import wrapper,因此并没有导入 EWrapper,只是一种不同的导入方式。
class TestClient(EClient):
    def __init__(self, wrapper):
        EClient.__init__(self, wrapper)

在上面的注释中,wrapper是传递给init并重新发送到EClient init的参数名称,他们可以随便取名字,但我认为重复使用名称是不好的做法。
7. 在1中已回答。
TestClient.__init__(self, wrapper=self)

注意上面的意思是他们已经创建了一个名为TestClient的EClient子类,并在TestApp中使用命名参数wrapper=self进行初始化。您可以按名称或位置发送参数,因此它更多地用于提醒您该参数的用途。
第二个self不等于wrapper,所以这是我的最后一个问题: 8.如果没有将self显式等于wrapper,这段代码如何工作?
请记住,在第一段代码中,TestApp是EClient和EWrapper的子类,因此self确实是wrapper。它也是客户端。
下面是一个示例,它不使用多重继承并显示了一些重写的方法。 https://stackoverflow.com/a/54423878/2855515

0
这并不是完整的答案,但这里是 Eclient 类的 __init__
class EClient(object):
    (DISCONNECTED, CONNECTING, CONNECTED, REDIRECT) = range(4)

    #TODO: support redirect !!

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

那么回答你关于两个self的问题:第一个是Python工作方式的体现(表明这是非静态方法),第二个是为了wrapper,但由于我们从两个类(其中一个是Ewrapper)继承,所以我们使用self(用于wrapper)。我们实例化的对象本身就是一个wrapper


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接