Question

Ok, so I have a list of tuples containing a three values (code, value, unit)

when I'm to use this I need to check if a value is an str, a list or a matrix. (or check if list and then check if list again)

My question is simply should I do like this, or is there some better way?

for code, value, unit in tuples:
    if isinstance(value, str): 
        # Do for this item
    elif isinstance(value, collections.Iterable):
        # Do for each item
        for x in value:
             if isinstance(x, str):
                  # Do for this item
             elif isinstance(x, collections.Iterable):
                  # Do for each item
                  for x in value:
                      # ...
             else:
                  raise Exception
    else:
        raise Exception
Was it helpful?

Solution

The best solution is to avoid mixing types like this, but if you're stuck with it then what you've written is fine except I'd only check for the str instance. If it isn't a string or an iterable then you'll get a more appropriate exception anyway so no need to do it yourself.

for (code,value,unit) in tuples:
    if isinstance(value,str): 
        #Do for this item
    else:
        #Do for each item
        for x in value:
             if isinstance(value,str):
                  #Do for this item
             else:
                  #Do for each item
                  for x in value:

OTHER TIPS

This works but every time you call isinstance, you should ask yourself "can I add a method to value instead?" That would change the code into:

for (code,value,unit) in tuples:
    value.doSomething(code, unit)

For this to work, you'll have to wrap types like str and lists in helper types that implement doSomething()

An alternative to your approach is to factor out this code into a more general generator function (assuming Python 2.x):

def flatten(x):
    if isinstance(x, basestring):
        yield x
    else:
        for y in x:
            for z in flatten(y):
                yield y

(This also incorporates the simplifications suggested and explained in Duncan's answer.)

Now, your code becomes very simple and readable:

for code, value, unit in tuples:
    for v in flatten(value):
        # whatever

Factoring the code out also helps to deal with this data structure at several places in the code.

Just use the tuples and catch any exceptions. Don't look before you jump :)

Recursion will help.

def processvalue(value):
  if isinstance(value, list): # string is type Iterable (thanks @sven)
    for x in value:
      processvalue(value)
  else:
    # Do your processing of string or matrices or whatever.


# Test each the value in each tuple.
for (code, value, unit) in tuples:
  processvalue(value)

This is a neater way of dealing with nested structures, and will also give you the ability to process abitrary depths.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top