3

I'm relatively new to programming so I beg your pardon if I'm making a ridiculous mistake by referring to the following as Duck Typing.

I have a procedure which receives either a string or a tuple (containing strings) as a single argument.

Example:

def proc(arg):
    try:
        arg is a tuple
        handle arg a tuple
    except:
        arg is a simple string
        handle it so

Depending on whether the argument is a tuple or not, I want the function to behave differently.

I do not want to type check and would like to use a try..except process.

I thought about trying arg[0] but strings in Python are objects as well and in that regard they behave like tuples and return something.

What can I do here?

Thank you.

Phil
  • 13,875
  • 21
  • 81
  • 126
  • Exceptions should be used for *exceptional cases* not to handle regular runtime. – Aram Kocharyan Apr 09 '13 at 15:07
  • 3
    @AramKocharyan: actually, in Python it's quite acceptable to use exceptions for control flow purposes. I wouldn't use it here, though. – Fred Foo Apr 09 '13 at 15:08
  • You should use exceptions for when your code expects things to act in the same way *always* and does not. here, you want the code to behave differently depending on the variable, so you should not try..except, but rather check what it is. – Inbar Rose Apr 09 '13 at 15:09

3 Answers3

5

In your case I recommend you do not try..except since you want to behave differently depending on the type of variable...

It is when you DO NOT behave differently that you should use try..except.

From my comment:

You should use exceptions for when your code expects things to act in the same way always and does not. here, you want the code to behave differently depending on the variable, so you should not try..except, but rather check what it is

You can use isinstance.

isinstance(x, tuple)

Refer to this post for the difference between isinstance and type

All about Duck Typing and Forgiveness


Using your code, and my answer to create a solution:

def proc(arg):
    if isinstance(arg, tuple):
        # handle as tuple
    elif isinstance(arg, str):
        # handle as str
    else:
        # unhandled?
Community
  • 1
  • 1
Inbar Rose
  • 41,843
  • 24
  • 85
  • 131
  • 2
    Hello. I thought about isinstance as well but is it not **type checking** which is discouraged? – Phil Apr 09 '13 at 15:04
  • @Phil: in many cases, this is the way to go. I'd personally do `isinstance(x, basestring)` since more often than not, strings are the exception, not tuples. It depends on what you want to do, though. – Fred Foo Apr 09 '13 at 15:06
  • 1
    Sure it's "discouraged." But the language has these tools for a reoson; sometimes type-checking is the best way. – kindall Apr 09 '13 at 15:08
1

I think your mistake (not quite "ridiculous" since even experienced programmers sometimes make it) is here:

I have a procedure which receives either a string or a tuple (containing strings) as a single argument... Depending on whether the argument is a tuple or not, I want the function to behave differently.

Do not design your functions like that. A function should do one thing, if you need two different things, write two functions:

def process_item(some_string):
def process_items(tuple_of_strings):

Although there's no explicit typing in python, variables and parameters should remain typed -- that is, at any point of your program you should be able to tell what type each variable is. At the risk of exaggerating a bit, I would say that every isinstance in your code is a sign of a design flaw. Fix your design and there will be no need for workarounds.

georg
  • 211,518
  • 52
  • 313
  • 390
  • Hello. Thank you for your kind input. In the end, this is pretty much what I've ended up doing and it cleared the code immensely and everything looks much better. – Phil Apr 09 '13 at 15:41
0

If you want it anyway:

>>> s='vd sd'
>>> t=('ds','')
>>> t+='34'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can only concatenate tuple (not "str") to tuple
>>> s+='34'
>>>
f p
  • 3,165
  • 1
  • 27
  • 35
  • Hi! Although I decided not to go try..except route, this is an excellent input. Never thought of adding things to each other that way to differentiate between the two. Thanks! – Phil Apr 09 '13 at 15:42