Python - Unsupported type(s) : range and range

2020-04-04 01:59发布

问题:

I'm getting this strange error trying to run a script, the code appears to be correct but it seems python (3) didn't liked this part:

        def function(x):
                  if integer:
                    return int(x)
                else:
                    return x

            non_nil = randrange(21)
            d = dict([(randrange(101), Racional(coeff(randrange(-20,20)),
                                    coeff(choice(range(-30,0)+\
                                                 range(1,30)))))
                     for k in range(non_nil)])

And i get the following error:

for k in range(non_nil)]) unsupported operand type(s) for +: 'range' and 'range'

I already tried to put the last four lines in a single one but python returns the same error.

回答1:

This is because Python 3 range does not return a list, like Python 2. This code was written for Python 2.

This code, should be changed:

range(-30,0) + range(1,30)

It should be changed to:

list(range(-30,0)) + list(range(1,30))


回答2:

As others have pointed out the problem is that in Python 3, range() returns an iterator not a list like it does in Python 2.

Here' one workaround: Add something like the following function:

def non_zero_range(lower, upper):
    ret = list(range(lower, upper))
    ret.remove(0)
    return ret

and then change the second Racional() call argument from:

coeff(choice(range(-30,0)+range(1,30)))

to simply:

coeff(choice(non_zero_range(-30,30)))

You will have something that would work in both Python 2 and 3.



回答3:

In the middle of your expression you do range(-30,0) + range(1,30). This is causing the error because in Python 3 range() returns an iterator, not a list like in Python 2.x.

One way to get this to work is to just convert each range to a list before adding:

d = dict([(randrange(101), Racional(coeff(randrange(-20,20)),
                                coeff(choice(list(range(-30,0))+
                                             list(range(1,30))))))
         for k in range(non_nil)])

Since it seems like you want to just exclude 0 from the range(-30, 30), you could also use filter(None, range(-30, 30)).

Alternatively you could use choice((1, -1)) * choice(range(1, 30)), which is equivalent to choice(list(range(-30, 0)) + list(range(1, 30))). (edit: actually the prior expression will not include -30 in the possibilities, not sure whether or not that is an issue).



回答4:

As other answers have said, range() being an iterator is your problem, however, a simpler (in my view) solution is to generate the list from -30 to 30 then remove 0, rather than avoiding it:

choice([i for i in range(-30, 30) if i != 0])

Naturally, if your ranges were more disparate, this might become unwieldy.