8

The basic idea of what I want to do is:

def aFuncion(string = '', dicti = {}):
    if len(str) > 0:
         print 'you gave string as input'
    if len(dicti) > 0:
         print 'you gave a dict as input'

aFunction(string = 'test')
dict['test'] = test
aFunction(dicti = dict)

I know this kind of idea is possible in more OO type of languages, but is this also possible in python?

Right now I'm doing

def aFuncion(input):
    if type(input) == str:
         print 'you gave string as input'
    if type(input) == dict:
         print 'you gave a dict as input'

aFunction('test')

But I want the difference to be clear when the function is called

Niek de Klein
  • 8,524
  • 20
  • 72
  • 143

3 Answers3

8

The idea of having the same method support different argument types is known as multiple dispatch or multimethods.

To get a good introduction to it, you can read this Guido Van Rossum article and have a look at PyPi since there are a few multimethod packages available.

jcollado
  • 39,419
  • 8
  • 102
  • 133
4

This goal of wanting "the difference to be clear when the function is called" doesn't rub so well with the design philosophy of the language. Google "duck typing" for more information about that. The accepted inputs should be made clear by the docstring of the function, and that's all you need to do.

In python, when you want your input it to be a string or a dict, then you just write code which assumes the input will be an object which behaves in behave in a string-like way or a dict-like way. If the input doesn't, then you can try to handle that gracefully if you want, but usually you can simply leave your code to simply pop with an unhandled exception. This puts the ball back in the caller's court to either decide how to handle the situation, or realise that they were sending in bad data.

Type checks should be avoided in general, if really necessary it should be done with isinstance rather than an equality check on the type like you have done. This has the advantage of being more flexible for inheritance situations.

def aFuncion(input_):
    if isinstance(input_, str):
        print 'you gave a string-like input'
    elif isinstance(input_, dict):
        print 'you gave a dict-like input'

aFunction('test')

In python3 you now have another option of using type hinting function annotations. Read PEP 484 for more details about that feature.

wim
  • 338,267
  • 99
  • 616
  • 750
  • +1 Good point about language philosophy. Plus I believe you should change the name of the `input` argument (now it overwrites a built-in function). – Tadeck Feb 10 '12 at 10:29
0

What you have basically works, there's just some trouble with the variable declarations. Here is a working vesrion:

def aFunction(str = '', dicti = {}):
    if len(str) > 0:
         print 'you gave string as input'
    if len(dicti) > 0:
         print 'you gave a dict as input'

str = 'test'
dicti = dict([('test', 'test')])
aFunction(str = str)
aFunction(dicti = dicti)
aFunction(str = str, dicti = dicti)
aFunction(dicti = dicti, str = str)

puts:

you gave string as input
you gave a dict as input
you gave string as input
you gave a dict as input
you gave string as input
you gave a dict as input

You can also have non-specific arguments that are sent to the function as both a list and a dictionary (see What is a clean, pythonic way to have multiple constructors in Python? for example).

Community
  • 1
  • 1
Explosion Pills
  • 188,624
  • 52
  • 326
  • 405
  • Your answer is wrong. You can still call `aFunction` with: `aFunction([1,2,3])` and it will be assuming that you gave it a string (which clearly isn't the case) as well as `aFunction(dicti="this is not a dict")` and it would assume you inputed a dict. @wim got the correct answer, using duck typing. Assigning a default argument to a given type, won't give you guarantees, since Python is a weakly typed language and it may change at runtime. – Diogo Martins Nov 24 '15 at 11:47