Pass List By Value

I want to pass a list to a function by value. By default, lists and other complex objects are passed to the function by reference. Here are some suggestions:

def add_at_rank(ad, rank): result_ = copy.copy(ad) .. do something with result_ return result_ 

Could this be written shorter? In other words, I want not to change the ad .

+4
source share
4 answers

You can use [:] , but for a list containing lists (or other mutable objects), you must go to copy.deepcopy() :

lis[:] equivalent to list(lis) or copy.copy(lis) and returns a partial copy of the list.

 In [33]: def func(lis): print id(lis) ....: In [34]: lis = [1,2,3] In [35]: id(lis) Out[35]: 158354604 In [36]: func(lis[:]) 158065836 

When to use deepcopy() :

 In [41]: lis = [range(3), list('abc')] In [42]: id(lis) Out[42]: 158066124 In [44]: lis1=lis[:] In [45]: id(lis1) Out[45]: 158499244 # different than lis, but the inner lists are still same In [46]: [id(x) for x in lis1] = =[id(y) for y in lis] Out[46]: True In [47]: lis2 = copy.deepcopy(lis) In [48]: [id(x) for x in lis2] == [id(y) for y in lis] Out[48]: False 
+8
source

This can be an interesting use case for the decorator function. Something like that:

 def pass_by_value(f): def _f(*args, **kwargs): args_copied = copy.deepcopy(args) kwargs_copied = copy.deepcopy(kwargs) return f(*args_copied, **kwargs_copied) return _f 

pass_by_value takes the function f as input and creates a new function _f , which deeply copies all its parameters, and then passes them to the original function f .

Using:

 @pass_by_value def add_at_rank(ad, rank): ad.append(4) rank[3] = "bar" print "inside function", ad, rank a, r = [1,2,3], {1: "foo"} add_at_rank(a, r) print "outside function", a, r 

Output:

 "inside function [1, 2, 3, 4] {1: 'foo', 3: 'bar'}" "outside function [1, 2, 3] {1: 'foo'}" 
+2
source

A shallow copy is usually good enough and potentially kneads faster than a deep copy.

You can take advantage of this if the modifications you make to result_ do not mutate the elements / attributes they contain.

For a simple example, if you have a chessboard

 board = [[' ']*8 for x in range(8)] 

You can make a shallow copy

 board2 = copy.copy(board) 

It is safe to add / insert / delete / delete / replace elements from board2 , but the lists not contained in it. If you want to change one of the rewritten lists, you must create a new list and replace existing one.

 row = list(board2[2]) row[3] = 'K' board2[2] = row 

This is a bit more work, but much more efficient in time and storage

0
source

In the case of a list of declarations, you can simply call your function as add_at_rank(ad + [], rank) .

This will create a NEW list instance each time you call the function, this value is equivalent to a declaration.

 >>>ad == ad + [] True >>>ad is ad +[] False 

Pure pythonic :)

0
source

Source: https://habr.com/ru/post/1468881/


All Articles