开发者

Python logic error?

Basically, I'm trying to flatten a list in my function but ignore that (you can also ignore the print functions I put in). take x = [[1,2,3],4,5] to be my variable. I call prob7(x) but the issue is that when type([1,2,3]) gets checked == list, it returns false. Why is that? I explicitly check this on the interpreter command line and it returns true. But inside the function, I get a false.

Just a bug that I missed because I'm sleepy or am I misunderstanding some part of the Python language? I run version 2.6 if it matters.

def prob7(list): # flatten a list
    tempList = []
    if list: # meaning if there are elements in the list and it is not empty
        for i in list:
            if type(i) != list:
                print tempList,'if',i,type(i)==list
                tempList.append(i)
            else:
                print tempList,'else',i
                tempList.extend开发者_运维知识库(prob7(i))

    return tempList


Just not use 'list' as a variable name and use isinstance(var, list) instead of type(var) == list. Please find corrected sample below.

def prob7(mylist): # flatten a list
    tempList = []
    if mylist: # meaning if there are elements in the list and it is not empty
        for i in mylist:
            if not isinstance(i, list):
                print tempList, 'if', i, isinstance(i, list)
                tempList.append(i)
            else:
                print tempList, 'else', i
                tempList.extend(prob7(i))    
    return tempList

Or if you don't really required to use recursion and you don't care about values order then you can use something like this:

lVals = [[1,2,3],4,5, [1,[4,7]]]

def make_flat(mylist): # flatten a list    
    while any(isinstance(x, list) for x in mylist):
        for i, val in enumerate(mylist):
            if isinstance(val, list):                
                mylist.extend(mylist.pop(i))        
                break
    return mylist

make_flat(lVals)
>>> [4, 5, 1, 2, 3, 1, 4, 7]


Artisom has your answer. In addtion, type checks are not very Pythonic. Duck typing often is the way to go. In case your elements are numbers only, the following does the job too, without explicit type checks but behavior checks:

def prob7(inlist): # flatten a list
    outlist = []
    for x in inlist:
        try:
            outlist += x
        except TypeError:
            outlist.append(x)
    return outlist

Note that string elements in this implementation would behave like nested lists. Anyway, just wanted to illustrate what it means to expect behavior, not types.


Some alternate approaches:

# Iterative, but more functional-style
def flatten(a_list):
  while any(isinstance(x, list) for x in a_list):
    a_list = sum((x if isinstance(x, list) else [x] for x in a_list), [])
  return a_list

# Using a generator recursively, 
# then evaluating the generator to produce the list
# instead of explicitly appending each element.
def flatten_gen(a_list):
  for x in a_list:
    if isinstance(x, list):
      for y in flatten_gen(x): yield y
    else: yield x

def flatten(a_list): return list(flatten_gen(a_list))


The problem here is you are using a local variable name (list) that is the same as the global list type. You should change your variable name. Also, when checking types like that you can use the is operator.

type(l) is list

But here's my version of flatten.

def flatten(alist):
    rv = []
    for val in alist:
        if isinstance(val, list):
            rv.extend(flatten(val))
        else:
            rv.append(val)
    return rv

This does not alter the original list, but returns a new list. This is consistent with most other patterns.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜