The principle of duck typing says that you shouldn't care what type of object you have – just whether or not you can do the required action with your object. For this reason the
isinstance
keyword is frowned upon. – –Definition
In below snippet(function) group_tweets_by_state
, following definition of duck typing, action setdefault
is performed on the object tweets_by_state
by appending object tweet
def group_tweets_by_state(tweets):
tweets_by_state = {}
USA_states_center_position = {n: find_center(s) for n, s in us_states.items()}
for tweet in tweets: # tweets are list of dictionaries
if hassattr(tweet, 'setdefault'): # tweet is a dictionary
state_name_key = find_closest_state(tweet, USA_states_center_position)
tweets_by_state.setdefault(state_name_key, []).append(tweet)
return tweets_by_state
My understanding is, function hasattr(tweet, 'setdefault')
is type checking tweet
to be of <class 'dict'>
type in duck typing style, before append.
Is my understanding correct? Does function group_tweets_by_state
follow duck typing?
Best Answer
A test like
hassattr(tweet, 'setdefault')
to make suretweet
is a dictionary is not a good one, since it obviously does not assuretweet
provides all methods/properties of a dictionary. So as longtweet.setdefault
is not the only method called byfind_closest_state
(which I think is unlikely), this test is not strict enough. On the other hand, a test likeisinstance(tweet, dict)
is too strict, because it forbids the usage of other, dictionary-like structures, which is exactly the idea of duck typing.In your example the requirement is not really that
tweet
is a dictionary, the requirement is thatfind_closest_state
can process the tweet, whatever methods it calls from a tweet, independently of the real type. The following solution will handle this in a generic manner, without the need of knowing exactly what methods insidefind_closest_state
are used:The code checks for an
AttributeError
because that is the exception you get whenfind_closest_state
calls a method not provided bytweet
. It also checks for aTypeError
, because that is what you get when you calltweet["abc"]
on a non-dictionary. You may need to add some other exceptions, depending on howfind_closest_state
is implemented internally, but you should not add any artificial constraints.And that's how duck typing should really be applied - by not making assumptions about the type of the object passed, only by testing whether or not you can do the required action (here: call
find_closest_state
without getting one of the above exceptions).