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"
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”
1
为了说明它的工作原理,请考虑以下两个类:
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中的所有类) . 它只是实现 print 每个查找的作用 - normally you don't want to and shouldn't implement it yourself . 如果您真的感兴趣,查找遵循pythons method resolution order (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.
>>> 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 . 继承的类不会(通常)干扰他们的祖先!
8
如果您的子类没有实现该方法,请引发异常!
class Base(object):
def something (self):
raise ('Not implemented')
5 回答
这是您请求的示例 . 这打印
chocolate
.打印字符串
chocolate
而不是foo
,因为Derived
会覆盖foo()
函数 . 即使在Base
中定义了bar()
,它最终也会调用foo()
的Derived
实现,而不是Base
实现 .它是如何工作的?
当对类的实例执行属性查找时,类字典 and 将按照特定顺序搜索其基类的字典(请参阅:Method Resolution Order)以获取适当的方法 . 首先发现的是被召唤 .
使用以下
Spam
示例:Spam
定义函数produce_spam
和get_spam
. 它们存在于Spam.__dict__
(类命名空间)中 . 通过继承,子类SuperSpam
可以访问这两种方法 .SuperSpam.produce_spam
不会替换Spam.produce_spam
,只是在其中一个实例上查找名称'produce_spam'
时,才会找到它 .本质上,继承的结果是,如果在对子类进行属性查找之后,在子类的字典中找不到该属性,那么任何基类的字典也将被搜索 .
首次调用函数
get_spam
时:事件的顺序大致如下:
查看
SuperSpam
s__dict__
了解get_spam
.因为在
SuperSpam
中找不到它__dict__
查看它的基类(mro
链)的字典 .Spam
是mro
链中的下一个,所以get_spam
在Spam
的字典中找到 .现在,当在
get_spam
的主体中使用self.produce_spam
查找produce_spam
时,序列要短得多:查看
SuperSpam
的(self
)__dict__
了解produce_spam
.找到它,得到它并调用它 .
produce_spam
首先在__dict__
中找到,以便获取 .打印“base sub”
为了说明它的工作原理,请考虑以下两个类:
__getattribute__
方法负责属性查找的新样式类(如python3中的所有类) . 它只是实现print
每个查找的作用 - normally you don't want to and shouldn't implement it yourself . 如果您真的感兴趣,查找遵循pythons method resolution order (MRO) .因此,当您想使用
eat
时,它在此示例中使用Parent.eat
. 但self.takefrompocket
用于Child
.这两种方法都取自
Parent
. 继承的类不会(通常)干扰他们的祖先!如果您的子类没有实现该方法,请引发异常!