根据继承文档:
派生类可以重写其基类的方法。因为在调用同一对象的其他方法时,方法没有特殊权限,所以调用在同一基类中定义的另一个方法的基类方法可能会调用覆盖它的派生类的方法。
发生这种情况是如何的?有人能用简单的例子说明这个概念吗?
派生类可以重写其基类的方法。因为在调用同一对象的其他方法时,方法没有特殊权限,所以调用在同一基类中定义的另一个方法的基类方法可能会调用覆盖它的派生类的方法。
发生这种情况是如何的?有人能用简单的例子说明这个概念吗?
以下是您所请求的示例。这将打印出chocolate
。
class Base:
def foo(self):
print("foo")
def bar(self):
self.foo()
class Derived(Base):
def foo(self):
print("chocolate")
d = Derived()
d.bar() # prints "chocolate"
之所以打印出字符串chocolate
而不是foo
,是因为Derived
覆盖了foo()
函数。即使bar()
在Base
中被定义,它最终调用的是Derived
实现的foo()
,而不是Base
的实现。
Base
类的一个实例的方法永远不会执行Derived
类的方法?我原以为文档是在暗示这一点。 - innisfreeBase
类的一个实例,这可能是混淆的根源。但是,是的,Base().bar()
不会调用任何重写的方法。 - Bergib = Base(); b.foo = Derived.foo.__get__(b); b.bar()
。但是,这只会在你明确放入代码时才会发生。 - jpmc26当对类实例进行属性查找时,按照一定顺序搜索该类字典和其基类的字典(参见:方法解析顺序),以寻找适当的方法。被发现的方法会首先被调用。
使用以下 Spam
示例:
class Spam:
def produce_spam(self):
print("spam")
def get_spam(self):
self.produce_spam()
class SuperSpam(Spam):
def produce_spam(self):
print("super spam")
Spam
定义了函数 produce_spam
和 get_spam
。它们存储在其 Spam.__dict__
(类命名空间) 中。通过继承,子类 SuperSpam
可以访问这两个方法。SuperSpam.produce_spam
并不替代 Spam.produce_spam
,当查找实例中的名称 'produce_spam'
时,它仅是先被找到。
基本上,继承的结果是,如果在子类的字典中未找到属性,则还会搜索任何基类的字典。
当第一次使用函数 get_spam
进行调用时:
s = SuperSpam()
s.get_spam()
事件的顺序大致如下:
SuperSpam
的 __dict__
,以获取 get_spam
。SuperSpam
的 __dict__
中没有找到,所以继续查找其基类(mro
链)的字典。Spam
在 mro
链中的下一个位置,因此在 Spam
的字典中找到了 get_spam
。现在,在使用 self.produce_spam
查找 produce_spam
时,序列要短得多:
SuperSpam
(self
)的 __dict__
,以获取 produce_spam
。produce_spam
最先在 __dict__
中被找到,因此被提取了出来。
class Base():
def m1(self):
return self.m2()
def m2(self):
return 'base'
class Sub(Base):
def m2(self):
return 'sub'
b = Base()
s = Sub()
print(b.m1(), s.m1())
输出 "base sub"。
class Parent(object):
def eat(self):
print("I don't want to eat that {}.".format(self.takefrompocket()))
def takefrompocket(self):
return 'apple'
def __getattribute__(self, name):
print('Looking for:', name)
method_to_use = object.__getattribute__(self, name)
print('Found method:', method_to_use)
return method_to_use
class Child(Parent):
def takefrompocket(self):
return 'salad'
__getattribute__
方法在新式类中(例如Python3中的所有类)负责属性查找。它只是被实现为打印每个查找所做的事情 - 通常您不希望也不应该自己实现它。如果您真的感兴趣,查找将遵循Python的方法解析顺序(MRO)。
>>> some_kid = Child()
>>> some_kid.eat()
Looking for: eat
Found method: <bound method Parent.eat of <__main__.Child object at 0x0000027BCA4EEA58>>
Looking for: takefrompocket
Found method: <bound method Child.takefrompocket of <__main__.Child object at 0x0000027BCA4EEA58>>
I don't want to eat that salad.
eat
时,它在这个例子中使用的是 Parent.eat
。但是 self.takefrompocket
是从 Child
中使用的。>>> some_parent = Parent()
>>> some_parent.eat()
Looking for: eat
Found method: <bound method Parent.eat of <__main__.Parent object at 0x0000027BCA4EE358>>
Looking for: takefrompocket
Found method: <bound method Parent.takefrompocket of <__main__.Parent object at 0x0000027BCA4EE358>>
I don't want to eat that apple.
这里的两种方法都来自Parent
。继承类通常不会干扰它们的祖先!
class Base(object):
def something (self):
raise ('Not implemented')