This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author asdfasdfasdfasdfasdfasdfasdf
Recipients Theo.Julienne, asdfasdfasdfasdfasdfasdfasdf, benjamin.peterson, giampaolo.rodola, loewis, r.david.murray, rhettinger
Date 2010-08-28.05:05:17
SpamBayes Score 0.0
Marked as misclassified No
Message-id <AANLkTimGmRNu=Erq5uK-Rz1T-xT0D_sSNfOPnyFtz2Sv@mail.gmail.com>
In-reply-to <1282950613.94.0.212653213805.issue9702@psf.upfronthosting.co.za>
Content
On 28 August 2010 09:10, Theo Julienne <report@bugs.python.org> wrote:
>
> Theo Julienne <theo.julienne@gmail.com> added the comment:
>
> def list_again(foo):
>        foo.append("bar")
>
> def list_again_again(foo):
>        foo = foo + ["1"]
>
>
> The part that can be confusing is that 'foo' is a *copy* of a *reference* to an object. Because 'foo' is a copy, assigning to it will only alter a local copy, while calling methods on it will always call on the original object (because it's a reference to the same place). When an object is mutable, it just has no methods that modify it, so the only way to change it is by assignment, which will never result in changes to the outside function.

Yes exactly!

>There are no special cases, but it does require understanding pass-by-(copy/reference) and object mutability, and is against most people's intuitions.

No that isn't really my point here really.

> The way that behaves is actually how most *programmers* would expect (because they are used to it), though. Every other language I can think of does it this way. For example, in C, a pointer is still a copy of a reference -- if you assign to the pointer, it wont propagate up to the caller. The same goes in Java.

Um sort of. This is kind of confusing right see the code below.

> Perhaps what makes it harder to understand in Python is that everything is an object and looks the same regardless of mutability, whereas other languages typically have conventions (such as capitalising: int, str, Dict, List) to make it clearer when something is an object (which usually means the same as a python mutable object) as opposed to a built-in type (which usually means the same as a python immutable object).

I actually think the problem is that python coders are not aware of
this largely (from my experience) and that the *operators* are going
to behave differently (java, for example,  differs in this respect (
you don't '+' maps )).

Here are some examples of use in other languages. Mapping python can
be found some of them.

foo.cpp
#include <iostream>
#include <string>
using namespace std;

void do_More_Foo(int *it);

int main()
{
	int *foo;
	int bar = 0;
	foo = &bar;
	cout << *foo << " "  << foo << endl;
	do_More_Foo(foo);
	cout << *foo << " "  << foo << endl;
	return 0;
}

void do_More_Foo(int *it)
{
	cout << "do more foo " << it << " " << *it <<endl;
	*it = 9;
}

g++ -Wall -Werror foo.cpp  -lmudflap -fmudflap
./a.out
0 0x7fff0ec19adc
do more foo 0x7fff0ec19adc 0
9 0x7fff0ec19adc

AND in python:
#!/usr/bin/env python

def do_More_Foo(it):
	print "in do_More_Foo"
	print "foo", foo, id(foo), id(foo[0])
	print "it", it, id(it)
	it.pop()
	it.append("9")

if __name__ == "__main__":
	bar = 0
	foo = [bar]
	print id(bar)
	print id(foo[0])
	print foo, id(foo)
	do_More_Foo(foo)
	print "after do_More_Foo", foo, id(foo), id(foo[0])

output:
16307968
16307968
[0] 140400602766512
in do_More_Foo
foo [0] 140400602766512 16307968
it [0] 140400602766512
after do_More_Foo ['9'] 140400602766512 140400602799200

However, this isn't what you expect people to do.
Oh and how did foo get there ;) (surprise! python isn't simple is it ?
- note the id).

So I think most people are going to think about this and write it like this:
#!/usr/bin/env python

def woops(it):
	# erh make foo = 9 ?
	print "foo", foo, id(foo)
	foo = 9
	print "foo", foo, id(foo)

def do_More_Foo(it):
	print "in do_More_Foo"
	print "foo", foo, id(foo)
	print "it", it, id(it)
	it = 9
	print "it", it, id(it)

if __name__ == "__main__":
	foo = 0
	print foo, id(foo)
	do_More_Foo(foo)
	print "after do_More_Foo", foo, id(foo)
	woops(foo)
	print "after do_More_Foo", foo, id(foo)

output:
0 19838720
in do_More_Foo
foo 0 19838720
it 0 19838720
it 9 19838504
after do_More_Foo 0 19838720
foo
Traceback (most recent call last):
  File "python-cpp2.py", line 21, in <module>
    woops(foo)
  File "python-cpp2.py", line 5, in woops
    print "foo", foo, id(foo)
UnboundLocalError: local variable 'foo' referenced before assignment

As you expect it is not the foo you are looking for ;)

foo.java

import java.util.HashMap;

import javax.print.DocFlavor.STRING;

public class foo
{

	public void bar(HashMap<String, String> z)
	{

		z.put("foo", "bar");
		HashMap<String, String> b = z;
		b.put("foo2", "ba2r");
	}

	void magic(String b)
	{
		String c = b;
		b = b.replace('b', 'c');
		System.out.println(c);
		System.out.println(b);
	}

	void moremagic(StringBuilder z)
	{
		z.append("b");
	}
	public static void main(String[] args)
	{
		HashMap<String, String> baz = new HashMap<String, String>();
		foo myfoo = new foo();
		myfoo.bar(baz);
		System.out.println(baz.toString());
		String aaa = "b";
		myfoo.magic(aaa);
		System.out.println(aaa);
		StringBuilder sb = new StringBuilder();
		myfoo.moremagic(sb);
		System.out.println(sb);
	}

}
java foo
{foo2=ba2r, foo=bar}
b
c
b
b

#!/usr/bin/env python

def bar(a_dict):
	a_dict["foo"] = "bar"
	new_dict = a_dict
	a_dict["foo2"] = "ba2r"

def magic(string_b):
	c = string_b
	string_b = string_b.replace('b', 'c')
	print c
	print string_b

def moremagic(list_s):
	list_s.append("b")

if __name__ == "__main__":
	d = dict()
	bar(d)
	print d
	aaa = "b"
	magic(aaa)
	print aaa
	a_list = []
	moremagic(a_list)
	print a_list[0]

python python-java.py
{'foo': 'bar', 'foo2': 'ba2r'}
b
c
b
b

- no problems here :)  - but in python we can use an operator like '+'
on a list which introduces the very confusion I am talking about in
respect to the differing behaviour as I stated at the top of this bug
report. :)
History
Date User Action Args
2010-08-28 05:05:26asdfasdfasdfasdfasdfasdfasdfsetrecipients: + asdfasdfasdfasdfasdfasdfasdf, loewis, rhettinger, giampaolo.rodola, benjamin.peterson, r.david.murray, Theo.Julienne
2010-08-28 05:05:24asdfasdfasdfasdfasdfasdfasdflinkissue9702 messages
2010-08-28 05:05:18asdfasdfasdfasdfasdfasdfasdfcreate