0

please tell me if what I am writing is correct, and if you can answer my question at the end I am very happy:

Is it correct that variables assigned to lists in python are "references" ? And the same is valid for other mutable objects (like dict but not tuples) ?

 a = [1,2,3]
 b = a
 def app(l,e):
     l += [ e ]

 app(a,5)
 print b

gives

 [1,2,3,5]

for having an assignment by value and not by reference I have to use deepcopy (from copy) ?

The problem for me is that it is very easy to introduce bugs not paying attention to this ! So i state following

QUESTION: is there any static analysis tool (like pylint or something similar) that can issue a warning for lines like b = a or app(a,5) telling me that I am potentially altering my mutable objects (lists, dictionaries) ?

Thank you

user2997356
  • 43
  • 1
  • 5
  • Not that I know of, but the rules are pretty simple once you get used to them, so as you code more, you shouldn't make this kind of mistakes anymore. See if this helps: http://bioruffo.net/lpotf/bindings-shallow-copy-deep-copy/115/ – Roberto Nov 15 '13 at 19:12
  • This thread in stackoverflow is very good: http://stackoverflow.com/questions/986006/python-how-do-i-pass-a-variable-by-reference?rq=1 – Roberto Nov 15 '13 at 19:15
  • 1
    Python is different from other languages so it's best to adapt; this is not, e.g., C/C++ where your technique is used commonly. – Simeon Visser Nov 15 '13 at 20:55

1 Answers1

0

I read the link to the question in the comments titled "How do I pass a variable by reference?" and some documentation. I believe normal Python assignments and parameter passing are technically passed by value. However, every assignment in Python automatically triggers the creation of a reference to an object. When you assigned a to b and passed a as a parameter to your function, both lines of code triggered the creation of references to the object a. The references were then passed as values to your function and to b.

Unfortunately, I do not know any static analysis tool to warn you of these rules. I admit they are confusing, but the only solution I know is to read the documentation and try to test concepts using simple code snippets. Your code is a good example from which you could deduce Python's "rules" and potential problems.

A section in Python documentation states:

"...arguments are passed by assignment in Python. Since assignment just creates references to objects..."

Further, according to an answer to "How do I pass a variable by reference?",

If you pass a mutable object into a method, the method gets a reference to that same object and you can mutate it to your heart's delight, but if you rebind the reference in the method, the outer scope will know nothing about it, and after you're done, the outer reference will still point at the original object.

In your code, l += e looks like a "rebinding" within a method and should not have modified a. However, it can be inferred that Python treated += [e] similar to .append(e). It was stated that "rebinding" a function variable to which an out-of-scope parameter was passed should not affect the passed object; despite that, a was modified by l += [e]. Thus it can be inferred that Python did not treat += [] as a rebinding. I encourage others to add links thru the comments as well, in case of new information or corrections.


NOTE: It can be helpful to use the Python id() function on a variable. It shows the integer that Python assigns to identify an object throughout the object's "lifetime". Unfortunately, I do not know the exact definition of "lifetime". You are better off asking others or reading the documentation: Python id() built-in function

Joachim Rives
  • 471
  • 6
  • 19