0

I am new to python. Can someone please explain to me how this works in python? How to change the value of item in the main function?

def calc(arr = []):
    index = 0
    for item in arr:
        item = item + 1
        arr[index] = item
        index += 1


if __name__ == '__main__':
    item = 1
    calc([item])
    print("item is => ", item)
Jerry Stratton
  • 3,287
  • 1
  • 22
  • 30
Aks
  • 23
  • 2
  • 1
    you can't change the value of `item` that way. Putting a variable into a list puts the value of variable, it doesn't put a reference to the variable itself. – Barmar Jan 20 '22 at 05:44
  • Python doesn't have variable references or aliases. – Barmar Jan 20 '22 at 05:45
  • 1
    Not related to your question but check ["Least Astonishment" and the Mutable Default Argument](https://stackoverflow.com/questions/1132941/least-astonishment-and-the-mutable-default-argument) about using mutable default argument – buran Jan 20 '22 at 05:46
  • `arr` is modified in the function, but since item is a simple immutable integer, it can't be modified inside the function, unless you declare `item` a global and that's not really what you want. (in fact, your code would be improved if you called a function `main()` or whatever from the `if __name__` section, instead of having the code in there, to avoid all the variable getting declared there effectively becoming globals.) – Grismar Jan 20 '22 at 05:48

2 Answers2

1

If your aim is to change an immutable value in some way, this would be best:

def add_one(value):
    return value + 1


def main():
    # your code moved to a function, to avoid these variables inadvertently becoming globals
    item = 1
    # update item with the function result
    item = add_one(item)
    print("item is => ", item)


if __name__ == '__main__':
    main()

From your example, it appears you want to update a list with each item in the list incremented by 1, you can do that the same way:

def add_one_all(values):
    return [values + 1 for values in values]


def main():
    items = [1, 4, 9]
    # update items with the function result
    items = add_one_all(items)
    print("items are => ", items)


if __name__ == '__main__':
    main()

However, since a list is mutable, you can update it from inside a function, by making the changes to the list in-place:

def add_one_all_inplace(values: list = None):
    if values is not None:
        for i in range(len(values)):
             values[i] += 1


def main():
    items = [1, 4, 9]
    # update the content of items
    add_one_all_inplace(items)
    print("items are => ", items)


if __name__ == '__main__':
    main()

The advantage of the latter solution is that no new list is created, which may be preferable if you need to be very frugal with space, or are only making a few changes to a very large list - your example would probably be better served with the second solution though.

Note that the way you called the function still wouldn't work in the latter case:

def main():
    item = 1
    add_one_all_inplace([item])

The list containing item would be changed to be [2], but that doesn't affect item itself. The list passed to add_one_all_inplace will just contain the value of item, not a reference to it.

Grismar
  • 27,561
  • 4
  • 31
  • 54
  • Thank you so much for the response. I get it now.. so when we are passing the list then it becomes mutable, but the variable inside the list is immutable.. so returning the value would change it. Thank you. I was going crazy over this. – Aks Jan 20 '22 at 07:09
  • @aks - that's about it, just remember it's the type that makes it mutable, not the fact that it was passed to a function. If you pass a list inside a list to a function, you can modify both lists and it will affect the variable outside the function, because it's the same list - but if whatever else is in those lists is immutable (like a str, int, float, tuple, etc.) those won't be modified outside the function, they can't be modified, period. The function doesn't really figure into it, it's just where it comes up most, because a new local variable (the parameter) is involved. – Grismar Jan 20 '22 at 22:46
0

you can do with the global keyword in python which allows us to use a non-global variable as global if we get an error like 'UnboundLocalError: local variable '' referenced before assignment' in that case we also use the global keyword I have done the same code with proper assignment in the below image

enter image description here

as you have declared variable in the wrong place because that would only be accessible inside the if block only so you have to place the variable at the upper level and what will happen if I don't use the global keyword see the below image

enter image description here

you can see the difference

and if you like my answer please follow me and upvote my answer