简体   繁体   中英

Elegant way to modify a list of variables by reference in Python?

Let's say I have a function f() that takes a list and returns a mutation of that list. If I want to apply that function to five member variables in my class instance (i), I can do this:

for x in [i.a, i.b, i.c, i.d, i.e]:
    x[:] = f(x)

1) Is there a more elegant way? I don't want f() to modify the passed list.

2) If my variables hold a simple integer (which won't work with the slice notation), is there also a way? (f() would also take & return an integer in this case)

Another solution, though it's probably not elegant:

for x in ['a', 'b', 'c', 'd', 'e']:
    setattr(i, x, f(getattr(i, x)))

Python doesn't have pass by reference. The best you can do is write a function which constructs a new list and assign the result of the function to the original list. Example:

def double_list(x):
    return [item * 2 for item in x]

nums = [1, 2, 3, 4]
nums = double_list(nums) # now [2, 4, 6, 8]

Or better yet:

nums = map(lambda x: x * 2, nums)

Super simple example, but you get the idea. If you want to change a list from a function you'll have to return the altered list and assign that to the original.

You might be able to hack up a solution, but it's best just to do it the normal way.

EDIT

It occurs to me that I don't actually know what you're trying to do, specifically. Perhaps if you were to clarify your specific task we could come up with a solution that Python will permit?

Ultimately, what you want to do is incompatible with the way that Python is structured. You have the most elegant way to do it already in the case that your variables are lists but this is not possible with numbers.

This is because variables do not exist in Python. References do. So ix is not a list, it is a reference to a list . Likewise, if it references a number. So if ix references y , then ix = z doesn't actually change the value y , it changes the location in memory that ix points to.

Most of the time, variables are viewed as boxes that hold a value. The name is on the box. In python, values are fundamental and "variables" are just tags that get hung on a particular value. It's very nice once you get used to it.

In the case of a list, you can use use slice assignment, as you are already doing. This will allow all references to the list to see the changes because you are changing the list object itself. In the case of a number, there is no way to do that because numbers are immutable objects in Python. This makes sense. Five is five and there's not much that you can do to change it. If you know or can determine the name of the attribute, then you can use setattr to modify it but this will not change other references that might already exist.

As Rafe Kettler says, if you can be more specific about what you actually want to do, then we can come up with a simple elegant way to do it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM