Python - 从旧式类继承

Posted

技术标签:

【中文标题】Python - 从旧式类继承【英文标题】:Python - inheriting from old-style classes 【发布时间】:2012-07-16 16:40:05 【问题描述】:

我正在尝试通过 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(),并使用from telnetlib import TelnetTelnet 代替super()。在这些情况下问题仍然存在。

谢谢!

【问题讨论】:

【参考方案1】:

您需要像这样调用constructor:

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

您需要添加显式self,因为telnet.Telnet.__init__ 不是绑定方法,而是未绑定方法,即没有分配实例。因此,调用它时,您需要显式传递实例。

>>> 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: unbound method __init__() must be called with Telnet instance as first argument (got str instance instead) 请显示您使用我刚刚发布的代码时遇到的确切代码和错误。因为如果你想调用旧式类的父构造函数,实际上就是这样做的。 啊,我发现了您的代码和我的代码之间的区别 - 您将 self 作为 __init__ 的第一个参数。现在可以使用 - 感谢您这么快回复!您能否向我解释为什么需要将self 作为构造函数的第一个参数?我是 Python 新手。 请注意,这仍然会为您提供旧式课程。 您总是需要将 self 传递给任何方法(类和静态方法除外)。这在正常的点调用中是半自动的:你调用self.foo(a, b),Python 把它变成对foo(self, a, b) 的调用。但在这种情况下,您不是在对象上调用__init__,而是在类上调用它,这意味着您必须显式添加self。 (这在一些细节上有点不准确,但对于学习目的来说已经足够接近了。)【参考方案2】:

你必须从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>

从对象继承为您提供了一个与super 一起使用的新型类。

【讨论】:

从旧式类继承以创建新式类的方式是否安全? @ThiefMaster 我不知道有什么问题,但我从来没有生气过,所以我真的没有任何信息。您预计会有什么问题吗? 我不熟悉 Python 中的多继承。由于新式课程对我的目的没有任何好处,因此我将坚持上述 TheifMaster 的策略。不过还是谢谢! @poorsod 你认为python中的“多继承”有什么特别之处?新型类的主要优点之一是它们实际上可以正确处理多重继承。 @poorsod super + new-style classes 的重点是使这项工作可预测。答案是你会得到通过搜索__mro__找到的第一个__init__

以上是关于Python - 从旧式类继承的主要内容,如果未能解决你的问题,请参考以下文章

python新式类与旧式类

Python面向对象 --- 新旧式类私有方法类属性和类方法静态方法

Python新式类

面向对象之多继承

Python基础(二十三):面向对象之继承介绍

旧式类、新式类和元类