6 ms·
Is python no longer a modern language? Objects are certainly not copied when passed to a function.
by azundo 2y ago
Is python no longer a modern language? Objects are certainly not copied when passed to a function.
- jerf 2y agoPython copies references by value. $ python3 Python 3.12.3 (main, Jul 31 2024, 17:43:48) [GCC 13.2.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> def x(): ... v = 1 ... y(v) ... print(v) ... >>> def y(val): ... val += 1 ... >>> x() 1 A pass-by-reference language would print 2. Everything in a modern language is passed by copy. Exactly what is copied varies and can easily be pointers/references. But there were languages once upon a time that didn't work that way. It's a dead distinction now, though, unless you go dig one of them up. If you want a specific one to look at, look at Forth. Note how when you call a function ("invoke a word", closest equivalent concept), the function/word doesn't get a copy of anything. It directly gets the actual value. There is no new copy, no new memory location, it gets the actual same memory as the caller was using, and not as a "pointer"... directly. Nothing works like that any more.
- froh 2y agouh I'd not say it like that Python passes primitive types by value, out rather "as if by value", because it copies them on write. if you modify your experiment to pass around a dict or list and modify that in the 'y', you'll see y is happily modified. so Python passes by reference, however it either blocks updates (tuple) or copies on write (int, str, float) or updates in place (dict, list, class)
- js2 2y agojerf is correct. Please read this: https://stackoverflow.com/questions/373419/whats-the-difference-between-passing-by-reference-vs-passing-by-value https://stackoverflow.com/questions/373419/whats-the-differe...
- tsimionescu 2y ago> if you modify your experiment to pass around a dict or list and modify that in the 'y', you'll see y is happily modified. No, you won't. x = {'a' : 1} foo(x) print(x) def foo(z): z = {'b' : 2} You'll see that this prints `{'a' : 1}`, not `{'b' : 2}`. Python always uses pass-by-value. It passes a copy of the pointer to a dict/list/etc in this case. Of course, if you modify the fields of the z variable, as in `z['b'] = 2`, you do modify the original object that is referenced by z. But this is not pass-by-reference.
- dwattttt 2y agoIs it not pass-by-reference by some technicality? In the mutation example you suggest, if a reference to x isn't being passed into foo, how could foo modify x? I would sooner believe the example is showing you shadowing the z argument to foo, than foo being able to modify the in-parameter sometimes even if it's pass by value.
- jerf 2y ago"In the mutation example you suggest, if a reference to x isn't being passed into foo, how could foo modify x?" Because it is passing a pointer by value under the hood. This is the part that messes everyone up. Passing pointers by value is not what passing by reference used to mean. And it matters, precisely because that is extremely realistic Python code that absolutely will mess you up if you don't understand exactly what is going on. You were passed a reference by value. If you go under the hood, you will find it is quite literally being copied and a ref count is being incremented. It's a new reference to the same stuff as the passed-in reference. But if you assign directly to the variable holding that reference, that variable will then be holding the new reference. This is base level, "I'd use it on an interview to see if you really know Python", level stuff. Everything in a modern language involves passing things by value. Sometimes the language will gloss over it for you, but it's still a gloss. There were languages where things fundamentally, at the deepest level, were not passed by value. They're gone. Passing references by copy is not the same thing, and that Python code is precisely why it's not the same thing.
- 2y ago
- rtpg 2y agoC++ is a live language, C# has out parameters.... there's stuff out there. The classic example of "pass by copy-reference is less expressive" is you can't have pass a reference to number and have the caller modify it. You have to explicitly box it. I understand you understand this, but it's worth considering when thinking about whether the distinction means absolutely nothing at all.
- tsimionescu 2y ago> The classic example of "pass by copy-reference is less expressive" is you can't have pass a reference to number and have the caller modify it. This is really not true. Depending on how your language implements pass-by-reference, you can pass a reference to an int without boxing in one of two ways: either pass a pointer to the stack location where the int is stored (more common today), or simply arrange the stack in such a way that the local int in the caller is at the location of the corresponding parameter in the callee (or in a register). The second option basically means that the calling convention for reference parameters is different from the calling convention for non-reference parameters, which makes it complicated. It also doesn't work if you're passing a heap variable by reference, you need extra logic to implement that. But, for local variables, it's extremely efficient, no need to do an extra copy or store a pointer at all.
- rtpg 2y agoHmmm... yeah that's a good point. Though I would contend that the fact that languages do not do this is indicative of... something.
- tsimionescu 2y agoI would guess that the main reason is that the on-stack way only works for local variables. If you want to pass anything else by reference, you need to use some kind of address to it, since it's not in the caller's stack anyway.