我有以下代码:
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()
类Employee
和Gun
彼此无关并不重要,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
实例。它是用户定义的对象,因此设置fname
和lname
属性没有问题。
之后,printper
方法在emp
实例上查找fname
和lname
属性将没有问题 - 因为它们就在那里。
"那又何必继承呢?">
因为即使这"有效",它实际上仍然没有建立继承关系。这会产生一些后果:
super
不起作用 -__init__
调用必须明确说明要使用哪个其他类,并且代码实际上没有意义。从外部的角度来看,它设置了正确的属性纯属巧合。默认情况下,
isinstance
将不起作用。emp
不在__bases__
,也不在person
的__mro__
。