Python - 继承旧式类

33

我正在尝试通过telnet连接实验室仪器。我想扩展标准库中的telnetlib模块中的Telnet类,以包括特定于我们仪器的功能:

import telnetlib
class Instrument(telnetlib.Telnet):
    def __init__(self, host=None, port=0, timeout=5):
        super(Instrument,self).__init__(host, port, timeout)

我在这段代码中所做的就是从父类(telnetlib.Telnet)继承__init__方法并传递标准参数,以便稍后添加内容到__init__中。这个公式在其他场合已经对我起过作用;但这一次,在我尝试实例化时,在super()语句处出现了错误:

TypeError: must be type, not classobj
我查看了 telnetlib 的源代码,Telnet 看起来是一种旧式类(它没有继承自 object) - 我想知道这是否可能是我的问题的来源?如果是,如何解决?我看过一些代码示例,其中派生类同时继承自超类和 object,但我不确定这是否是响应与我的问题相同的方式。

完全揭露:我还尝试过使用telnetlib.Telnet代替super(),以及使用Telnet代替super()from telnetlib import Telnet。在这些情况下,问题仍然存在。

谢谢!

2个回答

45

你需要像这样调用构造函数

telnetlib.Telnet.__init__(self, host, port, timeout)

由于telnet.Telnet.__init__是一个未绑定的方法(即没有实例分配),而不是一个绑定的方法,因此您需要添加显式的self。因此,在调用它时,您需要显式地传递实例。

>>> Test.__init__
<unbound method Test.__init__>
>>> Test().__init__
<bound method Test.__init__ of <__main__.Test instance at 0x7fb54c984e18>>
>>> Test.__init__()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unbound method __init__() must be called with Test instance as first argument (got nothing instead)

我已经尝试过了 - 它给了我这个错误:TypeError: 未绑定的方法__init__()必须使用Telnet实例作为第一个参数进行调用(而不是str实例) - Benjamin Hodgson
请展示您刚刚发布的代码和错误信息,因为这实际上是调用旧式类的父构造函数的正确方法。 - ThiefMaster
啊,我发现了你的代码和我的不同之处 - 你在__init__的第一个参数中使用了 self。现在它能够工作了 - 谢谢你的快速回复!你能否向我解释一下为什么需要将 self 作为构造函数的第一个参数?我是 Python 新手。 - Benjamin Hodgson
1
请注意,这将仍然会给您一个旧式类。 - Marcin
在任何方法中(除了类和静态方法),您总是需要传递self。在正常的点调用中,这是半自动处理的:您调用self.foo(a, b),Python将其转换为对foo(self, a, b)的调用。但在这种情况下,您不是在对象上调用__init__,而是在类上调用它,这意味着您必须显式添加self。(这在一些细节上略有不准确,但足以用于学习目的。) - abarnert

16

您必须从 object 继承,并且必须将其放置在您要继承的旧式类之后(以便先不查找 object 的方法):

>>> class Instrument(telnetlib.Telnet,object):
...     def __init__(self, host=None, port=0, timeout=5):
...         super(Instrument,self).__init__(host, port, timeout)
...
>>> Instrument()
<__main__.Instrument object at 0x0000000001FECA90>

继承自object会使你拥有一个新式类,可以使用super


2
在创建一个基于旧式类的新式类时,继承旧式类是否安全? - ThiefMaster
我不熟悉Python中的多重继承。由于新式类对我的目的没有任何优势,我将坚持上面ThiefMaster的策略。无论如何还是谢谢! - Benjamin Hodgson
1
@poorsod 你认为 Python 中的“多重继承”有什么特别之处?新式类的主要优点之一是它们确实正确地处理了多重继承。 - Marcin
我相信你是对的,但有些事情我不太清楚,这让我对这样做感到谨慎(包括你不知道它是否会破坏其他东西!)。例如,这与进入telnetlib源并将“def Telnet:”更改为“def Telnet(Object):”有何不同?我也不清楚调用“super”会返回什么。 - Benjamin Hodgson
1
@poorsod super + 新式类的目的是使其能够可预测地工作。答案是,您将获得通过搜索__mro__找到的第一个 __init__ - Marcin
显示剩余3条评论

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