1

A simplified version of my problem: I want to write a method in python that takes in one parameter, either a list of strings or my custom object which holds a list of strings. Then return the size of the list. The method is specifically for a user to call so I want it to be simple for the user (essentially I don't want two methods doing the same exact thing except for a single line of code and I don't want to import non python standard libraries)

I realize overloading is not possible in python like it is in Java.

What is a good way to go about this/what is the standard way? The solutions I have thought of are:

Write two different methods. Write one method with two parameters and defaults, check for defaults move accordingly. Write one method with one parameter, check what kind of object is passed in, move accordingly (not entirely sure if this type checking is possible)

From a design perspective if statements for each type of object I want to handle does not seem great in the long run, but I don't see any other solutions (besides separate methods)

Thank you for suggestions!

Billy Sans
  • 39
  • 5
  • 3
    You can create different objects and implement [`__len__`](https://stackoverflow.com/questions/2481421/difference-between-len-and-len) in each one of them the way you want. – Nir Alfasi Jul 25 '17 at 19:54
  • Agree with @alfasin, overloading is often not necessary if you can rely on [`duck typing`](https://en.wikipedia.org/wiki/Duck_typing). Just implement `__len__` in your class and then it doesn't matter which type you pass in. – AChampion Jul 25 '17 at 20:11

2 Answers2

2

In python, you use a single dispatch function to establish a single method with different implementations based on the argument type (specifically, on the type of the first argument).

from functools import singledispatch

@singledispatch
def process_str_list(str_list):
    raise NotImplementedError

@process_str_list.register(list)
def _(str_list):
    # process raw list of strings

@process_str_list.register(MyStrListClass)
def _(str_list)
    # process my object

To invoke the function, simply call process_str_list with your raw list or object. The type determination and implementation multiplexing takes place internally.

EDIT: Just wanted to add that the PEP that introduced single dispatch says:

It is currently a common anti-pattern for Python code to inspect the types of received arguments, in order to decide what to do with the objects.

Single dispatch is the pythonic way to approach that behavior.

wbadart
  • 2,583
  • 1
  • 13
  • 27
  • 1
    I would say `duck typing` is the pythonic way to approach this behaviour. `@singledispatch` was only added in `3.4`. – AChampion Jul 25 '17 at 20:15
0

As alfasin suggested, you can implement a __len__ function for your object;

class A(object):
    def __init__(self, mylist):
        self.mylist = mylist
    def __len__(self):
        return len(self.mylist)

For more complex distinctions, you can use isinstance at the function level:

def myfunction(obj):
    if isinstance(obj, list):
        # when the object is a list
    elif isinstance(obj, MyClass):
        # when the object is something else
    else:
        raise ValueError('wrong type!')
user1620443
  • 784
  • 3
  • 14