What is the canonical way of handling different types in Python?

I have a function where I need to generate different output strings for another program I invoke, depending on which type it wants.

Basically, the called program needs a command line argument telling it which type it was called with.

Happily I found this answer on SO on how to check a variable for type. But I noticed how people also raised objections, that checking for types betrays a "not object oriented" design. So, is there some other way, presumable more "more object oriented" way of handling this without explicitly checking for type?

The code I have now goes something like this:

def myfunc(val):
    cmd_type = 'i'
    if instance(val, str):
        cmd_type = 's'

    cmdline = 'magicprogram ' + cmd_type + ' ' + val
    Popen(cmdline, ... blah blah)
    ...

which works just fine, but I just wanted to know if there is some technique I am unaware of.

Answers


I don't think Double Dispatching or Multimethods are particularly relevant nor have much to do with the objections people had to that other SO answer.

Not surprisingly, to make what you're doing more object-oriented, you'd need introduce some objects (and corresponding classes) into it. Making each value an instance of a class would allow -- in fact, virtually force -- you to stop checking its type. The modifications to your sample code below show a very simple way this could have been done:

class Value(object):
    """ Generic container of values. """
    def __init__(self, type_, val):
        self.type = type_   # using 'type_' to avoid hiding built-in
        self.val = val

def myfunc(val):
    # Look ma, no type-checking!
    cmdline = 'magicprogram {obj.type} {obj.val}'.format(obj=val)
    print 'Popen({!r}, ... blah blah)'.format(cmdline)
    # ...

val1 = Value('i', 42)
val2 = Value('s', 'foobar')

myfunc(val1)  # Popen('magicprogram i 42', ... blah blah)
myfunc(val2)  # Popen('magicprogram s foobar', ... blah blah)

It would be even more object-oriented if there were methods in the Value class to access its attributes indirectly, but just doing the above gets rid of the infamous type-checking. A more object-oriented design would probably have a different subclass for each kind of Value which all share a common set of methods for clients, like myfunc(), to use to create, manipulate, and extract information from them.

Another benefit of using objects is that you shouldn't have to modify myfunc() if/when you add support for a new type of 'Value` to your application -- if your abstraction of the essence of a "Value" is a good one, that is.


You could use Double Dispatch or Multimethods.


    But I noticed how people also raised objections, 
that checking for types betrays a "not object oriented" design

Actually it's called Duck typing style ("If it looks like a duck and quacks like a duck, it must be a duck."), and it's the python language that recommend using this style of programming .

and with duck typing come something call EAFP (Easier to Ask Forgiveness than Permission)

    presumable more "more object oriented" way of handling this without 
   explicitly checking for type?

you mean more pythonic, basically what will be more pythonic in your case is something like this:

def myfunc(val):
    cmd_type = 'i'

    # forget about passing type to your magicprogram
    cmdline = 'magicprogram  %s ' % val 
    Popen(cmdline, ... blah blah)

and in your magicprogram (i don't know if it's your script or ...), and because in all cases your program will get a string so just try to convert it to whatever your script accept;

from optparse import OptionParser

# ....

if __name__ == '__main__':

    parser = OptionParser(usage="blah blah")

    # ...
    (options, args) = parser.parse_args()

    # Here you apply the EAFP with all type accepted.
    try:
        # call the function that will deal with if arg is string
        # remember duck typing.
    except ... :
        # You can continue here

I don't know what's all your code, but you can follow the example above it's more pythonic, and remember every rule has their exception so maybe your case is an exception and you will better be with type checking.

Hope this will clear things for you.


Need Your Help

To save data from DataGridView to Sql Server 2008 in C# 2008 takes too much time

c# sql-server-2008 datagridview

I have a DataGridView which have 303 rows and 11 column. When I am going to save all this data to my sql table it takes 30-40 secs. Is this possible to save this data within 1-2 secs.

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.