Python 中关于派生类用法语法的继承



我有以下代码:

class person:
def __init__(self,fname,lname):
self.fname=fname
self.lname=lname

def printper(self):
return self.fname,self.lname
class emp:
def __init__(self,fname,lname,empno):
self.empno=empno
person.__init__(self,fname,lname)

def printper(self):
return self.empno,self.fname,self.lname
e1=emp("john","michael",20)
print(e1.printper())
# output: (20, 'john', 'michael')

我很困惑 -emp不会从person继承,但代码仍然有效。为什么?在emp.__init__()中调用person.__init__()似乎可以使代码正常工作。这就是所有必要的吗?实际上不是必须编写class emp(person):才能拥有派生类吗?

Python 并不关心提前检查类型、继承关系等。它只关心代码运行时会发生什么。这允许所谓的"鸭子类型":

class Employee:
def fired(self):
print("Oh no, I have to look for a new job")
class Gun:
def fired(self):
print("Bang! Did the bullet hit the target?")
for thing in [Employee(), Gun()]:
thing.fired()

EmployeeGun彼此无关并不重要,fired的目的完全不同也没关系。列表中的两个对象都有一个名为fired的方法,因此代码可以正常工作

同样,在您的代码中:

class emp:
def __init__(self,fname,lname,empno):
self.empno=empno
person.__init__(self,fname,lname)

如果我们调用person.__init__,那么这只是我们在person类中找到的一个函数-而不是我们在对象上查找的方法。这是因为我们在.的左侧使用了一个类,而不是一个实例。该函数将愉快地接受emp实例作为self的值 - 它不关心self是否是person实例。它是用户定义的对象,因此设置fnamelname属性没有问题。

之后,printper方法在emp实例上查找fnamelname属性将没有问题 - 因为它们就在那里。

"那又何必继承呢?">

因为即使这"有效",它实际上仍然没有建立继承关系。这会产生一些后果:

  • super不起作用 -__init__调用必须明确说明要使用哪个其他类,并且代码实际上没有意义。从外部的角度来看,它设置了正确的属性纯属巧合

  • 默认情况下,isinstance将不起作用。emp不在__bases__,也不在person__mro__

最新更新