0

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
1
  • The body of the outer for loop is rather confusing. Shouldn't there be x instead of value in the first line? And shouldn't the inner loop be something like for y in x? Commented Jul 23, 2012 at 12:28

5 Answers 5

3

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:
Sign up to request clarification or add additional context in comments.

Comments

2

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()

1 Comment

I wont actually do anything on the value, but assign value(s) to an excelsheet. I believe it is easier for me to do like Duncan says.
2

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.

Comments

1

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

1 Comment

I think you mean, Easier to Ask forgiveness than Permission :)
0

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.

2 Comments

In this case I know that 2dimensional arrays are the largest, and i have to index them, which might be harder using this approach
I don't understand what you mean by indexing them.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.