user2804628
user2804628

Reputation: 143

Why is variable behaving differently outside loop?

if i run this code:

def numbers_in_lists(string):
    next_number = 0
    count = 0
    final_list = []
    while count < len(string):
        number = int(string[count])
        if number > next_number:
            final_list.append(number)
            new = []
            next_number = number
        else:
            new.append(number)
            if new not in final_list:
                final_list.append(new)
        count += 1
    print final_list


#testcases
string = '543987'
result = [5,[4,3],9,[8,7]]
print repr(string), numbers_in_lists(string) == result

i get this answer:

'543987' [5, [4, 3], 9, [8, 7]]
False

but if i put the number variable outside of the while loop like this:

def numbers_in_lists(string):
    next_number = 0
    count = 0
    final_list = []
    number = int(string[count])
    while count < len(string):
        if number > next_number:
            final_list.append(number)
            new = []
            next_number = number
        else:
            new.append(number)
            if new not in final_list:
                final_list.append(new)
        count += 1
    print final_list

i get this answer:

'543987' [5, [5, 5, 5, 5, 5]]
False

I am a beginner and i have looked everywhere for the explanation as to why the number variable behaves differently outside of the loop? Also, why are the other variables ok outside of the loop but not number variable?

Any help would be much appreciated. Thankyou. :)

Upvotes: 0

Views: 1844

Answers (3)

Cory Kramer
Cory Kramer

Reputation: 117856

You declare number as

number = int(string[count])

So when

count = 0

This means that number will be the first character of your string (position [0]) converted to int. If you do not update number within your loop, it will never change. In your first version of the code, number is in your while loop.

while count < len(string):
    number = int(string[count])
    # more code
    count += 1

Note at the end of the loop, you increment count. This means at the beginning of the next iteration, count now is incremented, so number will take on the value of the next character in your string.

A common misconception for beginners is that a variable is somehow "bound" to another variable. For example:

>>> a = 5
>>> b = a
>>> b
5

>>> a = 7
>>> b
5

See, even though a changed values from 5 to 7, b doesn't change because it is not "bound" to that variable in any way. The line b = a means "take the value from a and assign it to b" after that, b doesn't care what happens to a.

Upvotes: 1

hughdbrown
hughdbrown

Reputation: 49003

I get that you are a beginner. Here is a rewrite that should help you with some useful python idioms and constructs:

def numbers_in_lists(string):
    numbers = [int(c) for c in string]
    next_number = -1
    final_list = []
    for number in numbers:
        if number > next_number:
            final_list.append(number)
            final_list.append([])
            next_number = number
        else:
            final_list[-1].append(number)
    final_list = [x for x in final_list if x != []]
    print final_list

First, be suspicious when you have a while-loop and a counter. You can replace it with a for-loop that iterates over all the items.

Since this code operates on integers, not characters in a string, let's translate them all at once using a list comprehension:

numbers = [int(c) for c in string]

This creates a list that has all the characters translated to integers.

By setting next_number = -1, we ensure that all numbers in numbers will be greater. In particular, the first element will be greater.

When we find a number that exceeds our last maximum, next_number, we add number and a bucket to put succeeding numbers less than number into:

        if number > next_number:
            final_list.append(number)
            final_list.append([])
            next_number = number

That means when we add 5, final_list looks like this:

[5, []]

And when number is 4 and 3, they get added properly:

[5, [4]]
[5, [4, 3]]

How does that happen? This code does it:

        else:
            final_list[-1].append(number)

Here we do not append to final_list; we append to the last list in final_list, final_list[-1].

But what if our sequence was just 5? Then at the end of the loop, final_list would look like this:

[5, []]

In that case, we want to trim out all empty lists, so we do it like this:

final_list = [x for x in final_list if x != []]

This says, "make final_list into a list that has all elements of final_list except those that are empty lists."

Good luck with learning python. I hope you find it rewarding.

Upvotes: 1

Padraic Cunningham
Padraic Cunningham

Reputation: 180391

The number = int(string[count]) uses the value of count assigned outside the loop which is the first character index 0, it will never change outside the loop, so you will always get the original value appended which is the first character.

Using number = int(string[count]) inside the loop you are reassigning number to the value of the element at index count each time so you get a different part of the input string appended each time.

Once you enter the while loop any values you change that were defined outside of the loop will not change outside that loop, you must reassign the value inside the loop.

Upvotes: 1

Related Questions