python list mutation in loops, global modifying vs. local modifying -
halp, perhaps more experienced python can answer (noobish) question.
i'm having trouble figuring out why following behavior occurs lists.
let's have following functions:
def foo1(l): """ l list """ l = ['new', 'stuff'] print l def foo2(l): """ l list """ l[:] = ['new', 'stuff'] print l
idle outputs following:
>>>l = [1,2,3] >>>foo1(l) ['new', 'stuff'] >>>l [1,2,3] >>>foo2(l) ['new', 'stuff'] >>>l ['new', 'stuff']
i can't figure out why first function temporarily modifies list, second modifies list globally. don't think it's scope issue, rather issue l= versus l[:]=
i know if use list comprehension change l or use l.append() or other method mutate l within function, modifies l globally, too.
i'm not new python, but, usually, google solutions problems when coding, and, if works, don't question it. i'm taking time summer learn best-practices , @ meat of python.
edits: martijn decided mark question duplicate, disagree. linked question not address question.
when variable passed function, function creates new environment own scope. variables in environment exist in scope of environment, , else. hence, when list l passed both foo1 , foo2, temporary list, l, made within scope of function call. in other words, prior calling foo1(l), there exists list named l equal [1,2,3]. after call foo1(l), new function environment made, , contains temporary list, called l, lives in scope of function. if modify l via l = [blah, blah, blah] within function, nothing happens original list l. however, using [:] on l within function, original list modified. why? how python know after has created temporary variable limited scope, needs modify original 1 global scope? concept not make sense me.
both argument l , global variable l refer same objects in memory. when pass object reference global object since how references , assignment work in python. when ['new', 'stuff']
in foo1
assign value l
local copy i.e. argument since first lookup assignment. on doing l[:] = ['new', 'stuff']
in foo2
doing slice affects global variable.
you can test checking id same both global , parameter l
.
l = [1, 2, 3] b = l id(b) == id(l) # true def foo(l): print(id(l) == id(b)) foo(l) # true # or.. def foobar(l): print(id(locals()['l']) == id(globals()['l']))
hope helps. :)
Comments
Post a Comment