Interface and duck typing woes

Roy Smith roy at panix.com
Sat Aug 31 20:52:52 EDT 2013


In article <5221352b$0$6599$c3e8da3$5496439d at news.astraweb.com>,
 Steven D'Aprano <steve+comp.lang.python at pearwood.info> wrote:

> Heh, everybody has one of two reactions: 
> 
> "This is awesome!" [[i.e. what I said]]
> 
> "You'll add type checking to my Python code over my dead body!!!"

Duck typing is a funny thing.  Sure, I don't have to give you a Duck, I 
just have to give you something that quacks like a Duck.  But, at some 
point, you and I need to agree on what that means.  If you're expecting 
a https://en.wikipedia.org/wiki/Duck and I give you a 
https://en.wikipedia.org/wiki/DUKW, we've had a failure to communicate.

To take a quasi-realistic example, let's say I've got this musical 
masterpiece in my database:

{
   "_id" : ObjectId("4ccb7052e5f37551d479add6"),
   "album" : "My World",
   "album_comp_id" : NumberLong(34732133),
   "artist" : "Justin Bieber",
   "avail_date_aac" : ISODate("1970-01-01T00:00:00Z"),
   "avail_date_mp3" : ISODate("1970-01-01T00:00:00Z"),
   "duration" : 192,
   "genre" : "Pop",
   "mn_comp_id" : NumberLong(34732147),
   "seq_num" : 1297,
   "song_id" : 6544798,
   "title" : "Love Me",
   "track" : -1
}

If I want to ask you, "Please return to me a url from which I can stream 
this song as an mp3", I could look at your Song class and find:

@staticmethod
def get_stream_url(song):
   [some code goes here]

but that would leave me wondering what you mean by "song".  You could 
legitimately mean 6544798, "4ccb7052e5f37551d479add6", 
ObjectId("4ccb7052e5f37551d479add6"), an instance of the Song class 
itself, or possibly even 34732147.  Depending on the context, any of 
those might very well be the right answer.

And, we haven't even gotten to describing what I should expect to get 
back.

So, to clear things up, you had to go and write something in the doc 
string:

@staticmethod
def get_stream_url(song):
   """Song is an instance of class Song.  This will return
   an absolute URL as a string."""

But, why not just embed that information in some way which is both 
compact and machine readable?

Of course, when I say, "Song is an instance of class Song", what I 
really (in full duck typing glory) mean is, "Song is something which has 
a "mn_comp_id" attribute whose value is something which I can pass to 
str() and get back a properly formatted decimal integer string.  So, 
this would work, wouldn't it?

class Platypus:
    def __getattr__(self, name):
        return 34732147

duck = Platypus()
Song.get_stream_url(duck)

Hey, it met the description you gave me, didn't it?  And, sure enough, 
if you do with duck what I expect you will, we will soon hear Justin 
Bieber's, "Love Me" coming out the speaker.  But, in reality, I suspect 
we would quickly get into an argument about just what exactly did you 
mean when you said "Duck".



More information about the Python-list mailing list