Python如何获取实例的基本实例?
在C#中,我会这样做:
myObj.base
我有一个日期类,它是从date.datetime这个类继承来的。这个日期类重写了__gt__()
和__lt__()
这两个方法,所以当我使用<
和>
这些符号时,它们会被调用。但是我不想使用这些重写的方法,我想在Date类的实例上使用date.datetime的方法。
2 个回答
如果我理解你的问题没错,这在Python中是没有意义的。子类的实例里没有“基础实例”。
在Python中,一个实例就是一个东西,它包含了一些属性(这些属性可能是由它的父类设置或修改的,甚至可能是外部代码设置的)。实际上,你可以在运行时改变一个实例的类,甚至把它移到完全不同的继承结构中(虽然这通常不是个好主意,但这是可以做到的)。无论如何,这个实例始终是一个整体对象,它只知道自己有哪些属性,以及它属于哪个类(实际上这也是一个属性:__class__
)。
编辑:如果你想在一个实例上调用被重写的方法,你可以使用super
,就像hocl所说的那样。不过从你的评论来看,你似乎并没有完全理解super
的作用(这很正常,因为它确实比较复杂)。
super(Date, myObj)
并不会返回“底层的datetime.date
”实例,因为根本没有这样的东西,只有myObj
对象。虽然从你的需求来看,这似乎可以满足你的要求(你可能可以停在这句话)。
它的作用是返回一个神奇的包装器,围绕着myObj
,从Date
的“后面”开始查找方法;也就是说,它会找到如果Date
没有重写的方法会被调用的方法。所以在这种情况下,它会找到所有来自datetime.date
的方法,因为你只有单一继承。
一个关键的区别是,这支持多重继承。如果有人创建了一个类,它从Date
继承,同时又通过另一条路径从datetime.date
继承,那么super(Date, instanceOfThatClass)
可能实际上不会调用datetime.date
的方法。这取决于继承结构的细节。不过这正是super
设计的初衷;它使得在复杂的多重继承结构中,类能够协同调用彼此的实现,确保每个方法只被调用一次,并且以合理的顺序调用(尽管对于每个最终的叶子类,这个顺序可能不同,因此中间的类实际上不知道它们正在调用哪个超类的实现)。我理解的是,这种复杂情况在C#中不会出现,因此它可以提供简单的.base
语法。
我还理解到(这有点猜测),因为C#是静态类型的,并且支持从预编译库中定义的类继承,所以当你有类Sub
继承自类Base
时,在Sub
的实例内部,确实存在一个完整的Base
实例,你可以访问并调用它的方法。这会影响被遮蔽的字段;我预计(再次强调,我不是C#程序员,只是在猜测)在从Sub
实例获取Base
实例后,任何直接引用被Sub
重写的字段都会访问到Base
中的字段,而不是Sub
中的字段。
而在Python中,另一方面,没有基础实例,类也不能重写字段。如果Date
和datetime.date
的构造函数和方法都引用同一个字段,那就是它们共享的同一个字段。因此,使用super
不会改变你访问的字段,正如你可能认为的那样,认为它是在获取基础实例。
鉴于你没有使用复杂的多重继承情况,如果你想要简单的语法,你实际上可以直接调用Date.__lt__(myObj, otherObj)
,虽然这样看起来不太美观,因为你不能使用中缀操作符语法。不过如果考虑普通方法,这样做可能比使用super
更简单。
总结一下:我很确定在这种情况下super(Date, myObj)
是你想要的。但如果你进入更复杂的情况,你就不应该把super
看作是获取“基础实例”的方式,就像在C#中那样。这样的理解会在多重继承时让你困惑(这本来就很复杂),而且在继承层次中使用相同字段时也会出现问题。
使用 super()
可以获取父类的对象。在Python命令行中输入 help(super)
可以查看相关帮助。
根据手册的说明:
class super(object)
| super(type) -> unbound super object
| super(type, obj) -> bound super object; requires isinstance(obj, type)
| super(type, type2) -> bound super object; requires issubclass(type2, type)
| Typical use to call a cooperative superclass method:
| class C(B):
| def meth(self, arg):
| super(C, self).meth(arg)
假设类B是类A的子类,并且类A有一个方法 def f(self):
:
- 在Python 2中,你可以通过在类B中使用
super(B, self).f()
来调用类A的方法。 - 在Python 3中,你可以直接使用
super().f()
,不需要写B, self
这些参数。