Issue
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?
Solution
I think 6.) could be that the Protector
class makes just the basic shared methods abstract thus required, while leaving the extra methods to its heirs. Of course this can be splitted into more sub-classes, see https://repl.it/repls/AridScrawnyCoderesource (Written in Python 3.6)
class Protector(object):
def lookangry(self):
raise NotImplementedError("If it can't look angry, it can't protect")
def protect(self):
self.lookangry()
class Doggo(Protector):
def bark(self):
raise NotImplementedError("If a dog can't bark, it can't protect")
def protect(self):
super().protect()
self.bark()
class GermanShepherd(Doggo):
def lookangry(self):
print(') _ _ __/°°¬')
def bark(self):
print('wau wau')
class Pug(Doggo):
# We will not consider that screeching as barking so no bark method
def lookangry(self):
print('(◉ω◉)')
class ScaryCat(Protector):
def lookangry(self):
print('o(≧o≦)o')
class Kitten(Protector):
pass
doggo = GermanShepherd()
doggo.protect()
try:
gleam_of_silver = Pug()
gleam_of_silver.protect()
except NotImplementedError as e:
print(e)
cheezburger = ScaryCat()
cheezburger.protect()
try:
ball_of_wool = Kitten()
ball_of_wool.protect()
except NotImplementedError as e:
print(e)
Answered By - wiesion
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.