I am having trouble resolving the issue of placing a method in a python program, where it seems the approach used for duck input, which I'm used to relying on, contradicts my OOP instincts.
To illustrate, suppose we have three classes: Hero, Sword, and Apple. A hero can equip a sword, and a hero can eat an apple.
If I were following my OOP gut, I think the code would look like this:
duckless.py
class Hero:
def __init__(self):
self.weapon = None
self.inTummy = None
def equip(self, weapon):
weapon.define()
print("I shall equip it.")
self.weapon = weapon
def eat(self, food):
food.define()
print("I shall consume it.")
self.inTummy = food
class Sword:
def define(self):
print("'tis a shiny sword")
class Apple:
def define(self):
print("'tis a plump apple")
hero = Hero()
swd = Sword()
apl = Apple()
hero.equip(swd)
hero.eat(apl)
Which feels very intuitive and readable.
If I were a duck-type, it seemed to me that the code would look something like this:
duckfull.py
class Hero:
def __init__(self):
self.weapon = None
self.inTummy = None
def onEquip(self):
print("I shall equip it.")
def onEat(self):
print("I shall eat it.")
class Sword:
def define(self):
print("'tis a shiny sword")
def equip(self, hero):
self.define()
hero.onEquip()
hero.weapon = self
class Apple:
def define(self):
print("'tis a plump apple")
def eat(self, hero):
self.define()
hero.onEat()
hero.inTummy = self
hero = Hero()
swd = Sword()
apl = Apple()
swd.equip(hero)
apl.eat(hero)
Duck code has a clear advantage in that I can execute try-except at any time to determine if I am performing a “legitimate” action:
try:
apl.equip()
except AttributeError:
print("I can't equip that!")
pythonic, .
, , , . , , , .
def eat(self, hero):
self.define()
hero.onEat()
hero.inTummy = self
.
? ? ?
.