Interface and duck typing woes

Steven D'Aprano steve at pearwood.info
Thu Aug 29 03:53:10 EDT 2013


On Thu, 29 Aug 2013 08:31:25 +0200, Fabrice POMBET wrote:

> I am no depository of the pythonic way to think(tm) but I would create
> flock and inherit Duck from flock, or possibly set Flock as a method of
> ducks.

Neither of those are good design.

Donald is an individual Duck, he is not a flock of ducks. 
isinstance(donald, Flock) should return False, not True.


Likewise Donald has wings, a beak, even a sailor suit (but no pants). He 
does not have a Flock. hasattr(donald, 'Flock') should return False.


> that would look like this:
> 
> class Flock():
> 	def __init__(self, flock):
> 		self.flock=flock

This puts all the responsibility for creating the flock outside the 
class. As you show below, you have to do this:

flock=[]
flock.append(Duck('Donald'))

before calling Flock(flock). In this case, what is the point of the Flock 
class? It doesn't do anything. You might as well just work with the list.


> class Duck(Flock):
> 	def __init(self, flock):
> 		super().__init__(flock)

This design makes no sense. Presumably Duck should have an attribute 
"name". That's how you seem to be using it below, when you create
Duck("Donald"). But then you pass the name of the individual Duck up to 
the parent Flock. If Donald, Daffy and Daisy join a flock, why should the 
Flock be named "Donald"? Why should it have a name at all?


> then you only need to create some functions for any object to display
> the lists and or dicts that you will create outside these classes, in
> the main or in another function...
> 
> you just instantiate them like that:
> 
> Donald=Duck('Donald')
> or (rather):
> flock=[]
> flock.append(Duck('Donald'))


I think, rather, a better approach is:


class Flock:
    def __init__(self, *birds):
        self.birds = []
        # no up-front type checking
        self.birds.extend(birds)
        # --- or if you prefer Look Before You Leap ---
        for bird in birds:
            if isinstance(Duck, bird):
                self.birds.append(bird)
    def quack_all(self):
        for bird in self.birds:
            bird.quack()

class Duck:
    def __init__(self, name):
        self.name = name
    def quack(self):
        print "%s quacks" % self.name


-- 
Steven



More information about the Python-list mailing list