2

I have a function that accepts either a string or a dictionary as an argument. That is, it can be called as either:

lookup_person({name: "John Smith", age: 57})

or

lookup_person("John Smith")

My first inclination is to use type or isinstance to distinguish the type of the argument, but I've seen a lot of ink spilled over whether and when rigid type detection is appropriate. The prevailing wisdom I've read suggests that I should test if my object implements some interface, but testing for particular string or dictionary methods seems significantly less safe than simply testing if the type of the object is a string or dictionary.

Is it possible to employ duck typing here, and is it appropriate to do so? Or do I have a larger problem, and my approach here somehow fundamentally not Pythonic?

EDIT: To clarify, passing a dictionary is the "typical" use. Passing in a string is simply an API shorthand for a single-entry dictionary with name, i.e., lookup_person({name:"John Smith"}).

apsillers
  • 5,083
  • 25
  • 33

1 Answers1

3

You definitely can use duck typing here, although I'm not sure why you want to accept both a dictionary and a string in this case.

I'd ask for forgiveness instead of permission in this case:

try:
    name = person['name']  # treat as dictionary
except TypeError:
    name = person          # assume it's a string instead

but do review if asking for permission might be faster for your case.

Martijn Pieters
  • 14,499
  • 10
  • 57
  • 58
  • I agree. Ideally I would have had two functions: lookup_person_dict, lookup_person_string and force the user to be specific. The problem I find with this is that you basically use a try/except block for control flow, is a big no-no in my eyes. However, having a function which accepts both string and hashmaps is also a no-no in my eyes, and so this exception flow is the cleanest alternative I can think of at least. – martiert Jan 15 '13 at 15:13
  • 2
    @martiert: No, ideally you force the user to use `lookup_person(somedict['name'])`; simplify the API as there is no need for the rest of the `dict`. – Martijn Pieters Jan 15 '13 at 15:15
  • True. Given that the lookup is as easy as you assume in your code. – martiert Jan 15 '13 at 15:18
  • @martiert: The OP has not given us more than that. – Martijn Pieters Jan 15 '13 at 15:21