python 中关于派生 class 用法语法的继承

inheritance in python about derived class usage syntax

我有以下代码:

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): 以获得派生的 class 实际上不是强制性的吗?

Python不关心提前检查类型、继承关系等。它只关心代码为 运行 时会发生什么。 This allows for what is called "duck typing":

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()

class与EmployeeGun没有关系,fired的目的无关紧要是完全不同的。列表中的两个对象都有一个名为 fired 的方法,因此代码可以正常运行。

与您的代码类似:

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

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

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

“那么,为什么还要费心去继承呢?”

因为即使这个“有效”,它仍然没有真正建立继承关系。这会产生一些后果:

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

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