Loop for with isinstance() command does not work as expected

Asked

Viewed 41 times

-2

The first time I printed the variable "b", I expected the number 6 to appear, but a 0 is returned. However, outside the function it works perfectly. How to make this specific code work within a function?

a = [0, 1, 2, 3, 4, 5, 'b']
b = 0


def how_many_integers(aa, bb):
    for i in aa:
        if isinstance(i, int):
            bb += 1


how_many_integers(a, b)
print(b) # Retorna 0

for i in a:
    if isinstance(i, int):
        b += 1

print(b) # Retorna 6
  • Because you can’t pass an integer in Python by reference. So when you change bb within the function, the variable b passed as argument continues to store the value 0. A possible solution would be to declare b as a list, type b = [0] and within the function use bb[0] += 1, It would work, but the architecture would still suck. I mean, if a function counts the number of integers, that amount has to be its return value and not the change of one of its arguments.

  • The variable bb is a function parameter, and any modification made there does not change the b that is out of function - see here a more detailed explanation. No function works because you are changing the variable itself b. The simplest is to make the function return the counter bb: https://ideone.com/zgsbwS

  • Thanks guys, it helped a lot!

1 answer

3


To justify this behavior it will be necessary to comment on mutable and immutable objects. In short, mutable objects allow their value to be changed, while immutable.

Its object b is the type int, which is immutable and therefore does not allow to have its value changed. But how can I do b += 1 then and increase its value? What actually happens is the creation of a new object of the type int with the value b+1 and the envelope of b original by the new object.

So why doesn’t it work in one case and not in another?

When you pass the object to the function, all this operation will occur on the object bb, which is the function parameter, existing only locally. When you do print(b), you will still be displaying the original object, no changes, so zero appears.

When you directly modify this object in the global scope, as you did in the loop for, you lose the original object reference b and will always have an "updated version" and, therefore, is displayed the value 6.

As commented, the simplest solution is you make the due counter return in function:

def how_many_integers(aa):
    bb = 0
    for i in aa:
        if isinstance(i, int):
            bb += 1
    return bb

b = how_many_integers(a)
print(b)  # 6
  • Thanks for the explanation Woss!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.