7 ms·
Is Python call-by-value or call-by-reference? Neither.
- manojlds 14y agoIsn't this by definition call by value? The reference / binding is passed by value. Changing the reference to point to something else will not make the other reference to point to the same too.
- jknupp 14y agoCall by value would mean that a copy of the value of the argument is passed to the function without involving the original value at all. To say the binding is passed by value is not useful, as all languages would then be considered "call by value", since _something_ needs to be passed into the function, and we can just call it a value.
- viraptor 14y agoThis argument is as old as call-by-... definitions, but... What python holds in the variables are references to objects. Those are the values you're passing, so it's call by value using this reasoning. Some languages do actually hold the value itself (struct for example) in the variable, so there you get a copy of the value (the struct contents). In python you get the copy of a reference (which again, is the value held in a variable).
- lvh 14y agoThat is correct: the object reference is copied into the caller's symbol table when calling. Hence, CBV.
- adrusi 14y agonot true. the program can be compiled to directly reference the variables themselves
- mistercow 14y agoPedantically, sure, but I think the point is to explain it so that people actually understand. If you say "Python is call-by-value" to C programmer then they will probably have some serious misconceptions about what happens when you pass an object to a function.
- irahul 14y ago> they will probably have some serious misconceptions about what happens when you pass an object to a function. p = Person() The thing on the left is object reference, the thing on the right is object. When you do some_func(p) or some_func(Person()), you don't pass an object but an object reference. There. No serious misconceptions. C# and Java are doing just fine having the same model and explaining it the same way. And C programmers just need to think of `p = Person()` as `Person *p = new_person()`
- mistercow 14y ago>There. No serious misconceptions. Well, yes, there might be. Because "object reference" sounds a lot like you're saying it's call-by-reference, and that's also confusing. it makes it sound like the output of this would be "overwritten": def some_func(x): x = "overwritten" p = Person() some_func(p) print p In addition, my point was that using the term "call-by-value" is confusing, and since you didn't use that term in your explanation, it's all moot.
- irahul 14y agoMy point is writing a blog post saying python is neither call-by-value nor call-by-reference is made up shit and does nothing for someone who doesn't already understand it. Someone who doesn't already understand it will have to work through to get the gist of call-by-value and object references. The blog post didn't simplify anything for someone who doesn't already understand it. So why not stick with terminology which is used by Java, C#, C among others?
- mistercow 14y ago
- Jach 14y agoWrong. It's call-by-value, the confusion comes from what, in Python, is considered a value (and when a value is mutable, which is always (with a little ctypes magic), even the built-in number 4). And just like in Java, which also is always call-by-value, Python passes pointers-by-value under the hood which allows for some easy modification. There is an easy test to see if a language supports call-by-reference or not: a = 3 b = 4 swap(a,b) print a, b # 4 3 C++ can do this, C can't, C# can't (if you think it can, then so can C), Python can't, Java can't. Therefore, all of those but C++ are call-by-value in all cases. Edit: I hasten to add, the swap() function should be implemented "traditionally". i.e.: def swap(x, y): temp = x x = y y = temp
- tonetheman 14y agoyup yup this post is right!
- jknupp 14y agoTo say that because Python passes pointers-by-value under the hood (which is true for cpython, but not other implementations) is not useful. "Call by value" and "Call by reference" have reasonably precise definitions, and Python fits neither. See http://en.wikipedia.org/wiki/Call_by_sharing#Call_by_sharing http://en.wikipedia.org/wiki/Call_by_sharing#Call_by_sharing for a discussion of the difference.
- lvh 14y agoImplementation details don't really matter: it's about how the language behaves (as is demonstrated by the SWAP litmus test). That implementations may do other things (generally for performance reasons, such as PyPy's function inlining) is irrelevant: those performance optimizations are not allowed to (noticeably) change semantics.
- Jach 14y agoWhat do other Python implementations use? If it's something that indirectly keeps track of data location it's a pointer. The actual implementation of the pointer doesn't matter. "Call-by-object-sharing" is better expressed as "call-by-object-pointer-value". But at this point it's just an argument over definitions. One either accepts that call-by-reference and call-by-value are the only two options along with the test above that includes C++, Ada, and Pascal as languages which support call-by-reference, or one doesn't.
- adrusi 14y agothis is over complicating the model to avoid saying what for some reason people are terrified to say: that objects are just pointers. when you pass an object you are passing the value of a reference. it's not that scary
- jknupp 14y agoThat's confusing the language specification with one of its implementations. In Jython, for example, objects are not "just pointers".
- adrusi 14y agono, they are still just pointers. they might be pointers to something fancier than a struct of its instance variables and abstracted by java's object system but in the end it's still a pointer
- herge 14y agoI have the impression than anyone who has issues with this never experienced programming in assembly.
- lvh 14y agoHow is this different from call-by-value, where all values are object references?
- masklinn 14y agoIt's not, it's call-by-value-but-some-people-can't-accept-it
- rmc 14y agoI highly recommend this site: http://pythontutor.com/ http://pythontutor.com/ It'll parse and execute python code, including showing what variables are pointing to what obects.
- alphaBetaGamma 14y agoI have a C based mental model of what is happening. Can anyone comment on whether it is correct? In C terms, I think of all objects (including primitives such as numbers) as a struct with a void* pointer that holds the actual data, and another field that describes how to interpret the data: struct Obj { void* data; ObjDesc descr; } Whenever you do objA=objB you create an new struct Obj with objA.data == objB.data. The same things happens when you pass an object to a function: you create a copy of the Obj. When you modify an Obj, two things can happen: if the Obj is immutable you change where void* data points to: n1 = 4 n2 = b1 n1 = 5 ==> n1.data != n2.data On the other hand, if Obj is mutable, than you don't change void* data, you modify the memory pointed to by data: n1=[] n2=n1 n1.append(1) ==> n1.data == n2.data Is this correct or is mental model going to bite me sometime?
- irahul 14y agoThat is more or less correct. It isn't exactly what happens, but the mental model is correct.
- void-star 14y agoThis is really far off, actually. I don't mean to criticize. I think the best advice is to read K&R C again. And, as some other posters have suggested, take a look and at least a passing understanding of the memory model and assembly code generated by C/C++ compilers. You'll see, for instance, that type information is not stored as a field in a C struct at all, it's purely a distinction for the compiler to use. A C struct, indeed any type of data in C, is _just_data_ in memory. At the machine level, there's no such thing as a type. Just registers, memory, and instructions. The compiler uses type information to generate the right instructions to handle the type. And to clarify, type metadata _as_actual_data_ can exist in higher level languages, but it's definitely not a C thing.
- alphaBetaGamma 14y agoI was speaking of a model of how python does things, based on a C style implementation. Not an explanation of how C works.
- InclinedPlane 14y agoPython is a truly bizarre language in this regard. It's behavior is unusual and similar only to a few other less well known niche languages such as C# and Java.
- irahul 14y agoYou might want to add /s http://en.wikipedia.org/wiki/Poes_law http://en.wikipedia.org/wiki/Poes_law
- pdw 14y agoI wish all this "call by x" terminology would just disappear. It's fine if you're discussing ALGOL-60 dialects, which by modern standards were all horribly confused about parameter passing (call by name, anyone?). It's just not helpful at all when discussing modern languages. If we have to keep it, I vote for Kent Pitman's suggestion of "call by identity". (I can't find the reference right now.)
- barrkel 14y agoThe usual phrase I've seen to describe this is "passes references by value". And it's the norm in almost all popular OOP languages since the mid-90s.
- sirclueless 14y agoI like to think of this as "call-by-name". That's because every name in python is actually a lookup in a dictionary mapping strings to values. This is different from languages like C# and Java where some things such as class and function references can actually be thought of as "values". In python, everything that isn't a keyword or a literal is a name, thinking otherwise leads to gotchas.
- pdw 14y agoThe term call-by-name already exists and means something entirely different. It will blow your mind. http://www.cs.sfu.ca/~cameron/Teaching/383/PassByName.html http://www.cs.sfu.ca/~cameron/Teaching/383/PassByName.html
- mistercow 14y agoSince you explained name binding anyway, a useful way to describe Python might just be "call-by-binding".
- skittles 14y agoI'm a C# developer who also programmed in Java in the past. C# and Java both pass pointers by value (which is what Python does too). This is a very important thing to learn when programming C# or Java. A method (or function) in any of these languages can either manipulate the object that the reference points to, or they can reassign the reference to a new object internally (which will leave the original object alone).
- mattdeboard 14y agoWell, regardless of the call-by-x discussion, this is actually a really good explanation of scope and state in Python. Code like: def grow(array): array.append(1) array = [] grow(array) leads to such needless complexity.
- mistercow 14y agoA lot of comments here are talking about how it's "really" just call-by-value. I want to explain why this is unproductive. First, let's acknowledge that the context we're discussing is explaining to someone new to Python how Python works with function arguments. Now, if someone asks if lead-acid batteries work using chemistry, and you say "they use physics", then they will probably end up with a fairly inaccurate picture of how lead-acid batteries work. What you've told them is technically correct, but it isn't practically useful. It is the same if someone asks how Python passes arguments to functions and you say "it's pass-by-value". You've told them something technically correct, but they're going to think inaccurate things like that passing an object to a function copies all of the object's properties like a struct in C. Even if you say "it's pass-by-value but the values are not what you think", you haven't actually added to their understanding by that phrase. You're better off explaining conceptually how it works, describing it as "call-by-sharing", and then explaining what that means. It will signal their brain to allocate space for a new concept, and not to drag in erroneous ideas from existing concepts. After they understand how it works, you can explain that call-by-sharing is actually just a spoonful of sugar to help the call-by-value go down. Here's the thing: words are there to help us communicate. If you use a word in a way that is technically correct but conveys the wrong idea to your listener, you're doing it wrong. Here's the other thing: this is computer science. In computer science, as in all math, you often encounter a concept that is "really just" some other concept. When you come to that realization about a concept that you understand superficially, it can be transformative, taking you to a deeper level of comprehension. When someone asks you about the concept, you'll want to share that deep comprehension with them, so it's natural to want to jump right into it and explain it by connecting it to the general case. But they will not understand if you do that. You can't teach someone addition by starting with ring theory, after all.
- timmclean 14y agoSure, but I think it's still possible to explain something well without being inaccurate.
- mistercow 14y agoI agree if you're starting with a blank slate. If someone asks "How does Python handle arguments", then you can just omit any mention of call-by-value until they understand the concept, and have total accuracy the whole time. But if they come to you with "Is Python call-by-value or -reference?", then for the sake of getting them to break away from those contexts, I think your best bet is to say "neither", which is technically-but-not-practically slightly inaccurate. You could try saying "It's technically call-by-value but you seriously need to forget everything about call-by-value in this context until I explain it to you," but depending on how their mind works, they may be looking for the connection to call-by-value the whole time you explain it (certainly that's what my mind would do if it were explained that way). And that's just a distraction. So as long as you tell them at the end, "OK, so technically I lied earlier; this is call-by-value, but that's not how it's understood conceptually", I think the marginally inaccurate route is better.
- brabbins 14y agoPerhaps this is a digression, but there are some misunderstandings in this blog post about the memory model in his C++ example. Since the author goes to lengths to be precise and exact in terminology and his explanations, it would be good to clarify some things. For the example code C++ given: string some_guy = "Fred"; // ... some_guy = "George"; Here is the author's explanation: In the above, the variable some_guy refers to a location in memory, and the value 'Fred' is inserted in that location (indeed, we can take the address of some_guy to determine the portion of memory to which it refers). Later, the contents of the memory location referred to by some_guy are changed to 'George'. The previous value no longer exists; it was overwritten. This likely matches your intuitive understanding (even if you don't program in C++). There are several incorrect statements here. A. "the variable some_guy refers to a location in memory, and the value 'Fred' is inserted in that location" Not true. The variable some_guy refers to a location in memory, but that location contains a pointer to a region of memory with the value "Fred". More on this in a bit. B. "indeed, we can take the address of some_guy to determine the portion of memory to which it refers". Again, not true in the way the author probably intended. The address of 'some_guy' will be the address on the stack where the variable is located. The value at that address on the stack will be a pointer to a separate region of memory containing "Fred". C. "Later, the contents of the memory location referred to by some_guy are changed to 'George'." To be precise, the contents of the memory location referred to by some_guy are changed to a new pointer to a different region of memory containing "George". D. "the previous value no longer exists; it was overwritten." The values "Fred" and "George" exist through the entire lifetime of the program. They are string constants, which are compiled in to the data section of the program binary. The author is correct on one point: the value of 'some_guy' is overwritten during the reassignment. However, the value in this case is simply a pointer, not a string. We can verify my claims experimentally. On my system (Ubuntu 11.04 32-bit, g++ 4.5.2), I wrote the following test program: //a.cpp #include <string> using namespace std; int main() { string some_guy = "Fred"; some_guy = "George"; return 0; } Compile like this: $ g++ -O0 a.cpp -o a Now, we can disassemble the "main" function to see exactly what is going on in the executable: $ objdump -d a a: file format elf32-i386 ... 08048614 <main>: 8048614: 55 push %ebp 8048615: 89 e5 mov %esp,%ebp 8048617: 83 e4 f0 and $0xfffffff0,%esp 804861a: 53 push %ebx 804861b: 83 ec 2c sub $0x2c,%esp 804861e: 8d 44 24 1f lea 0x1f(%esp),%eax 8048622: 89 04 24 mov %eax,(%esp) 8048625: e8 06 ff ff ff call 8048530 <_ZNSaIcEC1Ev@plt> 804862a: 8d 44 24 1f lea 0x1f(%esp),%eax 804862e: 89 44 24 08 mov %eax,0x8(%esp) 8048632: c7 44 24 04 80 87 04 movl $0x8048780,0x4(%esp) 8048639: 08 804863a: 8d 44 24 18 lea 0x18(%esp),%eax 804863e: 89 04 24 mov %eax,(%esp) 8048641: e8 ca fe ff ff call 8048510 <_ZNSsC1EPKcRKSaIcE@plt> 8048646: 8d 44 24 1f lea 0x1f(%esp),%eax 804864a: 89 04 24 mov %eax,(%esp) 804864d: e8 ce fe ff ff call 8048520 <_ZNSaIcED1Ev@plt> 8048652: c7 44 24 04 85 87 04 movl $0x8048785,0x4(%esp) ... In this case, we are interested in the following two lines: 8048632: c7 44 24 04 80 87 04 movl $0x8048780,0x4(%esp) and 8048652: c7 44 24 04 85 87 04 movl $0x8048785,0x4(%esp) 0x4(%esp) is the address on the stack of our 'some_guy' variable. We are moving an "immediate" (constant) value into that location. What does that immediate refer to? Again, let's find out experimentally: $ objdump -s -j .rodata a a: file format elf32-i386 Contents of section .rodata: 8048778 03000000 01000200 46726564 0047656f ........Fred.Geo 8048788 72676500 00000000 rge..... Notice that the address of "Fred" is 0x8048778 + 8 = 0x8048780, which is exactly the immediate value from the disassembled main function. This means that our variable "some_guy" really is a pointer, and nothing more. The strings "Fred" and "George" are statically allocated in the data section of the binary, meaning they stick around indefinitely.
- tsuyoshi 14y agoI'm not too familiar with Python, but the semantics of Python described here match every other language that I can think of (including C). Can anyone give me an example of a language that is actually call-by-reference?
- Jach 14y agoC++ supports call-by-reference (and also call-by-value), here's an example of call-by-reference: #include <iostream> void swap(int &x, int &y) { int temp = x; x = y; y = temp; } int main() { int a = 3; int b = 4; std::cout << a; // 3 std::cout << b; // 4 swap(a, b); std::cout << a; // 4 std::cout << b; // 3 }
- jsnell 14y agoPerl.
- pierrebai 14y agoPython is strictly a call-by-ref language. The author of the blog and many commenter here seem confused. There are two causes: 1. Some objects are immutable. This makes some calls seem to be call-by-value, but they are not. A simple look at the generated code makes this obvious. Integers, strings, tuples, ... are passed by reference. It's just that you can't mutate the object being passed. 2. The behaviour of the assignment operator is different from most non-functional language. In Python, assignment never mutate values. It assign a new reference to the 'variable' (i.e. the scoped name). This explains clearly why in functions, you can't mutate an immutable object even though it is passed by reference: assignment merely rebind the argument name to a new value. That is why when you want to mutate something in a function in Python, your only recourse is to call a function on that object: i = 4 s = 'George' l = [ 'me', 'you'] foo (i, s, l) def foo(a, b, c): a = 3 b = 'Mark' c.append( 42 ) c = [ 2, 1 ] print(i, s, l) # prints 4, 'George', ['me', 'you', 42]
- mistercow 14y agoWhile Python works by passing object references, it is not call-by-reference as that term is usually understood. Call-by-reference means that assignment within a function will be seen in the calling scope. That does not happen in Python.