python - call Python method if it exists
问题描述
How to call a subclass method from a base class method, only if the subclass supports that method? And what's the best way to do that? Illustrative example, I have an animal that protects my house: if someone walks by it will look angry, and it will bark if it can.
Example code:
class Protector(object):
def protect(self):
self.lookangry()
if hasattr(self, 'bark'):
self.bark()
class GermanShepherd(Protector):
def lookangry(self):
print u') _ _ __/°°¬'
def bark(self):
print 'wau wau'
class ScaryCat(Protector):
def lookangry(self):
print '=^..^='
I can think of lots of alternative implementations for this:
- Using
hasattr
as above. try: self.bark() except AttributeError: pass
but that also catches any AttributeErrors inbark
- Same as 2 but inspect the error message to make sure it's the right AttributeError
- Like 2 but define an abstract bark method that raises
NotImplementedError
in the abstract class and check forNotImplementedError
instead ofAttributeError
. With this solution Pylint will complain that I forgot to override the abstract method inScaryCat
. Define an empty bark method in the abstract class:
class Protector(object): def protect(self): self.lookangry() self.bark() def bark(self): pass
I figured in Python their should usually be one way to do something. In this case it's not clear to me which. Which one of these options is most readable, least likely to introduce a bug when stuff is changed and most inline with coding standards, especially Pylint? Is there a better way to do it that I've missed?
解决方案
在我看来,您正在错误地考虑继承。基类应该封装在任何子类之间共享的所有内容。如果某些东西没有被所有子类共享,则根据定义,它不是基类的一部分。
所以你的说法“如果有人走过它会看起来很生气,如果可以的话它会吠叫”对我来说没有意义。“如果可以的话”部分不会在所有子类中共享,因此它不应该在基类中实现。
应该发生的是,您想要吠叫的子类将此功能添加protect()
到方法中。如:
class Protector():
def protect(self):
self.lookangry()
class GermanShepherd(Protector):
def protect(self):
super().protect() # or super(GermanShepherd, self).protect() for Python 2
self.bark()
这样,所有子类都会lookangry()
,但实现bark()
方法的子类将把它作为超类protect()
方法的扩展功能的一部分。
推荐阅读
- android - 设置了“不保留活动”,未调用 onSaveInstanceState
- android - 如何更改卡片视图中信息的数字格式?
- wordpress - 我可以在一个域上安装两次 wordpress
- terraform - 获取一组子网的 CIDR 块
- javascript - 如何优化 querySelectorAll 记录?
- java - ArrayIndexOutOfBoundsException 3 创建三重数组时出错
- firebase - 在颤动中使用来自 PageView.builder 的输入创建和更新数据库
- android - Nativescript searchBar 属性keyboardType 不起作用
- javascript - js动态访问私有字段(属性/成员)
- reactjs - React-app 在 Internet Explorer 11 中不起作用