Pass list to function by value

后端 未结 4 1680
南旧
南旧 2020-12-06 18:24

I want to pass a list into function by value. By default, lists and other complex objects passed to function by reference. Here is some desision:

def add_at_         


        
相关标签:
4条回答
  • 2020-12-06 18:53

    In case of ad is list you can simple call your function as add_at_rank(ad + [], rank).

    This will create NEW instance of list every time you call function, that value equivalented of ad.

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

    Pure pythonic :)

    0 讨论(0)
  • 2020-12-06 18:58

    This might be an interesting use case for a decorator function. Something like this:

    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 a function f as input and creates a new function _f that deep-copies all its parameters and then passes them to the original function f.

    Usage:

    @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'}"
    
    0 讨论(0)
  • 2020-12-06 19:15

    A shallow copy is usually good enough, and potentially mush faster than deep copy.

    You can take advantage of this if the modifications you are making to result_ are not mutating the items/attributes it contains.

    For a simple example if you have a chessboard

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

    You could make a shallow copy

    board2 = copy.copy(board)
    

    It's safe to append/insert/pop/delete/replace items from board2, but not the lists it contains. If you want to modify one of the contianed lists you must create a new list and replace the existing one

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

    It's a little more work, but a lot more efficient in time and storage

    0 讨论(0)
  • 2020-12-06 19:17

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

    lis[:] is equivalent to list(lis) or copy.copy(lis), and returns a shallow 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
    
    0 讨论(0)
提交回复
热议问题