Re: Finding the instance reference of an object
greg [EMAIL PROTECTED] writes: Steven D'Aprano wrote: At least some sections of the Java community seem to prefer a misleading and confusing use of the word value over clarity and simplicity, but I for one do not agree with them. I don't see anything inherently confusing or misleading about it. Confusion only arises when some people jump up and say that it's wrong to use the terms that way, because it might cause confusion... Personally, I find this whole debate kind of silly, as it is based on a completely fallacious either/or dichotomy. (1) It is unarguably true that Python and Java use a type of call-by-value. This follows from the standard definition of call-by-value, and common usage in, for example, the Scheme and Java communities, etc. (2) It is also unarguably true that saying that Python or Java use call-by-value, and saying nothing more is going to be profoundly confusing to anyone who is learning these languages. It's like the difference between Q. What is a giraffe? A. A giraffe is a type of animal. and Q. What is Greg? A. Greg is a type of animal. In both cases, the answers are strictly correct, but in the second case, the answer is also deeply misleading. Q. How do we generally solve this problem when speaking? A. We invent more specific terms and then generally stick to the more specific terms when the more general terms would be misleading. I.e., Q. What is Greg? A. Greg is a human being. and Q. What type of calling semantics do Python and Java use? A. Call-by-sharing. I assert that anyone who does not understand all of the above, is helping to spread confusion. |oug -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
On Nov 19, 2008, at 11:05 AM, Douglas Alan wrote: Personally, I find this whole debate kind of silly, as it is based on a completely fallacious either/or dichotomy. (1) It is unarguably true that Python and Java use a type of call-by-value. This follows from the standard definition of call-by-value, and common usage in, for example, the Scheme and Java communities, etc. True. (2) It is also unarguably true that saying that Python or Java use call-by-value, and saying nothing more is going to be profoundly confusing to anyone who is learning these languages. Perhaps (unless they've already learned this from one of the other languages). Q. How do we generally solve this problem when speaking? A. We invent more specific terms and then generally stick to the more specific terms when the more general terms would be misleading. I.e., Q. What is Greg? A. Greg is a human being. and Q. What type of calling semantics do Python and Java use? A. Call-by-sharing. Fair enough, but if the questioner then says WTF is call-by-sharing, we should answer call-by-sharing is the term we prefer for call-by- value in the case where the value is an object reference (as is always the case in Python). I assert that anyone who does not understand all of the above, is helping to spread confusion. I agree. Best, - Joe -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
I've just come to the conclusion it's not possible to call functions in python, to do so is undefined and indeterminate, like dividing by zero. Henceforth no calling functions for me as clearly it's the devil's playground. -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
On Nov 19, 12:28 pm, Joe Strout [EMAIL PROTECTED] wrote: On Nov 19, 2008, at 11:05 AM, Douglas Alan wrote: (2) It is also unarguably true that saying that Python or Java use call-by-value, and saying nothing more is going to be profoundly confusing to anyone who is learning these languages. Perhaps (unless they've already learned this from one of the other languages). If they learn the bad definition first, we can't go back and change it. We can correct it for them for the future. Don't appeal to hot- shot authorities, like the ones that don't acknowledge that there were already people using terms they hijacked for their own cult following. Q. What type of calling semantics do Python and Java use? A. Call-by-sharing. Fair enough, but if the questioner then says WTF is call-by-sharing, we should answer call-by-sharing is the term we prefer for call-by- value in the case where the value is an object reference (as is always the case in Python). But if someone says, 'What is call-by-reference?', do you answer, 'C-b- r is the term we prefer for call-by-value in the case where the value is a variable reference'? -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
Joe Strout [EMAIL PROTECTED] writes: Q. What type of calling semantics do Python and Java use? A. Call-by-sharing. Fair enough, but if the questioner then says WTF is call-by-sharing, we should answer call-by-sharing is the term we prefer for call-by- value in the case where the value is an object reference (as is always the case in Python). Personally, I think that it is much preferable to leave call-by-value completely out of any such discussion, as it provably leads to a great deal of confusion and endless, pointless debate. It's better to just start from a clean slate and explain how call-by-sharing works, and to assert that it is quite different from the calling semantics of languages such as C or Pascal or Fortran, so the student must set aside any preconceptions about how argument passing works. Call-by-sharing is technically a type of call-by-value only for those who are devotees of academic programming language zoology. For everyone else, call-by-sharing is its own beast. One might point all of this out in the discussion, however, if it will help the other person understand. You never know -- they might be a fan of academic programming zoology. |oug -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
arguably even older than that to Lisp. Firstly, thanks to those that have responded to my part in this debate, I have found it very informative and interesting as I have the entire thread. However, with regard to comments that I led myself astray, I want to reiterate the one thing I find determinably important in this... I did not go astray because I did not fret what the words meant and try to draw anything from that. I learned exactly what would happen when I passed arguments different ways, and I learned that well and accurately. Then I mused what to call it all. At no time was I astray because I think to really be astray would be to have a misunderstanding on what happens, not on what we call what happens. but I will concede that trying to use call-by-name is not a viable idea as it's yet another term that is already taken. I did not think too hard what the distinction is, and as far as I know it's as good a candidate for what we call it as anything else, but I certainly don't want to fight for the term. Whatever we call the passing semantics and methods in Python... it will not change what I understand about what happens with certain kinds of calls vs others. cheers. -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object [long and probably boring]
greg wrote: Arnaud Delobelle wrote: But in the course of conversation I might refer to Napoleon, meaning Napoleon Bonaparte (1769 - 1821) or Napoleon III (1808 - 1873). That's more like referring to the name 'Napoleon' in two different namespaces. The original binding still exists, you're just switching contexts. My point was to get away from a model for Python which was built on its likely implementation and to hint that we can build one using the naive concept of 'name for a thing' instead. I don't believe it's possible to build any complete and correct model of Python behaviour without including some concept equivalent to a reference. You can talk about names written on PostIt notes and such like, but that only gets you a short way. It doesn't easily handle names in different namespaces, or references that exist without simple names, e.g. list and tuple items. Trying to repair these deficiencies only leads to increasingly bizarre and contrived mental pictures. +1 On the other hand, if you explicitly include the concept of a reference from the beginning, everything is quite clear and consistent. Yes. References do explain things very well, since the model is in exact agreement with the reality of the implementation. In other words, the model should be as simple as possible but no simpler. Leaving out references makes it too simple. Another point I'd like to make is that there is nothing inherently low-level about the concept of a reference. It doesn't have to be implemented as a memory address or any other particular machine-level thing. It's possible to talk about Python object references in a completely implementation-independent way. Indeed one might make use of some object store, and references would still be useful even if they weren't memory addresses. Also, just because you don't explicitly refer to them and manipulate them at the language level doesn't mean they don't exist. To think otherwise is like thinking that air doesn't exist just because you can't see it. There are plenty of experiments which clearly indicate its existence. Likewise, there are plenty of experiments that you can perform with any Python interpreter that reveal the existence of references, or something equivalent to them. Good stuff. I have come to the conclusion that this thread is mostly best left alone, since the remaining participants appear to have agreed on Python's semantics and now continue to argue about what name should be used to describe them. regards Steve -- Steve Holden+1 571 484 6266 +1 800 494 3119 Holden Web LLC http://www.holdenweb.com/ -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
Steven D'Aprano wrote: If you equate arguments within the called procedure to the *name* of the arguments, then changing the arguments would mean changing the NAME If changing the name means rebinding the name, then I agree -- that's exactly the point I was trying to make. If you equate value with object, as you suggested some posts ago, *I* didn't suggest that, someone else did. I was just pointing out that you can use the word that way if you want, as long as you're consistent about it. And being consistent means using it in the same way when talking about assignment and about by-value parameter passing. If you insist that one of these implies copying the value but the other doesn't, then you're being inconsistent. At least some sections of the Java community seem to prefer a misleading and confusing use of the word value over clarity and simplicity, but I for one do not agree with them. I don't see anything inherently confusing or misleading about it. Confusion only arises when some people jump up and say that it's wrong to use the terms that way, because it might cause confusion... In the general case, you can't emulate call-by-reference by passing a name, because you don't know what the name of an object is. That's true, you need to communicate the namespace as well, either implicitly or explicitly. So a (namespace, name) pair, or a (sequence, index) pair in the case of a sequence item, would be the equivalent of a reference in the sense meant by call by reference. -- Greg -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
greg wrote: Arnaud Delobelle wrote: (CBV) An evaluation strategy where arguments are evaluated before the function or procedure is entered. Only the values of the arguments are passed and changes to the arguments within the called procedure have no effect on the actual arguments as seen by the caller. That hinges on what exactly is meant by changes to the arguments. Mutating them, like Python does, which is why calling Python CBV leads people to write buggy code. In Python it can only mean assigning directly to the bare name -- anything else isn't changing the argument itself, but something else to which the argument refers. Hogwash. The argument is the object and mutable objects can be changed as seen by the caller. -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
Terry Reedy wrote: In other words, as I acknowledged in my other post, one can say that all calling is calling by value. No, those are not other words for what I'm saying. Call by reference is very demonstrably different from call by value, as has been pointed out a large number of times already. -- Greg -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
On Nov 10, 2008, at 8:30 AM, Terry Reedy wrote: That hinges on what exactly is meant by changes to the arguments. Mutating them, like Python does, which is why calling Python CBV leads people to write buggy code. In Python it can only mean assigning directly to the bare name -- anything else isn't changing the argument itself, but something else to which the argument refers. Hogwash. The argument is the object and mutable objects can be changed as seen by the caller. By that definition, Java, REALbasic, C++, and VB.NET are all call-by- reference too (even when explicitly using the ByVal keyword in RB/ VB.NET). This will come as quite a shock to the designers and users of those languages. For what it's worth, I think Greg (double-quoted above) has it exactly right. The argument in any of these languages is an object reference; changing the object and changing the object reference are two different things. Best, - Joe -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
Arnaud Delobelle wrote: // What is passed to foo below is obviously not a 'variable // reference' as the argument is not a variable. foo(a[3]); // Now a[3] == 7 foo(b.i); // Now b.i == 7 Yes, it is. By variable I mean what C calls an lvalue, i.e. something you can assign to. I'm not sure that your definition of 'call by value' is widely accepted. If it was, then this thread wouldn't exist. It seems to be accepted by the Java and VB community, judging by what they refer to as call-by-value in those languages. You won't necessarily find it written down anywhere in the exact words I used. I have reverse-engineered it from the characteristics of a wide variety of languages that use the term call-by-value to describe one of their parameter passing mechanisms. Think of it as a theory that fits the observed linguistic facts. (CBV) An evaluation strategy where arguments are evaluated before the function or procedure is entered. Only the values of the arguments are passed and changes to the arguments within the called procedure have no effect on the actual arguments as seen by the caller. That hinges on what exactly is meant by changes to the arguments. In Python it can only mean assigning directly to the bare name -- anything else isn't changing the argument itself, but something else to which the argument refers. -- Greg -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
Joe Strout wrote: On Nov 10, 2008, at 8:30 AM, Terry Reedy wrote: That hinges on what exactly is meant by changes to the arguments. Mutating them, like Python does, which is why calling Python CBV leads people to write buggy code. In Python it can only mean assigning directly to the bare name -- anything else isn't changing the argument itself, but something else to which the argument refers. Hogwash. The argument is the object and mutable objects can be changed as seen by the caller. By that definition, Java, REALbasic, C++, and VB.NET are all call-by-reference too (even when explicitly using the ByVal keyword in RB/VB.NET). This will come as quite a shock to the designers and users of those languages. For what it's worth, I think Greg (double-quoted above) has it exactly right. The argument in any of these languages is an object reference; changing the object and changing the object reference are two different things. -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
Joe Strout wrote: On Nov 10, 2008, at 8:30 AM, Terry Reedy wrote: That hinges on what exactly is meant by changes to the arguments. Mutating them, like Python does, which is why calling Python CBV leads people to write buggy code. In Python it can only mean assigning directly to the bare name -- anything else isn't changing the argument itself, but something else to which the argument refers. Hogwash. The argument is the object and mutable objects can be changed as seen by the caller. By that definition, Java, REALbasic, C++, and VB.NET are all call-by-reference too (even when explicitly using the ByVal keyword in RB/VB.NET). This will come as quite a shock to the designers and users of those languages. For what it's worth, I think Greg (double-quoted above) has it exactly right. The argument in any of these languages is an object reference; In the Python I am talking about, the language defined in the Python Reference Manual, arguments are objects. Bye, tjr -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object [long and probably boring]
On Nov 7, 3:03 pm, Arnaud Delobelle [EMAIL PROTECTED] wrote: 1. Is Napoleon a copy of Dobby or are they the same cat? 2. Is Polion a copy of Napoleon or are they the same cat? 3. When we got rid of Napoleon's fleas, was Nelson deflea-ed as well? 4. When Napoleon died, did Nelson die as well? 5. When we got a new Napoleon, does this mean that our neighbours got a new Nelson? Now a question about the questions about the story: To be able to understand the story and answer questions 1-5, do we need to think of Napoleon, Nelson and Polion as variables containing references to cat objects, or is it enough to think of them as three names for cats? Do you ever say to someone, 'Napoleon' will no longer refer to Nelson. It is this lobster now instead, while you are holding a lobster? My point is that the assignment operation is rare in natural language. Some examples: unitedstates.president= people['Barack Obama'] catholicchurch.pope= people['Joseph Ratzinger'] chicagocubs.manager= people['Lou Pienella'] That is, in January, 'The President' will start to refer to a different person. But you don't see: popstars['Britney Spears']= people['Ricky Martin'] people['Richard Nixon']= people['Ronald Reagan'] You also have expressions, such as 'the man in the corner drinking Coke' and 'the first street on the right', which would not be likely to be modeled as attributes, per se, such as: corner.men.drinking['Coke'] street.ontheright[0] You'd more likely use: select id from people where standingin = 'corner' and drinking = 'coke' select id from streets where distanceonright = min( distanceonright ) Maybe in the future we'll see relational code, rather than hierarchical subclasses: select fly from birds where name = 'bluejay' 'flap_wings()' select fly from birds where name = 'ostrich' 'raise CannotFlyException' -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object [long and probably boring]
Aaron Brady [EMAIL PROTECTED] writes: Do you ever say to someone, 'Napoleon' will no longer refer to Nelson. It is this lobster now instead, while you are holding a lobster? Not explicitly. But in the course of conversation I might refer to Napoleon, meaning Napoleon Bonaparte (1769 - 1821) or Napoleon III (1808 - 1873). There would then be an implicit 'rebinding' of the name Napoleon. My point is that the assignment operation is rare in natural language. My point was to get away from a model for Python which was built on its likely implementation and to hint that we can build one using the naive concept of 'name for a thing' instead. IOW, 'call by value' is an unnecessary obfuscation of what *actually* happens (even though it may describe accurately the artifacts employed by an implementation) I'm glad that you thought about it! -- Arnaud -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object [long and probably boring]
On Nov 10, 2:45 pm, Arnaud Delobelle [EMAIL PROTECTED] wrote: Aaron Brady [EMAIL PROTECTED] writes: Do you ever say to someone, 'Napoleon' will no longer refer to Nelson. It is this lobster now instead, while you are holding a lobster? Not explicitly. But in the course of conversation I might refer to Napoleon, meaning Napoleon Bonaparte (1769 - 1821) or Napoleon III (1808 - 1873). There would then be an implicit 'rebinding' of the name Napoleon. My point is that the assignment operation is rare in natural language. My point was to get away from a model for Python which was built on its likely implementation and to hint that we can build one using the naive concept of 'name for a thing' instead. IOW, 'call by value' is an unnecessary obfuscation of what *actually* happens (even though it may describe accurately the artifacts employed by an implementation) I'm glad that you thought about it! I agree with Terry that all calling is call-by-value, and Steven that all calling is call-by-bit-flipping. I agree with Joe that call-by- object is a special case of call-by-value. I thought of another way Python's passing method could be implemented. Parameters are passed as namespace-name pairs, and every time a variable occurs, it's looked up in the namespace it's in. If it's changed (concurrently) in the outer scope, a copy is made into the inner scope. If it's changed in the inner scope, a new entry is added there. It's still call-by-value (and bit-flipping) on some level, in the trivial sense. What else is it? -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object [long and probably boring]
On Nov 10, 2008, at 2:30 PM, Aaron Brady wrote: I agree with Terry that all calling is call-by-value, and Steven that all calling is call-by-bit-flipping. I agree with Joe that call-by- object is a special case of call-by-value. Woo! Almost sounds like approaching consensus. :) However, I'm sorry to say that I think both Terry's and Steven's descriptions are unhelpful. There really are important distinctions among parameter evaluation strategies. Call-by-reference is not call- by-value (though it is call-by-bit-flipping, but that's too low a level). But if we can agree that call-by-sharing (which I believe is the more widely documented term than call-by-object) is a special case of call-by-value, when the parameters are object references, then I think we may have a winner. Best, - Joe -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
On Mon, 10 Nov 2008 08:39:58 -0700, Joe Strout wrote: By that definition, Java, REALbasic, C++, and VB.NET are all call-by- reference too (even when explicitly using the ByVal keyword in RB/ VB.NET). No, they are not call-by-reference either. They are call-by-sharing, just like Python and CLU. -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
On Mon, 10 Nov 2008 23:16:13 +1300, greg wrote: (CBV) An evaluation strategy where arguments are evaluated before the function or procedure is entered. Only the values of the arguments are passed and changes to the arguments within the called procedure have no effect on the actual arguments as seen by the caller. That hinges on what exactly is meant by changes to the arguments. In Python it can only mean assigning directly to the bare name -- anything else isn't changing the argument itself, but something else to which the argument refers. But the name isn't the argument. The argument to a function is an object, not a name. You can't write a function in Python that takes a name as an argument[1], which would be equivalent to Pascal's var parameters. Take a function foo that takes one formal parameter x. Pass an actual argument y to it. The argument is the object currently bound to y, not the name y. Nothing inside foo can rebind the name y because foo doesn't see the name y, it sees the object. Rebinding (or deleting) the name x inside foo does nothing to the object bound to y, or the name y. [1] You can pass a string representing the name to a function, which can then use some combination of setattr, globals(), exec etc to work with the name represented by that string. But you're still passing an object to the function, not a name. -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object [long and probably boring]
Arnaud Delobelle wrote: But in the course of conversation I might refer to Napoleon, meaning Napoleon Bonaparte (1769 - 1821) or Napoleon III (1808 - 1873). That's more like referring to the name 'Napoleon' in two different namespaces. The original binding still exists, you're just switching contexts. My point was to get away from a model for Python which was built on its likely implementation and to hint that we can build one using the naive concept of 'name for a thing' instead. I don't believe it's possible to build any complete and correct model of Python behaviour without including some concept equivalent to a reference. You can talk about names written on PostIt notes and such like, but that only gets you a short way. It doesn't easily handle names in different namespaces, or references that exist without simple names, e.g. list and tuple items. Trying to repair these deficiencies only leads to increasingly bizarre and contrived mental pictures. On the other hand, if you explicitly include the concept of a reference from the beginning, everything is quite clear and consistent. In other words, the model should be as simple as possible but no simpler. Leaving out references makes it too simple. Another point I'd like to make is that there is nothing inherently low-level about the concept of a reference. It doesn't have to be implemented as a memory address or any other particular machine-level thing. It's possible to talk about Python object references in a completely implementation-independent way. Also, just because you don't explicitly refer to them and manipulate them at the language level doesn't mean they don't exist. To think otherwise is like thinking that air doesn't exist just because you can't see it. There are plenty of experiments which clearly indicate its existence. Likewise, there are plenty of experiments that you can perform with any Python interpreter that reveal the existence of references, or something equivalent to them. -- Greg -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object [long and probably boring]
Aaron Brady wrote: I thought of another way Python's passing method could be implemented. Parameters are passed as namespace-name pairs, and every time a variable occurs, it's looked up in the namespace it's in. If it's changed (concurrently) in the outer scope, a copy is made into the inner scope. If it's changed in the inner scope, a new entry is added there. That sounds like a kind of copy-on-write. It's certainly not call-by-value by any sane interpretation (contrary to your assertion that all calling is call-by-value). -- Greg -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
Steven D'Aprano wrote: But the name isn't the argument. The argument to a function is an object The *formal* argument *is* a name, and that's what the phrase changes to the arguments within the called procedure is talking about. Take a function foo that takes one formal parameter x. Pass an actual argument y to it. The argument is the object currently bound to y, not the name y. Nothing inside foo can rebind the name y because foo doesn't see the name y, it sees the object. More to the point, it sees the *name x* rather than the name y, and rebinding the name x doesn't change the binding of name y. Therefore, the name y has been passed by value, not by reference. [1] You can pass a string representing the name to a function, which can then use some combination of setattr, globals(), exec etc to work with the name represented by that string. This would be the Python equivalent of the strategy used in C to emulate call-by-reference -- and it's needed for the same reason, i.e. the language itself only provides call-by-value. So you pass a value that you can manually dereference to get the same effect. -- Greg -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
On Tue, 11 Nov 2008 16:54:10 +1300, greg wrote: Steven D'Aprano wrote: But the name isn't the argument. The argument to a function is an object The *formal* argument *is* a name, and that's what the phrase changes to the arguments within the called procedure is talking about. If you equate arguments within the called procedure to the *name* of the arguments, then changing the arguments would mean changing the NAME, not the object bound to the name. That is, something like this: def foo(x): y = x del x except as a single operation. I'm sure that's not what you intended to say, but that's what you have said. Except for del and rebinding, Python level code does not allow you to do anything to *names*, only to objects. But I'm sure you know this, which makes your claim all the more confused. Take a function foo that takes one formal parameter x. Pass an actual argument y to it. The argument is the object currently bound to y, not the name y. Nothing inside foo can rebind the name y because foo doesn't see the name y, it sees the object. More to the point, it sees the *name x* rather than the name y, and rebinding the name x doesn't change the binding of name y. Therefore, the name y has been passed by value, not by reference. The term for what you have just said is non sequitor, Latin for it does not follow. The _name_ y is not passed AT ALL. If there is a value that is passed, it is the object bound to y, and not any name at all. If you equate value with object, as you suggested some posts ago, then it could be argued that Python is call-by-value (for value=object) but because call by value has connotations and implications that do not apply to Python, we prefer to avoid the misleading and confusing term c-b-v in preference to Barbara Liskov's term call by sharing or call by object. At least some sections of the Java community seem to prefer a misleading and confusing use of the word value over clarity and simplicity, but I for one do not agree with them. [1] You can pass a string representing the name to a function, which can then use some combination of setattr, globals(), exec etc to work with the name represented by that string. This would be the Python equivalent of the strategy used in C to emulate call-by-reference -- and it's needed for the same reason, i.e. the language itself only provides call-by-value. So you pass a value that you can manually dereference to get the same effect. In the general case, you can't emulate call-by-reference by passing a name, because you don't know what the name of an object is. Obviously I can hard-code some names: def swap(x, y): # arguments x and y are actually pointless g = globals() g['x'], g['y'] = g['y'], g['x'] but you can't emulate c-b-r's ability to swap arbitrary names determined by the compiler. The reason is that when you call a function with an argument, the function sees only the object, and the object does not know what name(s) is bound to it. You could do this: def swap(x_name, y_name): g = globals() g[x_name], g[y_name] = g[y_name], g[x_name] which gives you something a little closer to c-b-r, but it still isn't the same thing. Some major differences: - you can't affect values unless they are bound to a name, that is no swapping of anonymous values, e.g. swap(a[4], a[8]) could not work; - within a nested scope, you can't affect anything unless it is in the global scope; - you need to know the name to apply at runtime, there is no way to programmatically discover it. The third point is the most telling. Consider the Pascal procedure: procedure swap(var x, var y: integer): var tmp: integer; begin tmp := x; x := y; y := tmp; end; Given two integer variables a and b, you call the procedure swap(a, b), and the compiler can determine what memory addresses are used. If Pascal was like Python, you would have to determine the addresses yourself: a := 1; b := 2; swap(12693024, 190342874); after which a would equal 2 and b would equal 1. Obviously Pascal is not like that, but Python is (using names instead of memory locations). This proves that Python names are nothing like Pascal call-by-reference arguments. Passing a name is *not* Python's way to emulate call-by- reference. -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
Steven D'Aprano wrote: Not according to my Comp Sci lecturers back in the day, and not according to my Pascal books. Pascal books will tell you what call-by-value means in Pascal. You can't just blindly take that description and apply it to other languages, just as you can't take what your Pascal book says about assigment and apply it blindly to Python without getting into trouble. Describing call-by-value as copying the value works in Pascal, because assignment and copy are synonyms in that language. But they're not synonyms in all languages, so a language-independent definition of call-by-value needs to describe it in a more general way. Refusing to accept that a more general definition exists just because it's not mentioned in your Pascal book is a little absurd. -- Greg -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
Dennis Lee Bieber wrote: You must have missed all the threads about binding then... Wherein a Python assignment statement binds the LHS name to the RHS object rather than assigns the RHS object value to the LHS I know that it is sometimes referred to that way. But nobody seems to get worked up into a religious fervour and insist that the word assignment be banned from the Python terminology lexicon, the way some people seem to do about words such as value and reference. If we can all get along nicely and accept that assignment is an acceptable term, among alternatives, for something that has an analogy, if not an exact equivalent, in other languages, why can't we do the same for reference and call by value? -- Greg -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
greg [EMAIL PROTECTED] writes: Arnaud Delobelle wrote: What's a variable reference? It's a reference to a variable. It's what gets passed behind the scenes when you use a VAR parameter in Pascal, or a ByRef parameter in VB. Do you mean you can't do the following C++ snippet in Pascal or VB? I haven't used Pascal for more than 20 year and I have never used VB, so this is a real question. foo(int x) { x = 7; } struct bar { int i; float j; }; int main() { int a[10]; bar b; // What is passed to foo below is obviously not a 'variable // reference' as the argument is not a variable. foo(a[3]); // Now a[3] == 7 foo(b.i); // Now b.i == 7 } [...] Passing q by value means that the value of the expression 'q', whatever that is in the language concerned, gets assigned to the local variable 'p', whatever *that* means in the language concerned. Because of the way C assignment works, the result is that p ends up with a copy of the whole struct. Because of the way Python assignment works, the result is that p and q end up referring to the same object. The difference is *entirely* due to the difference in the semantics of assignment between the two languages. Once you've taken that into account, there is no need to look for difference in the parameter passing scheme. I'm not sure that your definition of 'call by value' is widely accepted. If it was, then this thread wouldn't exist. I've tried to google for an authoritative definition but it's harder than I thought. This definition comes up everywhere though. call-by-value (CBV) An evaluation strategy where arguments are evaluated before the function or procedure is entered. Only the values of the arguments are passed and changes to the arguments within the called procedure have no effect on the actual arguments as seen by the caller. [This from http://dictionary.reference.com/browse/call-by-value] It seems to me that it more or less is the definition that most people on this thread has been implicitly using. -- Arnaud -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
On Sun, 09 Nov 2008 11:17:28 +, Arnaud Delobelle wrote: greg [EMAIL PROTECTED] writes: Arnaud Delobelle wrote: What's a variable reference? It's a reference to a variable. It's what gets passed behind the scenes when you use a VAR parameter in Pascal, or a ByRef parameter in VB. Do you mean you can't do the following C++ snippet in Pascal or VB? I haven't used Pascal for more than 20 year and I have never used VB, so this is a real question. foo(int x) { x = 7; } struct bar { int i; float j; }; int main() { int a[10]; bar b; // What is passed to foo below is obviously not a 'variable // reference' as the argument is not a variable. foo(a[3]); // Now a[3] == 7 foo(b.i); // Now b.i == 7 } Translated to Pascal: Program Test; Type Bar = Record i: Integer; j: Real; End; Var a: Array[0..9] Of Integer; b: Bar; Procedure Foo(Var x:Integer); Begin x := 7; End; Begin Foo(a[3]); WriteLn(a[3]); {Prints 7.} Foo(b.i); WriteLn(b.i); {Prints 7.} End. In reality I would not expect that anything is passed here but that the compiler inlines it as direct assignment. Should read: Copying the bit pattern of a 7 into the fixed memory locations. :-) Ciao, Marc 'BlackJack' Rintsch -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
Arnaud Delobelle wrote: What's a variable reference? It's a reference to a variable. It's what gets passed behind the scenes when you use a VAR parameter in Pascal, or a ByRef parameter in VB. What you're saying is that in the code below, when foo(q) is called then 'p' in foo is another name for q in main. Right? struct point { int x; int y; } int foo(point p) { p.x = 42; } int main() { point q = {0, 0}; foo(q); /* So now you're saying that q.x == 0 ? */ } No. Passing q by value means that the value of the expression 'q', whatever that is in the language concerned, gets assigned to the local variable 'p', whatever *that* means in the language concerned. Because of the way C assignment works, the result is that p ends up with a copy of the whole struct. Because of the way Python assignment works, the result is that p and q end up referring to the same object. The difference is *entirely* due to the difference in the semantics of assignment between the two languages. Once you've taken that into account, there is no need to look for difference in the parameter passing scheme. -- Greg -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
greg wrote: No. Passing q by value means that the value of the expression 'q', whatever that is in the language concerned, gets assigned to the local variable 'p', whatever *that* means in the language concerned. In other words, as I acknowledged in my other post, one can say that all calling is calling by value. -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
Joe Strout wrote: On Nov 8, 2008, at 2:38 PM, Terry Reedy wrote: So if you then insist that Python uses call by object, you're actually saying it uses call by value! Both Joe and you seem to be engaging in the following bit of sophistry: In order for code A to call code B, some information must be communicated from A to B. Something we all know ... That information is a value of some sort. True... Therefore all calling is calling by value. Hey now, hang on. That doesn't characterize my argument at all. My argument is much simpler: You can hardly get simpler than what I wrote. -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
On Nov 8, 6:21 am, greg [EMAIL PROTECTED] wrote: Arnaud Delobelle wrote: 'Pass by value' is not relevant to Python as variables do not contain anything. Where abouts in the phrase pass by value does the word contain appear? You don't quote enough context for it to appear. You don't need a notion of containment in order for pass by value to have meaning. All you need is some notion of a value (it doesn't matter what) and some way to pass that value. 'Pass by reference' is not relevant to Python as the language doesn't have the concept of object reference (in the sense of e.g. C++ reference). What it doesn't have is the concept of a *variable* reference, which is what the reference in pass by reference means. What's a variable reference? Here lies, IMHO, the reason why you think you need Python to 'pass by value'. As you believe that variables must contain something, you think that assignment is about copying the content of a variable. Assignment in Python is simply giving a new name to an object. Yes, and so is passing by value! What you're saying is that in the code below, when foo(q) is called then 'p' in foo is another name for q in main. Right? struct point { int x; int y; } int foo(point p) { p.x = 42; } int main() { point q = {0, 0}; foo(q); /* So now you're saying that q.x == 0 ? */ } -- Arnaud -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object [long and probably boring]
On Nov 7, 2008, at 6:21 PM, Aaron Brady wrote: Therefore objects don't need names to exist. Having a name is sufficient but not necessary to exist. Being in a container is neither necessary -nor- sufficient. What do you mean? Being in a container isn't necessary, but it certainly is sufficient. Having ANY references to it is both necessary and sufficient to exist. And isn't that the easiest way to say it? Best, - Joe -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object [long and probably boring]
On Nov 8, 8:42 am, Joe Strout [EMAIL PROTECTED] wrote: On Nov 7, 2008, at 6:21 PM, Aaron Brady wrote: Therefore objects don't need names to exist. Having a name is sufficient but not necessary to exist. Being in a container is neither necessary -nor- sufficient. What do you mean? Being in a container isn't necessary, but it certainly is sufficient. Having ANY references to it is both necessary and sufficient to exist. And isn't that the easiest way to say it? No, you forgot about cyclically-linked garbage, which Python implementations are allowed to, but not required to, collect. -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
On Nov 8, 1:08 am, Steven D'Aprano [EMAIL PROTECTED] cybersource.com.au wrote: On Sat, 08 Nov 2008 18:31:47 +1300, greg wrote: Quote in favor of Steven snip Example in favor of Steven snip There's no obviously about it. To anyone who has learned that call-by- value means that a copy is made, obviously it does mean copying the value. If you have learned a different meaning, then you will believe differently. I don't think it's obvious to everyone what a copy constructor is and when it's called. That's ok, it's something you can learn. I think Joe's idea is that you can think of every variable in Python as a pointer, and that clears up some confusions about its variable model. What happens when a pointer is copied? What is an example of copying a pointer in spoken language? a= [ 1, 2, 3 ] Are the following true? The value of 'a' is an object. The value of that object is [ 1, 2, 3 ]. The value of 'a' is [ 1, 2, 3 ]. If so, 'value' is ambiguous and therefore not very useful as a term. -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
greg wrote: Joe Strout wrote: Something has just occurred to me. If you take the view that the value of an expression is an object, then the terms value and object are synonymous. Nope. The result of an expression is an object with an id, class, and 'value', where 'value' can include attributes (other than class) or non-attribute content or both. The distinction does not matter much for immutables but it definitely does for mutable objects. So if you then insist that Python uses call by object, you're actually saying it uses call by value! Both Joe and you seem to be engaging in the following bit of sophistry: In order for code A to call code B, some information must be communicated from A to B. Something we all know ... That information is a value of some sort. True... Therefore all calling is calling by value. Well, yes, if you insist. *But*, a distinction that does not distinguish is useless. One might as well say Calling is calling. In order to successfully program in Python, one must understand how functions are called. That 'how' is distinct from the 'how' of some other languages. Therefore, some of us claim, that 'how' should have a distinct name. Terry Jan Reedy -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object [long and probably boring]
Steven D'Aprano wrote: In an attempt to keep this post from hitting the ridiculous length of one (Aside: I've learned one thing in this discussion. Despite the number of sources I've read that claim that if you pass an array to a C function the entire array will be copied, this does not appear to be true) Since C does not have an array type, it is impossible to pass an array. int *a, b[10] declares *both* a and b as int pointers. As I remember, the only difference is that b is initialized to the address of an allocated block of 10. In expressions, b is an int pointer, just like a, and a[i] and b[i] are defined the same, as *(a+i) and *(b+i), where the addition is pointer arithmetic. Function definitions can only define parameters as pointers (and lots else), not arrays. So passing either a or b passes the address it represents. (Function names also represent addresses in expressions, whereas, I believe, in C99 at least, struct names represent the struc, not its address.) tjr -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
On Nov 8, 3:38 pm, Terry Reedy [EMAIL PROTECTED] wrote: In order for code A to call code B, some information must be communicated from A to B. Something we all know ... That information is a value of some sort. True... Therefore all calling is calling by value. Well, yes, if you insist. *But*, a distinction that does not distinguish is useless. One might as well say Calling is calling. Actually I like that. We should call all call methods call by calling, because it is a useful and consistent generalization. -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object [long and probably boring]
On 2008-11-08, Terry Reedy [EMAIL PROTECTED] wrote: Steven D'Aprano wrote: In an attempt to keep this post from hitting the ridiculous length of one (Aside: I've learned one thing in this discussion. Despite the number of sources I've read that claim that if you pass an array to a C function the entire array will be copied, this does not appear to be true) Since C does not have an array type, it is impossible to pass an array. int *a, b[10] declares *both* a and b as int pointers. As I remember, the only difference is that b is initialized to the address of an allocated block of 10. No, that's not true. b is not a pointer that's initialized with an address. b is a constant literal that is equivalent to the address of the first element in the array. IOW, (void*)b == (void*)b == (void*)b[0]. That's not true for a. (void*)a == (void*)a[0], but (void*)a != (void*)a. In expressions, b is an int pointer, just like a, and a[i] and b[i] are defined the same, as *(a+i) and *(b+i), where the addition is pointer arithmetic. True, but a and b are very different, and a can be used as an lvalue and b can not. a is a variable, and b is a literal constant (that can, for static storage classes, be resolved to a value at compile/load time). Function definitions can only define parameters as pointers (and lots else), not arrays. So passing either a or b passes the address it represents. (Function names also represent addresses in expressions, whereas, I believe, in C99 at least, struct names represent the struc, not its address.) -- Grant -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
On Nov 8, 2008, at 2:38 PM, Terry Reedy wrote: So if you then insist that Python uses call by object, you're actually saying it uses call by value! Both Joe and you seem to be engaging in the following bit of sophistry: In order for code A to call code B, some information must be communicated from A to B. Something we all know ... That information is a value of some sort. True... Therefore all calling is calling by value. Hey now, hang on. That doesn't characterize my argument at all. My argument is much simpler: Python's call semantics are exactly the same as other modern OOP languages, where it is commonly called call-by-value (and it is, in fact, call-by-value, as you can see with the simple test of assigning to the formal parameter). Therefore, we would reduce confusion if we'd get on board and call it that in Python, too. Of course, I've softened my position somewhat, since being shown that call by sharing is simply a term for call-by-value in the case where the values are object references. That clearly does apply to Python (as well as other OOP languages, where object references are involved), and as long as we can explain it as just a restricted form of call-by-value, I'm OK with that. In order to successfully program in Python, one must understand how functions are called. That 'how' is distinct from the 'how' of some other languages. Which languages? Certainly none of those at http://www.strout.net/info/coding/valref/ . (Except that some of them have a by-reference option, which Python and Java do not.) Best, - Joe -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
On Nov 8, 10:59 pm, Joe Strout [EMAIL PROTECTED] wrote: Of course, I've softened my position somewhat, since being shown that call by sharing is simply a term for call-by-value in the case where the values are object references. That clearly does apply to Python (as well as other OOP languages, where object references are involved), and as long as we can explain it as just a restricted form of call-by-value, I'm OK with that. Humor me briefly. In 'x= [1, 2, 3]', do you think that the value of x is a memory address? -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
On Fri, 07 Nov 2008 00:44:21 -0500, Steve Holden wrote: Steven D'Aprano wrote: On Thu, 06 Nov 2008 09:59:37 -0700, Joe Strout wrote: [...] And by definition, call by value means that the parameter is a copy. So if you pass a ten megabyte data structure to a function using call-by- value semantics, the entire ten megabyte structure is copied. Since this does not happen in Python, Python is not a call-by-value language. End of story. Without knowing that, you don't know what assignments to the formal parameter will do, or even what sort of arguments are valid. Answer: it's a copy of it. Lies, all lies. Python doesn't copy variables unless you explicitly ask for a copy. That some implementations of Python choose to copy pointers rather than move around arbitrarily large blocks of memory instead is an implementation detail. It's an optimization and irrelevant to the semantics of argument passing in Python. [...] Are you sure you meant to write this? I'm not sure I understand what you're getting at. The only thing I can imagine is that you think there's some sort of contradiction between my two statements. I don't see why you think so. In principle one could create an implementation of Python with no stack at all, where everything lives in the heap, and all argument passing is via moving the actual objects (large blocks of memory) rather than references to the objects. I don't mean to imply that this is a practical way to go about implementing Python, particularly given current computer hardware where registers are expensive and the call stack is ubiquitous. But there are other computing models, such as the register machine model which uses a hypothetically-infinite number of registers, no stack and no heap. With sufficient effort, one could implement a Python compiler using only a Turing Machine. Turing Machines don't have call-by-anything semantics. What would that say about Python? Alternatively, you're commenting about my comment about copying pointers. I thought I had sufficiently distinguished between what takes place at the level of the Python VM (nothing is copied without an explicit request to copy it) and what takes place in the VM's implementation (the implementation is free to copy whatever pointers it wants as an optimization). If I failed to make that clear, I hope I have done so now. Pointers do not exist at the level of the Python VM, but they clearly exist in the C implementation. We agree that C is call-by-value. CPython is (obviously) built on top of C's call-by-value semantics, by passing pointers (or references if you prefer) to objects. But that doesn't imply that Python's calling semantics are the same as C's. Algol is call-by-name. Does anyone doubt that we could develop an Algol implementation of Python that used nothing but call-by-name semantics at the implementation level? Would that mean that Python was call-by-name? The point is that Joe's argument is based on a confusion between the C implementation (calling a function with argument x makes a copy of a pointer to x and puts it into the stack for the function) and what happens at the level of the Python language. -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object [long and probably boring]
On Nov 6, 2008, at 10:35 PM, Steve Holden wrote: That's good to hear. Your arguments are sometimes pretty good, and usually well made, but there's been far too much insistence on all sides about being right and not enough on reaching agreement about how Python's well-defined semantics for assignment and function calling should best be described. In other words, it's a classic communication problem. That's a fair point. I'll try to do better. I must say I find it strange when people try to contradict my assertion that Python names are references to objects, when the (no pun intended) reference implementation of the language uses reference counting to track how many assignments have been made. I agree. It seems like we should be able to take that as a given. So any argument that the language doesn't have the concept of object reference (in the sense of e.g. C++ reference) is simply stating the obvious: that Python has no way to declare reference variables. I would argue myself that it has no need of such a mechanism precisely because names are object references, and I'd like to hear counter-arguments. Right. I think of it this way: every variable is an object reference; no special syntax needed for it because that's the only type of variable there is. (Just as with Java or .NET, when dealing with any class type; Python is just a little more extreme in that even simple things like numbers are wrapped in objects.) Note: I tried to say name above instead of variable but I couldn't bring myself to do it -- name seems to generic to do that job. Lots of things have names that are not variables: modules have names, classes have names, methods have names, and so do variables. If I say name, an astute listener would reasonably say name of what -- and I don't want to have to say name of some thing in a name space which can be flexibly associated with an object when the simple term variable seems to work as well. Well that's not true either. If I remember all the way back to my computational science degree I seem to remember being taught that there was call by *simple reference*, which is what I understand you to mean. Suppose I write the following on some not-quite-Python language: lst = ['one', 'two', 'three'] index = 1 def foo(item, i): i = 2 item = ouch foo(lst[index], index) ... With call by simple reference, after the call I would expect the following conditions to be true: index == 2 lst == ['one', 'ouch', 'three'] Yes, I guess so, though it would require that lst[index] evaluate to an lvalue to which the 'item' parameter could be an alias. (With the second parameter, 'i', the situation is more straightforward because you're passing in a simple variable rather than a more complex expression.) With full call by reference, however, arguably the change to the value of index would induce the post-conditions index == 2 lst == ['one', 'two', 'ouch'] because the reference made by the first argument depends on the value of a variable mutated inside the function call. I confess that I've never heard of call by simple reference or call by full reference before. What you're describing in the second case sounds more like call by name to me. But I think we can agree that neither of these behaviors describes Python. Why the resistance to these simple and basic terms that apply to any OOP language? Ideally I'd like to see this discussion concluded without resorting to democratic appeals. Otherwise, after all, we should all eat shit: sixty billion flies can't possibly be wrong. I think I could make a good argument that the nutritional needs of flies are different from those of humans. On the other hand, what argument is there that the Python community should use its own unique terminology for concepts that apply equally well to other languages? Wouldn't communication be easier and smoother if we adopted standard terms for standard behavior? What does give a new name to an object mean? I submit that it means exactly the same thing as assigns the name to refer to the object. I normally internalize x = 3 as meaning store a reference to the object 3 in the slot named x, and when I see x in an expression I understand it to be a reference to some object, and that the value will be used after dereferencing has taken place. Works for me. I've seen various descriptions of Python's name binding behavior in terms of attaching Port-It notes bearing names to the objects reference by the names, and I have never found them convincing. The reason for this is that names live in namespaces, whereas values live in some other universe altogether (that I normally describe as object space to beginners, though this is not a term you will come across in the python literature). Agreed. That model implies that all names are global, and completely fails to explain how one object might be named x and a
Re: Finding the instance reference of an object
Steven D'Aprano wrote: On Fri, 07 Nov 2008 00:44:21 -0500, Steve Holden wrote: Steven D'Aprano wrote: On Thu, 06 Nov 2008 09:59:37 -0700, Joe Strout wrote: [...] And by definition, call by value means that the parameter is a copy. So if you pass a ten megabyte data structure to a function using call-by- value semantics, the entire ten megabyte structure is copied. Since this does not happen in Python, Python is not a call-by-value language. End of story. Without knowing that, you don't know what assignments to the formal parameter will do, or even what sort of arguments are valid. Answer: it's a copy of it. Lies, all lies. Python doesn't copy variables unless you explicitly ask for a copy. That some implementations of Python choose to copy pointers rather than move around arbitrarily large blocks of memory instead is an implementation detail. It's an optimization and irrelevant to the semantics of argument passing in Python. [...] Are you sure you meant to write this? I'm not sure I understand what you're getting at. The only thing I can imagine is that you think there's some sort of contradiction between my two statements. I don't see why you think so. In principle one could create an implementation of Python with no stack at all, where everything lives in the heap, and all argument passing is via moving the actual objects (large blocks of memory) rather than references to the objects. I don't mean to imply that this is a practical way to go about implementing Python, particularly given current computer hardware where registers are expensive and the call stack is ubiquitous. But there are other computing models, such as the register machine model which uses a hypothetically-infinite number of registers, no stack and no heap. With sufficient effort, one could implement a Python compiler using only a Turing Machine. Turing Machines don't have call-by-anything semantics. What would that say about Python? Alternatively, you're commenting about my comment about copying pointers. I thought I had sufficiently distinguished between what takes place at the level of the Python VM (nothing is copied without an explicit request to copy it) and what takes place in the VM's implementation (the implementation is free to copy whatever pointers it wants as an optimization). If I failed to make that clear, I hope I have done so now. Pointers do not exist at the level of the Python VM, but they clearly exist in the C implementation. We agree that C is call-by-value. CPython is (obviously) built on top of C's call-by-value semantics, by passing pointers (or references if you prefer) to objects. But that doesn't imply that Python's calling semantics are the same as C's. Algol is call-by-name. Does anyone doubt that we could develop an Algol implementation of Python that used nothing but call-by-name semantics at the implementation level? Would that mean that Python was call-by-name? The point is that Joe's argument is based on a confusion between the C implementation (calling a function with argument x makes a copy of a pointer to x and puts it into the stack for the function) and what happens at the level of the Python language. I am probably egregiously misunderstanding. The practical difficulty with the moving huge blocks of data approach would appear to emerge when a function that gets passed an instance of some container then calls another function that references the same container as a global, for example. Again, I don't think we disagree about how Python actually works, but it seemed to me that your statement obscured rather than helped. regards Steve -- Steve Holden+1 571 484 6266 +1 800 494 3119 Holden Web LLC http://www.holdenweb.com/ -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
On Thu, 06 Nov 2008 21:31:16 -0700, Joe Strout wrote: You're wrong, Python variables don't contain *anything*. Python variables are names in a namespace. I think we're saying the same thing. What's a name? It's a string of characters used to refer to something. That which refers to something is a reference. In some sense, I have to agree with that. Reference as a plain English word is very abstract. The thing it refers to is a referent. I was trying to avoid saying the value of an object reference is a reference to an object since that seems tautological and you don't like my use of the word value, but I see you don't like contains either. I'm happier with the idea that a name in Python refers to an object than your claim that variables contain a reference to an object. Let me explain: In languages such as C and Pascal, a variable is a named memory location with an implied size. For the sake of the argument, let's assume variables are all two bytes in size, i.e. they can hold a single short integer. So, if the name 'x' refers to location 0x23A782, and the two bytes at that location are 0x0001, then we can legitimately say that the location 0x23A782 (otherwise known as 'x') _contains_ 1 because the byte pattern representing 1 is at that memory location. But in Python, what you've been calling variables is explicitly a *mapping* between a name and a value. Unlike variables above, the compiler can't map a name to a memory location. At run time, the VM has to search a namespace for the name. If you disassemble Python byte-code, you will see things like: LOAD_NAME 1 (x) If you want to talk about something containing the value, that something would be the namespace, not the name: the name is the key in the hash table, and is a separate piece of data to the value. The key and the value are at different locations, you can't meaningfully say that the value is contained by the key, for the same reason that given a list [10, 11, 12, 13, 14, 15] you wouldn't say that the int 12 was contained by the number 2. Maybe we can try something even wordier: a variable in Python is, by some means we're not specifying, associated with an object. (This is what I mean when I say it refers to the object.) Can we agree that far? So far. Now, when you pass a variable into a method, the formal parameter gets associated with same object the actual parameter was associated with. Agreed. I like to say that the object reference gets copied into the formal parameter, since that's a nice, simple, clear, and standard way of describing it. I think you object to this way of saying it. But are we at least in agreement that this is what happens? At the implementation level of CPython, yes. In abstract, no. In abstract, we can't make *any* claims about what happens beyond the Python code, because we don't know how the VM is implemented. Perhaps it is a giant pattern in Conway's cellular automata Life, which is Turing Complete. In practice, any reasonable implementation of Python on existing computer hardware is going to more-or-less do what the CPython implementation does. But just because every existing implementation does something doesn't mean it's not an implementation detail. But putting that aside, consider the Python code x = 1. Which statement would you agree with? (A) The value of x is 1. Only speaking loosely (which we can get away with because numbers are immutable types, as pointed out in the last section of [1]). Why speaking loosely? At the level of Python code, the object you have access to is nothing more or less than 1. There is a concrete representation of the abstract Platonic number ONE, and that concrete representation is written as 1. The fact that the object 1 is immutable rather than mutable is irrelevant. After x = [] the value of x is the empty list. As far as I am concerned, this is one place where the plain English definition of the word value is the only meaningful definition: what is denoted by a symbol. Or if you prefer, what the symbol represents. At the language level, x=1 means that x represents the object 1, nothing more and nothing less, regardless of how the mechanics of that representation are implemented. The value of a variable is whatever thing you assign to that variable. If that thing is the int 1, then the value is the int 1. If the thing is a list, the value is that list. If the thing is a pointer, the value is a pointer. (Python doesn't give you access to pointers, but other languages do.) Whatever mechanism is used to implement that occurs at a deeper level. In Pascal and C, bytes are copied into memory locations (which is actually implemented by flipping bits at one location to match the state of bits at another location). In CPython and Java, pointers or references are created and pointed at complex data structures called objects. That's an implementation detail, just like flipping
Re: Finding the instance reference of an object
On Fri, 07 Nov 2008 10:50:55 -0500, Steve Holden wrote: I am probably egregiously misunderstanding. The practical difficulty with the moving huge blocks of data approach would appear to emerge when a function that gets passed an instance of some container then calls another function that references the same container as a global, for example. I have no doubt whatsoever that such an implementation would be fragile, complicated, convoluted and slow. In other words, it would be terrible. But that's merely a Quality of Implementation issue. It would still be Python. -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
Steven D'Aprano wrote: On Fri, 07 Nov 2008 10:50:55 -0500, Steve Holden wrote: I am probably egregiously misunderstanding. The practical difficulty with the moving huge blocks of data approach would appear to emerge when a function that gets passed an instance of some container then calls another function that references the same container as a global, for example. I have no doubt whatsoever that such an implementation would be fragile, complicated, convoluted and slow. In other words, it would be terrible. But that's merely a Quality of Implementation issue. It would still be Python. OK, more specifically: I don't see how changes to the copy of the (structure referenced by) the argument would be reflected in the global structure. In other words, it seems to involve a change of semantics to me, so I think I am misunderstanding you. regards Steve -- Steve Holden+1 571 484 6266 +1 800 494 3119 Holden Web LLC http://www.holdenweb.com/ -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object [long and probably boring]
On Fri, 07 Nov 2008 08:48:19 -0700, Joe Strout wrote: I think of it this way: every variable is an object reference; no special syntax needed for it because that's the only type of variable there is. (Just as with Java or .NET, when dealing with any class type; Python is just a little more extreme in that even simple things like numbers are wrapped in objects.) Note: I tried to say name above instead of variable but I couldn't bring myself to do it -- name seems to generic to do that job. Lots of things have names that are not variables: modules have names, classes have names, methods have names, and so do variables. But modules, classes and methods are also objects, and they can be bound to names. What's the name of the module after this piece of code? import math foo = math del math Unfortunately, the term name is *slightly* ambiguous in Python. There are names, and then there are objects which have a name attribute, which holds a string. This attribute is usually called __name__ but sometimes it's called other things, like func_name. The __name__ attribute of objects is an arbitrary label that the object uses for display purposes. But names are the entities that Python code usually uses to refer to objects. [...] what argument is there that the Python community should use its own unique terminology for concepts that apply equally well to other languages? Wouldn't communication be easier and smoother if we adopted standard terms for standard behavior? You're assuming that call-by-sharing isn't a standard term. That's not true. It's a standard term that is sadly not well known, I believe because of the ignorance of most coders to the history of their own discipline. (I include myself in that.) You're also assuming that the use of call-by-value to refer to very different behaviours in C and Java somehow makes communication easier and smoother. I don't think it does. [...] In a language that supports integers and doubles as simple types, stored directly in a variable, then it is an obvious generalization that in the case of an object type, the value is a reference to an object. How is it a generalization? Using Python syntax instead of Java, but let's pretend that Python ints are primitives just like in Java, but floats are not. I do this to avoid any confusion over mutable/immutable, or container types. Nice simple values, except one is an object and one is a primitive type. x = 1 # the value of x is 1 x = 1.0 # the value of x is 0x34a5f0 Where is the generalization that you speak of? In a generalization, you extend the same rule to cover slightly different circumstances. But that's not what happens here. In the first place, you start with the rule that the value of x is the thing you assign to x. In the second place, you change the rule to say that the value of x is an arbitrary implementation-dependent pointer to the thing you assign to x. That's not a generalization, it's an anti-generalization. But Python doesn't have those simple types, so there is a temptation to try to skip this generalization and say that references are not values, but rather the values are the objects themselves (despite the dereferencing step that is still required to get any data out of them). What dereferencing step? There's no such thing in Python code. You just use the name, as normal. Oh sure, at the deep implementation level there's a dereferencing step, but that applies for primitive types in C too. When you refer to a variable x in C, the CPU has to look into a memory location to find out what the value of x is. That applies whether x is an int on the stack or a object in the heap. But it's not something that the C programmer has to worry about, it's an implementation detail handled by the compiler and the runtime environment. It's not part of your C program. In the same way the dereferencing of Python names is not part of your Python program. It's an implementation detail. However, it seems to me that when you start denying that the value of an object reference is a reference to an object, this is when you get led into a quagmire of contradictions. Let's hear some of these contradictions. Personally, they would have to be pretty big to make me give up saying that the value of x after x=1 is 1. [...] But continuing to attempt to gloss over that fact, when you come to parameter passing, you're then stuck trying to avoid describing it as call by value, since if you claim that what a variable contains is the object itself, then that doesn't fit (since clearly the object itself is not copied). Your reasoning is backwards. Call-by-value by definition implies that the value is copied. If the value isn't copied, it can't be call-by-value. You shouldn't change the definition of value in order to hammer the square peg of your language into the round hole of call-by-value, especially since there has
Re: Finding the instance reference of an object
On Fri, 07 Nov 2008 11:37:28 -0500, Steve Holden wrote: Steven D'Aprano wrote: On Fri, 07 Nov 2008 10:50:55 -0500, Steve Holden wrote: I am probably egregiously misunderstanding. The practical difficulty with the moving huge blocks of data approach would appear to emerge when a function that gets passed an instance of some container then calls another function that references the same container as a global, for example. I have no doubt whatsoever that such an implementation would be fragile, complicated, convoluted and slow. In other words, it would be terrible. But that's merely a Quality of Implementation issue. It would still be Python. OK, more specifically: I don't see how changes to the copy of the (structure referenced by) the argument would be reflected in the global structure. In other words, it seems to involve a change of semantics to me, so I think I am misunderstanding you. What, you want me to come up with an implementation? Okay, fine. The VM keeps a list of the namespaces that contain such cloned objects. After each Python statement is executed, before the next one gets to run, the VM runs through that list and synchronizes each object in the caller's scope with the value of its clone in the function scope. -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
On Fri, 07 Nov 2008 11:37:28 -0500, Steve Holden wrote: Steven D'Aprano wrote: On Fri, 07 Nov 2008 10:50:55 -0500, Steve Holden wrote: I am probably egregiously misunderstanding. The practical difficulty with the moving huge blocks of data approach would appear to emerge when a function that gets passed an instance of some container then calls another function that references the same container as a global, for example. I have no doubt whatsoever that such an implementation would be fragile, complicated, convoluted and slow. In other words, it would be terrible. But that's merely a Quality of Implementation issue. It would still be Python. OK, more specifically: I don't see how changes to the copy of the (structure referenced by) the argument would be reflected in the global structure. In other words, it seems to involve a change of semantics to me, so I think I am misunderstanding you. Of course every copy has a list of references to other copies and time stamps associated with every attribute. So when you access an attribute the implementation first chases all the links to the copies, and checks if the attribute has a newer time stamp there, so the value has to be copied back. =:o) More serious: If you start to design distributed object oriented systems with call-by-sharing semantics you may end up with actually copying the value and propagating changes or checking for them in other copies. Ciao, Marc 'BlackJack' Rintsch -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object [long and probably boring]
On Nov 7, 2008, at 10:29 AM, Steven D'Aprano wrote: Note: I tried to say name above instead of variable but I couldn't bring myself to do it -- name seems to generic to do that job. Lots of things have names that are not variables: modules have names, classes have names, methods have names, and so do variables. But modules, classes and methods are also objects, and they can be bound to names. OK, that's a good point. It strikes me as a generally Bad Idea to actually take advantage of that (i.e., to reassign to a class or module name), but I guess Python allows it. Unfortunately, the term name is *slightly* ambiguous in Python. There are names, and then there are objects which have a name attribute, which holds a string. This attribute is usually called __name__ but sometimes it's called other things, like func_name. The __name__ attribute of objects is an arbitrary label that the object uses for display purposes. But names are the entities that Python code usually uses to refer to objects. Right. This may lead to the confusion that started this thread, i.e. someone asking how to find the name of an arbitrary object (by which they meant the entry in some namespace that refers to it, what I like to call a variable name). If you think of objects as having names (which as you point out is sort of true in some cases but not in general), rather than names as referring to objects, then you get into this trouble. You're also assuming that the use of call-by-value to refer to very different behaviours in C and Java somehow makes communication easier and smoother. I don't think it does. OK, so now we're getting down to it: you think that Python's behavior is like Java, but Java's behavior is different from C, right? What would it take to convince you that Java and C have exactly the same semantics, and differ only in syntax? Would equivalent code snippets that do the same thing do the job? In a language that supports integers and doubles as simple types, stored directly in a variable, then it is an obvious generalization that in the case of an object type, the value is a reference to an object. How is it a generalization? Because you start with, say, integers, and make such observations as: 1. x = y copies the integer value from y into x. 2. foo(x), where foo's parameter is by-value, copies x into the formal parameter. 3. foo(x), where foo's parameter is by-reference (e.g. using in C++, or using ByRef in RB/VB.NET), makes the formal parameter an alias of x. Then you look at a declaration of (speaking loosely) object type, such as Java's SomeClass x; or C++'s SomeClassPtr x; // where typedef SomeClass* SomeClassPtr; Then you ask, how do the above situations 1-3 apply to this? Well, they apply just fine, except that what is being copied or aliased is the reference to an object rather than an integer. That's the obvious generalization I was thinking of. Using Python syntax instead of Java, but let's pretend that Python ints are primitives just like in Java, but floats are not. I do this to avoid any confusion over mutable/immutable, or container types. Nice simple values, except one is an object and one is a primitive type. x = 1 # the value of x is 1 x = 1.0 # the value of x is 0x34a5f0 Strictly true, but irrelevant if float objects are immutable. Immutable objects can be treated as values; it's only by mutating an object that you can tell that you're dealing with references to shared data. What dereferencing step? There's no such thing in Python code. You just use the name, as normal. If you just use the name, then you're accessing the reference. To get to the actual data, you have to dereference it with .. (Granted, this dereferencing is often done within operator methods so that it's mostly hidden from you in many cases, especially when dealing with number- and string-like objects.) Oh sure, at the deep implementation level there's a dereferencing step, but that applies for primitive types in C too. When you refer to a variable x in C, the CPU has to look into a memory location to find out what the value of x is. That's not what I'm talking about. I'm talking about person.age in Python, Java, or .NET, or person-age in C/C++. Personally, they would have to be pretty big to make me give up saying that the value of x after x=1 is 1. I've stated repeatedly that this is fine shorthand. You only get into trouble when, instead of assigning 1, you are assigning (a reference to) some mutable object. Then you have to think about whether you are copying the data or just copying a reference to it. Your reasoning is backwards. Call-by-value by definition implies that the value is copied. If the value isn't copied, it can't be call-by-value. Quite right. We just disagree on what value means. I think this is because Python is so restricted: everything is an
Re: Finding the instance reference of an object [long and probably boring]
Joe Strout wrote: On Nov 6, 2008, at 10:35 PM, Steve Holden wrote: Note: I tried to say name above instead of variable but I couldn't bring myself to do it -- name seems to generic to do that job. Python has two types of names. Some complex objects -- modules, classes, and functions, and wrappers and subclasses thereof, have 'definition names' that are used instead of a 'value' to print a representation. Otherwise, names are identifiers, the term used in the grammar. But I agree even two meaning is one too many. Maybe 'label' would be a better short form for 'identifier'. 'Labeling' might be clearer for many beginners than 'name-binding'. Lots of things have names that are not variables: modules have names, classes have names, methods have names, and so do variables. If I say name, an astute listener would reasonably say name of what Common nouns, when instantiated, become the name of whatever particular object they are associated with. -- and I don't want to have to say name of some thing in a name space which can be flexibly associated with an object when the simple term variable seems to work as well. 'Variable' has many more meanings than 'name' or 'label' and overall seems to be more confusing, not less. I say this as an empirical observation of c.l.p postings. You yourself switched back and forth between two different meanings. I'm with you there. To me, the consistent simplicity is exactly this: all variables are object references, and these are always passed by value. The me, this implies that the corresponding parameter should become a reference to that reference value. In any case, the last 10 years of this newsgroups shows that describing Python calling as 'by value' confuses people so that they are surprised that mutating a list inside a function results in the list being mutated outside the function. But Python doesn't have those simple types, so there is a temptation to try to skip this generalization and say that references are not values, The Python Language Reference uses the word 'reference' but does not define it. I take it to be 'whatever information an interpreter uses to associate a name or collection slot with an object and to retrieve the object (and possibly its value) when requested'. Well of course. I'm pretty sure I've said repeatedly that Python variables refer to objects on the heap. Built-in objects are not allocated on the heap. (Please replace heap with object space if you prefer.) They are in abstract object space, although CPython occasionally leaks the abstraction in error messages about not being able to modify non-heap objects. I'm only saying that Python variables don't contain any other type of value than references. One problem with the word 'variable' is that variables are somethings thought of as 'containing', as you did above. So you switch back and forth between 'variables *are* references' and 'variables *contain* references'. Whereas a name (noun) definitely *is* a reference and not a container. Ditto right back at you. :) So maybe here's the trouble: since all Python variables are references, Back to *is*. But continuing to attempt to gloss over that fact, when you come to parameter passing, I believe most of us here try to follow Knuth's lead and use 'parameter' for the local names and 'argument' for the value/object that gets associated with the name. not copied). You also have to describe the assignment operator as In Python, assignment is not an operator by intentional design. different from all other languages, since clearly that's not copying the object either. Python's assignment *statement* does what we routinely do in everyday life when we assign new labels to things, whether permanently or temporarily. An assignment copies the RHS reference into the LHS variable, nothing more or less. Back to variable as container. An assignment associates the RHS object(s) with the LHS target(s). A parameter copies the argument reference into the formal parameter, A function call associates objects derived from the argument expressions and stored defaults with the function parameters. Isn't that simple, clear, and far easier to explain? Applied to my version, I agree ;-). I wonder if that could be tested systematically. Perhaps we could round up 20 newbies, divide them into two groups of 10, give each one a 1-page explanation either based on passing object references by-value, or passing values sort-of-kind-of-by-reference, and then check their comprehension by predicting the output of some code snippets. That'd be very interesting. Except for your garbling of the alternative to your version, I agree. I suspect that different people might do better with different explanations, depending on background. In my case, my understanding of Python became clear only once I stopped listening to all the confusing descriptions here,
Re: Finding the instance reference of an object
Steven D'Aprano wrote: On Fri, 07 Nov 2008 11:37:28 -0500, Steve Holden wrote: Steven D'Aprano wrote: On Fri, 07 Nov 2008 10:50:55 -0500, Steve Holden wrote: I am probably egregiously misunderstanding. The practical difficulty with the moving huge blocks of data approach would appear to emerge when a function that gets passed an instance of some container then calls another function that references the same container as a global, for example. I have no doubt whatsoever that such an implementation would be fragile, complicated, convoluted and slow. In other words, it would be terrible. But that's merely a Quality of Implementation issue. It would still be Python. OK, more specifically: I don't see how changes to the copy of the (structure referenced by) the argument would be reflected in the global structure. In other words, it seems to involve a change of semantics to me, so I think I am misunderstanding you. What, you want me to come up with an implementation? Okay, fine. The VM keeps a list of the namespaces that contain such cloned objects. After each Python statement is executed, before the next one gets to run, the VM runs through that list and synchronizes each object in the caller's scope with the value of its clone in the function scope. Right, so we replace references to values with references to namespaces? Anyway, thanks. I'm really glad you stated up-front that this was not a practical execution scheme. regards Steve -- Steve Holden+1 571 484 6266 +1 800 494 3119 Holden Web LLC http://www.holdenweb.com/ -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object [long and probably boring]
Steven D'Aprano wrote: On Fri, 07 Nov 2008 08:48:19 -0700, Joe Strout wrote: Unfortunately, the term name is *slightly* ambiguous in Python. There are names, and then there are objects which have a name attribute, which holds a string. This attribute is usually called __name__ but sometimes it's called other things, like func_name. 3.0 corrects that divergence. def foo(): pass foo.__name__ 'foo' You're assuming that call-by-sharing isn't a standard term. That's not true. It's a standard term that is sadly not well known, I believe because of the ignorance of most coders to the history of their own discipline. (I include myself in that.) - http://en.wikipedia.org/wiki/Call_by_something#Call_by_sharing Call by sharing Also known as call by object or call by object-sharing is an evaluation strategy first named by Barbara Liskov et al for the language CLU in 1974[1]. It is used by languages such as Python[2] and Iota and (as argued by some[3]) Java, although the term is not in common use by the Java community. Call-by-sharing implies that values in the language are based on objects rather than primitive types. The semantics of call-by-sharing differ from call-by-reference in that assignments to function arguments within the function aren't visible to the caller (unlike by-reference sematics). However since the function has access to the same object as the caller (no copy is made), mutations to those objects within the function are visible to the caller, which differs from call-by-value semantics. Although this term has widespread usage in the Python community, identical semantics in other languages such as Java and Visual Basic are often described as call-by-value, where the value is implied to be a reference to the object. - http://www.pmg.csail.mit.edu/papers/thetaref/node34.html Call by Sharing The caller and called routine communicate only through the argument and result objects; routines do not have access to any variables of the caller. After the assignments of actual arguments to formal arguments, the caller and the called routine share objects. If the called routine modifies a shared object, the modification is visible to the caller on return. The names used to denote the shared objects are distinct in the caller and called routine; if a routine assigns an object to a formal argument variable, there is no effect on the caller. From the point of view of the invoked routine, the only difference between its formal argument variables and its other local variables is that the formals are initialized by its caller. == Python object *do* have access to surrounding scopes, but the second paragraph exact described Python, as does the corresponding Wikipedia entry. == myweb.lmu.edu/dondi/fall2004/cmsi585/subroutines-in-depth.pdf • Call by sharing – Used by languages where variables are already references to objects – Parameters are references to objects, but assignments to those parameters don’t change them at the level of the caller — e.g. Java uses call-by-value for primitives (int, char) and uses call-by-sharing for Objects --- And Google had other links to course notes using 'call by sharing' Terry Jan Reedy -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object [long and probably boring]
On Nov 7, 2008, at 12:13 PM, Terry Reedy wrote: Python has two types of names. Some complex objects -- modules, classes, and functions, and wrappers and subclasses thereof, have 'definition names' that are used instead of a 'value' to print a representation. Otherwise, names are identifiers, the term used in the grammar. But I agree even two meaning is one too many. Maybe 'label' would be a better short form for 'identifier'. 'Labeling' might be clearer for many beginners than 'name-binding'. I actually rather like identifier, though it seems a little too technical for casual use. On the other hand, label seems too arbitrary -- variable is a common term, and accurate enough to me. 'Variable' has many more meanings than 'name' or 'label' and overall seems to be more confusing, not less. I say this as an empirical observation of c.l.p postings. You yourself switched back and forth between two different meanings. Did I? What were they? I thought I had a clear idea what I mean by it (and, as far as I know, it's consistent with what everybody else means by it too). The only oddity in Python is that things you might not expect to be variables (such as module names) actually are. But that's a succinct way to express that observation; saying module names are variables too seems to imply all the right things (e.g. that you can assign new values to them, or assign them to other variables). I'm with you there. To me, the consistent simplicity is exactly this: all variables are object references, and these are always passed by value. To me, this implies that the corresponding parameter should become a reference to that reference value. Really? You've just described passing an object reference by reference. If passing a reference by value implies adding an additional reference to it, then what would passing a reference by reference mean to you? And, examining your thought process, can you explain where that implication came from? In any case, the last 10 years of this newsgroups shows that describing Python calling as 'by value' confuses people so that they are surprised that mutating a list inside a function results in the list being mutated outside the function. Yes, but that would happen ONLY when they also think that a variable actually contains the object data. And since there are many here trying to claim exactly that, I think that is the root cause of the problem, not calling parameter passing by value. And this belief (that the value of a variable is an object) leads to other mistaken beliefs too, such as that assignment should make a copy: x = y x.foo = bar Anyone surprised by the list mutation inside a function should also be surprised to find that y.foo = bar. I think we should simply address the root cause of that confusion, not try to redefine their understanding of how parameters are passed, and ALSO redefine what assignment means. But Python doesn't have those simple types, so there is a temptation to try to skip this generalization and say that references are not values, The Python Language Reference uses the word 'reference' but does not define it. I take it to be 'whatever information an interpreter uses to associate a name or collection slot with an object and to retrieve the object (and possibly its value) when requested'. Sure, that's fine. It doesn't really matter how it's implemented. What matters is that a name or collection slot somehow refers to an object, and whatever the form of that reference is, it is copied (*) to the LHS of an assignment or to the formal parameter of a function call. (*) I was going to say transferred but when something is transferred from A to B, it implies that B gains it and A loses it. Copied has the right implication: that afterwards, both A and B now have it. I'm only saying that Python variables don't contain any other type of value than references. One problem with the word 'variable' is that variables are somethings thought of as 'containing', as you did above. So you switch back and forth between 'variables *are* references' and 'variables *contain* references'. Perhaps this is the two meanings you mentioned above. I'm not sure I see any useful dichotomy here, though. In C, we say that this variable is an integer, that variable is a character, the one over there is a double. This is unambiguous shorthand for the declared type of this variable is such-and-so, and each such variable contains data of that type. So there's no harm in saying that a variable is an integer, or that a variable contains an integer, as the context requires. In Python, AFAICT, there is only one type, the object reference. So, the type of every variable is 'reference', and each one contains a reference. Whereas a name (noun) definitely *is* a reference and not a container. Yes, I'll grant
Re: Finding the instance reference of an object [long and probably boring]
On Nov 7, 2008, at 12:35 PM, Terry Reedy wrote: http://en.wikipedia.org/wiki/Call_by_something#Call_by_sharing Call by sharing Also known as call by object or call by object-sharing is an evaluation strategy first named by Barbara Liskov et al for the language CLU in 1974[1]. It is used by languages such as Python[2] and Iota and (as argued by some[3]) Java, although the term is not in common use by the Java community. Call-by-sharing implies that values in the language are based on objects rather than primitive types. The semantics of call-by-sharing differ from call-by-reference in that assignments to function arguments within the function aren't visible to the caller (unlike by-reference sematics). However since the function has access to the same object as the caller (no copy is made), mutations to those objects within the function are visible to the caller, which differs from call-by-value semantics. Although this term has widespread usage in the Python community, identical semantics in other languages such as Java and Visual Basic are often described as call-by-value, where the value is implied to be a reference to the object. You know, people rip on Wikipedia, but I'm often surprised at how frequently it succinctly and accurately describes a topic, even when it is a topic of much controversy. The above summary seems spot on. My difficulty, I guess, is that I'm coming from the Java/VB/RB community, where the semantics are exactly the same as Python, and where it makes perfect sense to call it call-by-value (since it is a trivial generalization of the very same evaluation strategy used on other types). But I get here, and there is widespread use of this call-by-sharing term (though my initial impressions were much more disparate and confusing than the above concise summary makes it sound). Thanks for pointing this out. I'd only found the entry on evaluation strategies, which makes no mention of call-by-sharing. http://www.pmg.csail.mit.edu/papers/thetaref/node34.html Call by Sharing The caller and called routine communicate only through the argument and result objects; routines do not have access to any variables of the caller. After the assignments of actual arguments to formal arguments, the caller and the called routine share objects. If the called routine modifies a shared object, the modification is visible to the caller on return. The names used to denote the shared objects are distinct in the caller and called routine; if a routine assigns an object to a formal argument variable, there is no effect on the caller. From the point of view of the invoked routine, the only difference between its formal argument variables and its other local variables is that the formals are initialized by its caller. == Python object *do* have access to surrounding scopes, but the second paragraph exact described Python, as does the corresponding Wikipedia entry. Well yes, but it exactly describes VB.NET, RB, Java, and C++ as well (when talking about object types rather than primitive types). == myweb.lmu.edu/dondi/fall2004/cmsi585/subroutines-in-depth.pdf • Call by sharing – Used by languages where variables are already references to objects – Parameters are references to objects, but assignments to those parameters don’t change them at the level of the caller — e.g. Java uses call- by-value for primitives (int, char) and uses call-by-sharing for Objects Well, not according to the Java specification, it doesn't. But these sources finally make it clear that call-by-sharing is just a special case of call-by-value when the value is an object reference. So, it's accurate to say that Java (and all the other languages under discussion) always use call-by-value, but some of those calls (depending on the parameter data type) may also be described as call- by-sharing. I suppose it's reasonable that if you use a language where some types are references and some types are not, the simplest thing is to describe all calls as call-by-value (except for those with an optional by-reference syntax, like C++ and RB/.NET). But if you come from a language where all types are references, then it's reasonable to describe all calls as call-by-sharing (provided the language doesn't also support call-by-reference). So. How about this for a summary? Python uses call-by-sharing. That's a special case of call-by-value where the variables are references to objects; it is these references that are copied to the parameters, not the objects themselves. For users of other languages, this is the same semantics used for objects in Java, RB/VB.NET, and C++ when dealing with objects. Best, - Joe -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object [long and probably boring]
Joe Strout [EMAIL PROTECTED] writes: So. How about this for a summary? Python uses call-by-sharing. That's a special case of call-by-value where the variables are references to objects; it is these references that are copied to the parameters, not the objects themselves. For users of other languages, this is the same semantics used for objects in Java, RB/VB.NET, and C++ when dealing with objects. Here's a story about call by sharing: One day a black cat came strolling into our garden. It seemed quite hungry so we gave it some milk and food remains. The cat drank the milk and ate the food, stayed for a bit then walked away. A couple of days later it came back, miaowing, so we fed it again. It started coming to see us almost every day, sometimes sleeping in the house, sometimes disappearing for a day or two. We started thinking of it as our cat and we *named* it Napoleon. Napoleon became very popular and stayed at home more and more often, and very young son was very fond of it, calling it something like 'Polion'. Unfortunately Napoleon got infested with fleas and we had to take him to the vet. The vet scanned Napoleon with a little machine and discovered that it had an ID chip. This revealed that Napoleon was really called Nelson (ironically!) and belonged to a house down our road. We contacted them and they were happy to 'share' the cat with us. By this time the cat answered to the name of Napoleon so we carried on calling it this name. This story ends quite sadly. One day Napoleon escaped out the front door and got run over by a passing van. Our son kept asking for Polion so we decided to get a new cat and called him Napoleon as well (we decided it would be easier for him!). Now some questions about the story: 1. Is Napoleon a copy of Dobby or are they the same cat? 2. Is Polion a copy of Napoleon or are they the same cat? 3. When we got rid of Napoleon's fleas, was Nelson deflea-ed as well? 4. When Napoleon died, did Nelson die as well? 5. When we got a new Napoleon, does this mean that our neighbours got a new Nelson? Now a question about the questions about the story: To be able to understand the story and answer questions 1-5, do we need to think of Napoleon, Nelson and Polion as variables containing references to cat objects, or is it enough to think of them as three names for cats? -- Arnaud -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object [long and probably boring]
Joe Strout wrote: On Nov 7, 2008, at 12:13 PM, Terry Reedy wrote: [...] I wonder if that could be tested systematically. Perhaps we could round up 20 newbies, divide them into two groups of 10, give each one a 1-page explanation either based on passing object references by-value, or passing values sort-of-kind-of-by-reference, and then check their comprehension by predicting the output of some code snippets. That'd be very interesting. Except for your garbling of the alternative to your version, I agree. I suspect that different people might do better with different explanations, depending on background. Could be. Maybe we could run such an experiment at PyCon, pulling in non-attendees from the hallway and getting them to take the test in exchange for a free donut or coffee. +1: great idea! It would make a good video too ... regards Steve -- Steve Holden+1 571 484 6266 +1 800 494 3119 Holden Web LLC http://www.holdenweb.com/ -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object [long and probably boring]
On Nov 7, 3:03 pm, Arnaud Delobelle [EMAIL PROTECTED] wrote: Joe Strout [EMAIL PROTECTED] writes: So. How about this for a summary? Python uses call-by-sharing. That's a special case of call-by-value where the variables are references to objects; it is these references that are copied to the parameters, not the objects themselves. For users of other languages, this is the same semantics used for objects in Java, RB/VB.NET, and C++ when dealing with objects. Here's a story about call by sharing: One day a black cat came strolling into our garden. It seemed quite hungry so we gave it some milk and food remains. The cat drank the milk and ate the food, stayed for a bit then walked away. A couple of days later it came back, miaowing, so we fed it again. It started coming to see us almost every day, sometimes sleeping in the house, sometimes disappearing for a day or two. We started thinking of it as our cat and we *named* it Napoleon. Napoleon became very popular and stayed at home more and more often, and very young son was very fond of it, calling it something like 'Polion'. Unfortunately Napoleon got infested with fleas and we had to take him to the vet. The vet scanned Napoleon with a little machine and discovered that it had an ID chip. This revealed that Napoleon was really called Nelson (ironically!) and belonged to a house down our road. We contacted them and they were happy to 'share' the cat with us. By this time the cat answered to the name of Napoleon so we carried on calling it this name. This story ends quite sadly. One day Napoleon escaped out the front door and got run over by a passing van. Our son kept asking for Polion so we decided to get a new cat and called him Napoleon as well (we decided it would be easier for him!). Now some questions about the story: Sorry didn't read above yet. 1. Is Napoleon a copy of Dobby or are they the same cat? Same cat. 2. Is Polion a copy of Napoleon or are they the same cat? Same cat. 3. When we got rid of Napoleon's fleas, was Nelson deflea-ed as well? Yes. 4. When Napoleon died, did Nelson die as well? No, honey. He lives on in all of us. 5. When we got a new Napoleon, does this mean that our neighbours got a new Nelson? No, darling, Nelson is just sleeping. When we got a New Orleans, where did the old one go? Now a question about the questions about the story: To be able to understand the story and answer questions 1-5, do we need to think of Napoleon, Nelson and Polion as variables containing references to cat objects, or is it enough to think of them as three names for cats? I think they are names, implying that Python has a different variable model than C++. However, a[0] isn't exactly a name, per se, and if you say that 'b' and 'a[0]' are names of an object, then 'a[1-1]', 'a[2*0]', etc. are all names of it. Furthermore, some class models variables like this: a.b= 'abc' a.c= 'def' a.d= 'ghi' It also allows index access: a[0], a[1], a[2], respectively. 'abc' has two names: 'a.b', and 'a[0]'. Correct? -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object [long and probably boring]
Aaron Brady [EMAIL PROTECTED] writes: Furthermore, some class models variables like this: a.b= 'abc' a.c= 'def' a.d= 'ghi' It also allows index access: a[0], a[1], a[2], respectively. 'abc' has two names: 'a.b', and 'a[0]'. Correct? You know very well that a.b and a[0] aren't names, they are function calls written in short hand ;) a.b is getattr(a, 'b') a[0] is getattr(a, '__getitem__')(0) So they just return an object, which happens to be the same :) -- Arnaud -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
Joe Strout [EMAIL PROTECTED] writes: As for where I get my definitions from, I draw from several sources: 1. Dead-tree textbooks You've been reading the wrong textbooks. Read Liskov -- she's called CLU (and hence Python's) calling strategy call-by-sharing since the 70s. 2. Wikipedia [2] (and yes, I know that has to be taken with a grain of salt, but it's so darned convenient) 3. My wife, who is a computer science professor and does compiler research 4. http://javadude.com/articles/passbyvalue.htm (a brief but excellent article) 5. Observations of the ByVal (default) mode in RB and VB.NET 6. My own experience implementing the RB compiler (not that implementation details matter, but it forced me to think very carefully about references and parameter passing for a very long time) Not that I'm trying to argue from authority; I'm trying to argue from logic. I suspect, though, that your last comment gets to the crux of the matter, and reinforces my guess above: you don't think c-b-v means what most people think it means. Indeed, you don't think any of the languages shown at [1] are, in fact, c-b-v languages. If so, then we should focus on that and see if we can find a definitive answer. I'll give you the definitive answer from a position of authority, then. I took Barbara Liskov's graduate-level class in programming language theory at MIT, and she called what Python does call-by-sharing. |oug -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
Joe Strout [EMAIL PROTECTED] writes: Yes, OK, that's great. But there are several standard pass-by- somethings that are defined by the CS community, and which are simple and clear and apply to a wide variety of languages. Pass by object isn't one of them. Call-by-sharing *is* one of them, and the term has been around since the 70s: http://hopl.murdoch.edu.au/showlanguage.prx?exp=637 I guess if you want to campaign for it as a shorthand for object reference passed by value, you could do that, and it's not outrageous. There's no need for a campaign. The term has already been used in the academic literature for 34 years. But to anybody new to the term, you should explain it as exactly that, rather than try to claim that Python is somehow different from other OOP languages where everybody calls it simply pass by value. It's not true that everybody calls it simply pass by value. OK, if there were such a thing as pass-by-object in the standard lexicon of evaluation strategies, I would be perfectly happy saying that a system has it if it behaves as though it has it, regardless of the underpinnings. There is call-by-sharing in the standard lexicon of evaluation strategies, and it's been in the lexicon since 1974. However, if you really think the term is that handy, and we want to agree to say Python uses pass by object and answer the inevitable huh? question with that's shorthand for object references passed by value, then I'd be OK with that. Excellent. We can all agree to get along then! |oug -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object [long and probably boring]
On Nov 7, 3:39 pm, Arnaud Delobelle [EMAIL PROTECTED] wrote: Aaron Brady [EMAIL PROTECTED] writes: Furthermore, some class models variables like this: a.b= 'abc' a.c= 'def' a.d= 'ghi' It also allows index access: a[0], a[1], a[2], respectively. 'abc' has two names: 'a.b', and 'a[0]'. Correct? You know very well that a.b and a[0] aren't names, they are function calls written in short hand ;) a.b is getattr(a, 'b') a[0] is getattr(a, '__getitem__')(0) So they just return an object, which happens to be the same :) -- Arnaud Therefore objects don't need names to exist. Having a name is sufficient but not necessary to exist. Being in a container is neither necessary -nor- sufficient. a is the name of an object. The object is associated with a dictionary you can usually access. 'b' is a key in the dictionary. -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
Steven D'Aprano wrote: Python's behaviour is not the same as what Pascal, or C, calls call-by-value. Python's assignment is not the same as what Pascal or C calls assignment, either. Yet we don't hear anyone claim that the term assignment shouldn't be used in Python. The difference between call-by-value in Python and Pascal is exactly the same difference as there is between assignment in Python and Pascal. Why should we throw out one term but not the other? -- Greg -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object [long and probably boring]
In an attempt to keep this post from hitting the ridiculous length of one of my posts last night, I'm going to skip over a lot of things Joe writes that aren't critical. Just because I've skipped over a comment doesn't mean I agree with it, merely that I don't think it gains much to argue the point. On Fri, 07 Nov 2008 11:55:21 -0700, Joe Strout wrote: What would it take to convince you that Java and C have exactly the same semantics, and differ only in syntax? Would equivalent code snippets that do the same thing do the job? Of course not. You would also have to demonstrate that there is nothing you can do in C that can't be done directly in Java, and vice versa. I say directly, because once you allow indirect techniques, you can do all sorts of things. Here's an indirect proof that Python is call-by- reference: def swap(x, y): Swap the values referred to by x and y. x[0], y[0] = y[0], x[0] x = [2] y = [3] swap(x, y) assert x == [3] and y == [2] See, Python is call-by-reference!!! Not. Here's a short C snippet: #include stdio.h #include stdlib.h struct record { int x; int y; int z; }; void mutate(struct record p) { p.x = 0; printf(Inside: %d %d %d\n, p.x, p.y, p.z); } struct record A; int main(void) { A.x = 1; A.y = 1; A.z = 1; printf(Outside: %d %d %d\n, A.x, A.y, A.z); mutate(A); printf(Outside: %d %d %d\n, A.x, A.y, A.z); return 0; } It prints: Outside: 1 1 1 Inside: 0 1 1 Outside: 1 1 1 Note that mutations to the struct inside the function aren't visible outside the function. This is typical call-by-value behaviour: the argument is copied. How do you get this behaviour in Java without relying on tricks and indirect techniques as in the Python code above? (Aside: I've learned one thing in this discussion. Despite the number of sources I've read that claim that if you pass an array to a C function the entire array will be copied, this does not appear to be true. Perhaps C is more like Java than I thought. Or perhaps my C coding skills are even more pathetic than I thought.) [...] Personally, they would have to be pretty big to make me give up saying that the value of x after x=1 is 1. I've stated repeatedly that this is fine shorthand. You only get into trouble when, instead of assigning 1, you are assigning (a reference to) some mutable object. Then you have to think about whether you are copying the data or just copying a reference to it. Please explain the nature of this trouble that you describe, specifically in the context of Python. If you understand the Python model (call-by-sharing, assignment is binding to names and not an operation on objects) then there is no such trouble *unless* you insist on interpreting things otherwise. You have a choice: give up the commonsense meaning of the word value merely to allow you to claim Python is call-by-value (where value is a pointer to the value you care about). Or you can keep the commonsense definition of value (that which a symbol represents) and stop claiming that Python is call-by-value. [...] You shouldn't change the definition of value in order to hammer the square peg of your language into the round hole of call-by-value I'm not changing the definition of value, I'm merely being precise about it. And yet you keep needing to say where the value is a reference. The fact that you need to do this proves that what you are doing is surprising to people. If I want somebody to put a book on top of a box sitting on a table, I don't feel the need to say Put the book on top of the box, where the top is the part of the box pointing towards the sky. That's understood, from the ordinary meaning of the word. But you say Put the book on top of the box, where the top is the part of the box in contact with the table., and then argue black and blue that for primitive boxes, the top points to the sky but for all the other boxes, the top points to the ground. You only need to give that explanation because you're changing the definition. When I execute x=1 and then say the value of x is 1, I don't need to explain what I mean by value because I'm using the general meaning of the word: that which a symbol represents. In Python code, the symbol x represents the object 1. It doesn't matter whether 1 is a primitive or an object, or whether 1 is mutable or immutable. But you insist on an extra layer of indirection, because you want to talk about an implementation detail and give value a non-standard meaning: value, to you, is a reference to the thing which the symbol represents. But only for certain things. For other things, the value is the thing itself. This isn't precision, it's obfuscation, partly because it complicates the meaning of value, but more importantly because you're not talking at the relevant level any more. You're not discussing the Python object model, or the behaviour of Python code, you're discussing one specific
Re: Finding the instance reference of an object [long and probably boring]
On Fri, 07 Nov 2008 13:05:16 -0700, Joe Strout wrote: In Python, AFAICT, there is only one type, the object reference. So, the type of every variable is 'reference', and each one contains a reference. This is wrong. If we take variable to mean name, then Python names do not have types. But *objects* have types, and there are many of them: a = 23; type(a) type 'int' a = foo; type(a) type 'str' a = []; type(a) type 'list' But a name that isn't bound to an object doesn't have a type: del a; type(a) Traceback (most recent call last): File stdin, line 1, in module NameError: name 'a' is not defined The type information is associated with the object, not with the name. It is possible that, in the C implementation, there is a C-type 'reference' and all(?) C variables relating to the implementation of namespaces have that type. Possibly. But even if true, that's the wrong level of description. -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
On Sat, 08 Nov 2008 17:12:00 +1300, greg wrote: Steven D'Aprano wrote: Python's behaviour is not the same as what Pascal, or C, calls call-by-value. Python's assignment is not the same as what Pascal or C calls assignment, either. Yet we don't hear anyone claim that the term assignment shouldn't be used in Python. Er, you're not from around here are you? I admit that sometimes I slip into bad habits, but generally the accepted terminology is that x = 1 binds the object 1 to the name x. The difference between call-by-value in Python and Pascal is exactly the same difference as there is between assignment in Python and Pascal. Why should we throw out one term but not the other? Exactly. -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
Marc 'BlackJack' Rintsch wrote: You have said the value that is copied is a pointer to the object. This assumes that call by value means call by copying the value. That assumption is WRONG. It doesn't mean that. It means call by ASSIGNING the value. So, you can think of the value of an expression as being an object, as opposed to a reference to an object, if you want. But then you need to consider what it means to assign that value to a name. Obviously it doesn't mean copying the value -- it must mean making the name refer to the value somehow. The same thing happens when the value is passed to a function. -- Greg -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
Arnaud Delobelle wrote: 'Pass by value' is not relevant to Python as variables do not contain anything. Where abouts in the phrase pass by value does the word contain appear? You don't need a notion of containment in order for pass by value to have meaning. All you need is some notion of a value (it doesn't matter what) and some way to pass that value. 'Pass by reference' is not relevant to Python as the language doesn't have the concept of object reference (in the sense of e.g. C++ reference). What it doesn't have is the concept of a *variable* reference, which is what the reference in pass by reference means. Here lies, IMHO, the reason why you think you need Python to 'pass by value'. As you believe that variables must contain something, you think that assignment is about copying the content of a variable. Assignment in Python is simply giving a new name to an object. Yes, and so is passing by value! -- Greg -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
Joe Strout wrote: On Nov 5, 2008, at 2:06 PM, Lie wrote: Another example: pass-by-object. Here's where we depart, I guess. I think there's no such thing (see http://en.wikipedia.org/wiki/Evaluation_strategy for example, and the dead-tree references I have on hand agree). Something has just occurred to me. If you take the view that the value of an expression is an object, then the terms value and object are synonymous. So if you then insist that Python uses call by object, you're actually saying it uses call by value! -- Greg -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
On Sat, 08 Nov 2008 18:31:47 +1300, greg wrote: Marc 'BlackJack' Rintsch wrote: You have said the value that is copied is a pointer to the object. This assumes that call by value means call by copying the value. That assumption is WRONG. Not according to my Comp Sci lecturers back in the day, and not according to my Pascal books. E.g. Programming In Pascal, 2nd Edition (1985), by Peter Grogono of Concordia University refers to value parameters and variable parameters to refer to the standard Pascal call-by-value convention and the call-by-reference convention you get when you declare a parameter with the var keyword. He writes: When an object is passed to a procedure by value, a local copy of it is made. If the object is a large array, the copying operation will make the program slower and will increase its memory requirements. This was written as an undergraduate textbook. Remember that in 1985, OOP was far more exotic than now, and object in the above means any Pascal type (integer, array, set etc.) and not object as we understand it today. Grogono doesn't explicitly use the terms call-by-value and call-by- reference, but my lecture notes from the time make it clear that the Melbourne University Comp Sci department understood those terms to imply Pascal calling semantics. It doesn't mean that. It means call by ASSIGNING the value. Which, in languages like Pascal, means COPYING the value. And that leads to confusion when people who understand C-B-V to mean what Pascal means by the term hear that Python is C-B-V. So, you can think of the value of an expression as being an object, as opposed to a reference to an object, if you want. That's the natural interpretation based on the ordinary meaning of the word value. In a language like Python that doesn't have references, it's the only sensible interpretation. Otherwise you're forced to argue that following a statement x=1, the value of x is something that has no existence in Python code. But then you need to consider what it means to assign that value to a name. But you need to do that anyway. Here's a simple C program: struct Rec { int x; }; struct Rec a; struct Rec b; int main(void) { a.x = 1; b = a; printf(Before: %d %d\n, a.x, b.x); a.x += 1; printf(After: %d %d\n, a.x, b.x); return 0; } It prints: Before: 1 1 After: 2 1 Here's a simple Python equivalent: class Rec: pass a = Rec() a.x = 1 b = a print Before: %d %d % (a.x, b.x) a.x += 1 print After: %d %d % (a.x, b.x) It prints: Before: 1 1 After: 2 2 Anyone want to argue that assignment in Python is the same as in C? Obviously it doesn't mean copying the value -- it must mean making the name refer to the value somehow. There's no obviously about it. To anyone who has learned that call-by- value means that a copy is made, obviously it does mean copying the value. If you have learned a different meaning, then you will believe differently. The same thing happens when the value is passed to a function. Sure. Calling conventions in Python are the same as name/value binding, except that you have a slight extra complication due to having two namespaces instead of one. -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
On Sat, 08 Nov 2008 19:30:17 +1300, greg wrote: Something has just occurred to me. If you take the view that the value of an expression is an object, then the terms value and object are synonymous. So far so good. So if you then insist that Python uses call by object, you're actually saying it uses call by value! Fail! The terms guy and man are synonymous, but a wise guy and a wise man are not. -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
On Nov 5, 2008, at 12:29 AM, Dennis Lee Bieber wrote: C++: void foo(PersonPtr who) { who-zipcode = 12345; } Please show us the type definition of PersonPtr Sorry, that'd be obvious to anyone experienced in C++, but I shouldn't assume. It would be: typedef Person* PersonPtr; It's a pretty standard idiom, precisely because it is so much more common to need a variable of the pointer type than of the class type itself. Java: void foo(Person who) { who.zipcode = 12345; } Please show us the type definition of Person No. It's a class, and you can see that it defines a zipcode member; nothing more is needed for the sake of this example. (The Java designers realized that needing object reference variables is so overwhelmingly more common than needing non-pointer variables, that they eliminated the pointer syntax and made every variable of object type actually a pointer to the object data, just as in RB, .NET, and Python.) REALbasic/VB.Net: Sub foo(ByVal who as Person) who.zipcode = 12345 End Sub Note they YOU, as the programmer, explicitly told the language to use a call-by-value Correct; these languages support both call-by-value and call-by- reference. ByVal is the default, but you can still specify it (as I've done here) if you want to be explicit. -- and you still have not shown us the definition of Person Right, again, there is nothing you need to know about it not already evident from the example. Python: def foo(who): who.zipcode = 12345 Note that there is NO PROGRAMMER CONTROL over the passing mechanism. Quite right. (Same too in Java.) Some languages offer both call-by- value and call-by-reference; but Java and Python offer only call-by- value. 5. You see that the first three languages above are passing a reference by value and using that to mutate and object, yet for reasons still mysterious, the Python example (which has exactly the same behavior) must be doing something different. I do not... I see the programmer telling the language that a reference is to be taken of some object and that this reference is /then/ to be passed. Quite right (and that's what I said). The reference is being passed. By value. And then that reference is used to mutate an object. AND the programmer is also (C++) explicitly dereferencing (by use of -)! Yep, - is the dereference operator in C++; in Java, RB, .NET, and Python, it's .. Different characters, same meaning. The syntax, in C/C++ is different for accessing the parameter by value vs by reference (pointer -- C++ is smarter in that it allows declaring the parameter as a ref and the language automatically takes the address on the caller's side, and dereferences on the called side -- but that notation is STILL a programmer responsibility). Careful here -- a ref parameter really is passed by reference; that's not the same as passing a pointer by value, which is what's shown above. It's the C++ equivalent of the ByRef keyword in RB/VB.NET. Java passes /objects/ by reference, but passes native types (base numerics) by value No, it passes everything by value. who in the Java example is not an object; it is an object reference. It was passed by value. If it were passed by reference, you'd be able to make a swap function that exchanges the objects referred to by two variables, but you can't. This is explained more fully here: http://javadude.com/articles/passbyvalue.htm -- can you create a Java example where you pass a base numeric by reference? No, because Java (like Python) has only call-by-value. By your argument, even FORTRAN is call-by-value. No, FORTRAN's an oddball: it passes everything by reference. You obfuscate the mechanics used at the machine language level with the semantics of the language itself. No, I haven't said anything at all about what's happening at the machine language level, and I frankly don't care. This is about how the language behaves. FORTRAN is the language commonly used to explain call-by-reference! Quite right. So, please try to convert any of those FORTRAN explanations into Python or Java. Can't be done. In C++ or RB/ VB.NET, it can be done only by using the special by-reference syntax ( or ByRef). I'm not sure where you got the idea that I thought FORTRAN is call-by- value. I never said or implied any such thing. And the examples above aren't meant to prove that those languages are using by-value; they're meant to show that mutating an object via a reference passed in proves NOTHING about how that reference was passed. This is to invalidate the argument (frequently heard around here) that Python must use call-by-reference since you can mutate an object passed to a function. As should be painfully clear by now, that argument is total bunk. You can pass an object reference by value, and use it to
Re: Finding the instance reference of an object
On Nov 4, 2008, at 12:57 PM, Hendrik van Rooyen wrote: 4. You now see how a mutating an object within a function tells you NOTHING about how the reference to that object was passed. 5. You see that the first three languages above are passing a reference by value and using that to mutate and object, yet for reasons still mysterious, the Python example (which has exactly the same behavior) must be doing something different. This is dialectic nit picking - WTF makes passing a reference by value different from passing a reference - the salient point is that its a reference that is passed I know it seems nit-picky on the surface, but it is important. It is the distinction that lets you answer whether: def foo(x): x = Foo() x = Bar() foo(x) ...results in x (after the call) now referring to a Foo, or still referring to a Bar. If x is a reference passed by value, then the assignment within the foo method can't affect the x that was passed in. But if it is passed by reference, then it does. (Also, if it is passed by reference, then you probably wouldn't be able to pass in a literal or computed value, but only a simple variable.) - would you expect another level of indirection - a reference to the reference, or what, before you admit that the thing that is passed is a reference and not a copied value of the OBJECT that is of interest. Um, no, I've admitted that it's a reference all along. Indeed, that's pretty much the whole point: that variables in Python don't contain objects, but merely contain references to objects that are actually stored somewhere else (i.e. on the heap). This is explicitly stated in the Python docs [1], yet many here seem to want to deny it. Looks to me that even if there were ten levels of indirection you would still insist that its a pass by value because in the end, its the actual memory address of the first pointer in the queue that is passed. No, it's entirely possible for an OOP language to have pass by reference, and, to put it your way, this adds one more level of indirection. Look at the C++ and RB/VB.NET examples at [2]. But Python and Java do not offer this option. If that is what you mean, it is obviously trivially true - but then ALL calling can only be described as call by value - which makes nonsense of what the CS people have been doing all these years. That would indeed be nonsense. But it's also not what I'm saying. See [2] again for a detailed discussion and examples. Call-by-value and call-by-reference are quite distinct. Calling by value is not a useful definition of Pythons behaviour. It really is, though. You have to know how the formal parameter relates to the actual parameter. Is it a copy of it, or an alias of it? Without knowing that, you don't know what assignments to the formal parameter will do, or even what sort of arguments are valid. Answer: it's a copy of it. Assignments don't affect the actual parameter at all. This is exactly what call by value means. Best, - Joe [1] http://www.python.org/doc/2.5.2/ext/refcounts.html [2] http://www.strout.net/info/coding/valref/ -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
I know this thread has grown quite personal for some of its participants. I am posting in a spirit of peace and understanding :) Joe Strout [EMAIL PROTECTED] writes: [...] Um, no, I've admitted that it's a reference all along. Indeed, that's pretty much the whole point: that variables in Python don't contain objects, but merely contain references to objects that are actually stored somewhere else (i.e. on the heap). This is explicitly stated in the Python docs [1], yet many here seem to want to deny it. You refer to docs about the *implementation* of Python in C. This is irrelevant. Also, you talk about variables 'containing' something. In Python, variables don't contain anything, they're simply names for objects. 'Pass by value' is not relevant to Python as variables do not contain anything. 'Pass by reference' is not relevant to Python as the language doesn't have the concept of object reference (in the sense of e.g. C++ reference). [...] Calling by value is not a useful definition of Pythons behaviour. It really is, though. You have to know how the formal parameter relates to the actual parameter. Is it a copy of it, or an alias of it? Without knowing that, you don't know what assignments to the formal parameter will do, or even what sort of arguments are valid. Answer: it's a copy of it. Assignments don't affect the actual parameter at all. This is exactly what call by value means. Here lies, IMHO, the reason why you think you need Python to 'pass by value'. As you believe that variables must contain something, you think that assignment is about copying the content of a variable. Assignment in Python is simply giving a new name to an object. To understand variables (which I prefer to call 'names') and function calls in Python you need simply to understand that: - a variable is a name for an object - assignment is naming an object - the parameters of a function are local names for the call arguments (I guess 'pass by object' is a good name). Now quoting the start of your post: On Nov 4, 2008, at 12:57 PM, Hendrik van Rooyen wrote: 5. You see that the first three languages above are passing a reference by value and using that to mutate and object, yet for reasons still mysterious, the Python example (which has exactly the same behavior) must be doing something different. This is dialectic nit picking - WTF makes passing a reference by value different from passing a reference - the salient point is that its a reference that is passed I would say that an oject is passed, not a reference. I know it seems nit-picky on the surface, but it is important. It is the distinction that lets you answer whether: def foo(x): x = Foo() x = Bar() foo(x) ...results in x (after the call) now referring to a Foo, or still referring to a Bar. You don't need this to decide. This is what happens: x = Bar() # Call this new Bar object 'x' foo(x)# call function foo with argument the object known as 'x' # Now, in foo: def foo(x): # Call 'x' locally the object passed to foo x = Foo() # Call 'x' locally this new Foo object. Obviously after all this, 'x' is still the name of the Bar object created at the start. To sum up: for 'pass by value' to make sense in Python you need to create an unnecessarily complex model of how Python works. By letting go of 'pass by value' you can simplify your model of the language (keeping it correct of course) and it fits in your brain more easily. Of course your own model is valid but there is a better one which is easier to grasp for people without a background in C/C++ - like languages. -- Arnaud -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
On Nov 6, 1:44 pm, Arnaud Delobelle [EMAIL PROTECTED] wrote: I know this thread has grown quite personal for some of its participants. I am posting in a spirit of peace and understanding :) Hear, hear. You refer to docs about the *implementation* of Python in C. This is irrelevant. Also, you talk about variables 'containing' something. In Python, variables don't contain anything, they're simply names for objects. 'Pass by value' is not relevant to Python as variables do not contain anything. 'Pass by reference' is not relevant to Python as the language doesn't have the concept of object reference (in the sense of e.g. C++ reference). ... I would say that an oject is passed, not a reference. ... To sum up: for 'pass by value' to make sense in Python you need to create an unnecessarily complex model of how Python works. By letting go of 'pass by value' you can simplify your model of the language (keeping it correct of course) and it fits in your brain more easily. Of course your own model is valid but there is a better one which is easier to grasp for people without a background in C/C++ - like languages. I agree, and I don't think we're giving Joe the proper credit for what he knows and has worked on. Furthermore, his understanding of the implementation of languages is thorough, and you can't have languages without implementations. Though, you do not need to understand the implementation to understand the language. I haven't thought it through completely, but now that Joe mentions it, it appears Python behaves the same as C++, if variables can't be anything but pointers, parameters are all c-b-v, and you can't dereference the l-h-s of an assignment ( '*a= SomeClass()' ). When you're explaining Python to a beginner, you have to introduce a new term either way. You'll either have to explain pointers, which there are chapters and chapters on in introductory textbooks; or, you'll have to explain a new calling mechanism, and give it a name. I think pointer-by-value would be accurate, but by-value wouldn't be. I would say that an oject is passed, not a reference. I agree, and anything else would be overcomplicated. -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
On Nov 5, 2008, at 2:06 PM, Lie wrote: http://www.strout.net/info/coding/valref/ I'm fed up with you. I'm sorry -- I'm really not trying to be difficult. And it's odd that you're fed up with me, yet you seem to be agreeing with me on at least most points. In Von Neumann Architecture computers, only pass-by-value is natively supported. Other idioms are made on top of pass-by-value. Well, sure. But a language may or may not naturally support the others. That's why exclusively pass-by-value languages like C is most flexible than other exclusively pass-by-insertanythinghere. BUT the difference is clear, if you want to do pass-by-reference in C (I prefer to call it faux pass-by-reference), you'd have to manually find a variable's address, pass it by-value, then dereference the address. Agreed. Compare with VB's ByRef or C++'s , which does all that _automatically_ for you behind the scene. Agreed again. Another example: pass-by-object. Here's where we depart, I guess. I think there's no such thing (see http://en.wikipedia.org/wiki/Evaluation_strategy for example, and the dead-tree references I have on hand agree). I disagree with the term pass-by-object-reference, since the notion of object reference is unnecessary in a true pass-by-object mechanism (i.e. we should travel outside VNA realm for a true pass-by-object mechanism). Problem is: I'm not aware of any computer architecture that can accommodate pass-by-object natively or whether such architecture is feasible to be made. I don't think it's necessary (or helpful) to reach down into the architecture or implementation details. What matters is the behavior as seen by the language user. Variables in a language could hold actual object data (in which case a = b would copy the data from b into a), or they could hold just references to object data that lives elsewhere (in which case a = b would copy that reference, giving you two references to the same object). In Python, they are of course just references. Then, and completely independent of that, variables could be passed into a method by value or by reference (or by several other more esoteric evaluation strategies that are rarely used, but call by object isn't one of them). Again, it's easy to tell these apart with a simple behavioral test. Python passes its object references by value; changes to the formal parameter have no effect on the actual parameter. In pass-by-object, the whole object is passed around, not a copy of the object like in pass-by-value or a copy of the pointer to the object like in faux pass-by-reference. I can't understand what that would mean, unless we imagine the variable actually containing the object data; but it doesn't, or a = b would copy that data, which clearly it does not. Understanding that a name in Python is merely a reference to the object, and not the object itself, seems to me to be one of the fundamental truths that any beginning Python programmer must know. This makes pass-by-object actually closer to pass-by-reference than to pass-by-value, since the notion of VNA's requirement for Object Reference means passing pointers around. But don't let it confuse you, the pass-by-object mechanism itself does not recognize Object Reference, unlike pass-by- reference recognition of reference/pointer. Sorry, it's confusing me whether I want it to or not. And here's what I don't understand: object references are so simple, why do people go to such great lengths to pretend that Python doesn't have them, resulting in a far more complex and convoluted explanation that is much harder to understand? Now that I have clearly defined the line between pass-by-object and pass-by-value, I'm left with you thinking what's the difference between pass-by-object and pass-by-reference. If they're that hard to tell apart, then Python doesn't have either, since it is very clear and obvious that Python does not have pass-by- reference (since you can't write a function to swap two parameters, for example). In pass-by-reference, names are _mnemonic to location in memory_. In pass-by-object, names are _mnemonic to objects_. These would be equivalent if objects live at some location in memory, wouldn't they? In pass-by-reference, when we assign a value to the name, we'd assign a value _to the location in memory_. In pass-by-object, when we assign a value to the name, we assign an object _to the name_. When passing parameters, pass-by-reference systems passed the memory address and alias that memory address to a local name. In pass-by-object system, since the object itself has no idea of its own name, so it is rebound to a local name. You can say that pass-by-reference system is memory-location-centered, while pass- by-object system is name-centered. Hmm. I can only interpret the object is rebound to a local name sounds the same to me as a local variable is assigned a reference to the
Re: Finding the instance reference of an object
On Nov 6, 2008, at 12:44 PM, Arnaud Delobelle wrote: I know this thread has grown quite personal for some of its participants. I am posting in a spirit of peace and understanding :) Thanks, I'll do the same. Um, no, I've admitted that it's a reference all along. Indeed, that's pretty much the whole point: that variables in Python don't contain objects, but merely contain references to objects that are actually stored somewhere else (i.e. on the heap). This is explicitly stated in the Python docs [1], yet many here seem to want to deny it. You refer to docs about the *implementation* of Python in C. This is irrelevant. It's supportive. I don't understand how/why anybody would deny that Python names are references -- it's all over the place, from any discussion of reference counting (necessary to understand the life cycle of Python object) to understanding the basics of what a = b does. It seems absurd to argue that Python does NOT use references. So the official documentation calmly discussing Python references, with no caveats about it being internal implementation detail, seemed relevant. Also, you talk about variables 'containing' something. In Python, variables don't contain anything, they're simply names for objects. You say names for, I say references to. We're saying the same thing (though I'm saying it with terminology that is more standard, at least in the wider OOP world). 'Pass by value' is not relevant to Python as variables do not contain anything. 'Pass by reference' is not relevant to Python as the language doesn't have the concept of object reference (in the sense of e.g. C++ reference). Both are relevant to answering simple questions, like what happens to x in this case: def foo(spam): spam = 5 foo(x) This is a basic and fundamental thing that a programmer of a language should know. If it's call-by-reference, then x becomes 5. If it's call-by-value, it does not. Why the resistance to these simple and basic terms that apply to any OOP language? Here lies, IMHO, the reason why you think you need Python to 'pass by value'. As you believe that variables must contain something, you think that assignment is about copying the content of a variable. Assignment in Python is simply giving a new name to an object. What does give a new name to an object mean? I submit that it means exactly the same thing as assigns the name to refer to the object. There certainly is no difference in behavior that anyone has been able to point out between what assignment does in Python, and what assignment does in RB, VB.NET, Java, or C++ (in the context of object pointers, of course). If the behavior is the same, why should we make up our own unique and different terminology for it? To understand variables (which I prefer to call 'names') and function calls in Python you need simply to understand that: - a variable is a name for an object A reference to an object, got it. - assignment is naming an object Assigning the reference to the object, yes. - the parameters of a function are local names for the call arguments Agreed; they're not aliases of the call arguments. (I guess 'pass by object' is a good name). Well, I'm not sure why that would be. What you've just described is called pass by value in every other language. I would say that an oject is passed, not a reference. That seems to contradict the actual behavior, as well as what you said yourself above. The only way I know how to interpret an object is passed is the data of that object is copied onto the stack. But of course that's not what happens. What actually happens is what you said above: a name (reference) is assigned to the object. The name is a reference; it is made to refer to the same thing that the argument (actual parameter) referred to. This is exactly what the reference is passed means, nothing more or less. I know it seems nit-picky on the surface, but it is important. It is the distinction that lets you answer whether: def foo(x): x = Foo() x = Bar() foo(x) ...results in x (after the call) now referring to a Foo, or still referring to a Bar. You don't need this to decide. This is what happens: x = Bar() # Call this new Bar object 'x' In other words, make 'x' refer to this new object. foo(x)# call function foo with argument the object known as 'x' Yes. But what does that mean? Does the parameter within 'foo' become an alias of x, or a copy of it? That's what we DO need to decide. # Now, in foo: def foo(x): # Call 'x' locally the object passed to foo I think you mean here that local 'x' is made to refer to the object passed to foo. Agreed. It is NOT an alias of the actual parameter. And that's what we need to know. So it's not call-by-reference, it's call-by-value; the value of x (a reference to whatever object Bar() returned) is copied from the
Re: Finding the instance reference of an object
Aaron Brady wrote: and you can't have languages without implementations. This is either a claim that languages are their own implementations, or an admission that human brains are the implementation of all languages thought of by human brains, coupled with a claim that there cannot be languages not thought of by humans, or just wrong in terms of the common meaning of algorithmic implementation of an interpreter. There are many algorithm languages without such implementations. They were once called 'pseudocode'. (I don't know if that term is still used much.) Hence my oxymoronic definition, a decade ago, of Python as 'executable pseudocode'. Though, you do not need to understand the implementation to understand the language. Languages are typically defined before there is any implementation. They are implemented if they are understood as being worth the effort. I haven't thought it through completely, but now that Joe mentions it, it appears Python behaves the same as C++, Python and C/C++ have completely different object and data models. You and Joe are completely welcome to understand/model Python in terms of the C implementation, if you wish, but it not necessary and, I believe, a disservice to push such a model on beginners as *the* way to model Python. if variables can't be anything but pointers, parameters are all c-b-v, and you can't dereference the l-h-s of an assignment ( '*a= SomeClass()' ). I don't understand this. When you're explaining Python to a beginner, you have to introduce a new term either way. You'll either have to explain pointers, which Python has no concept of pointers. there are chapters and chapters on in introductory textbooks; or, you'll have to explain a new calling mechanism, and give it a name. I disagree. In everyday life, we have multiple names for objects and classes of objects. We nearly always define procedures in terms of generic object classes (common nouns) rather than particular objects. We apply procedures by binding generic names to particular objects, by associating them with objects, by filling in the named blanks. This is what Python does. Except for the particular formalized syntax, there is nothing new, not even the idea of a specialized procedure language. def make_cookies(flour, oil, sugar, egg, bowl, spoon, cookie_pan, oven): flour, oil, and sugar are containers with respectively at least 2 cups, 1 tablespoon, and 1/4 cup of the indicated material mix(bowl, spoon, measure(flour, '2 cups'), measure(sugar, '1/4 cup')) etc OK, there is one important difference. The concrete referents for the parameters are non-physical information objects rather than physical objects. I would say that an oject is passed, not a reference. I agree, and anything else would be overcomplicated. To me, 'pass' implies movement, but in Python, objects don't really have a position and hence cannot move. So I would say that an object is associated (with a parameter). 'Associating' is a primitive operation for Python interpreters. If and when all parameters get associated with something, the function code is activated. Then the return object gets associated with the call expression in the computation graph. Terry Jan Reedy -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
On Nov 6, 6:00 pm, Terry Reedy [EMAIL PROTECTED] wrote: Aaron Brady wrote: and you can't have languages without implementations. This is either a claim that languages are their own implementations, or an admission that human brains are the implementation of all languages thought of by human brains, coupled with a claim that there cannot be languages not thought of by humans, or just wrong in terms of the common meaning of algorithmic implementation of an interpreter. There are many algorithm languages without such implementations. They were once called 'pseudocode'. (I don't know if that term is still used much.) Hence my oxymoronic definition, a decade ago, of Python as 'executable pseudocode'. I was just saying that Joe has a good idea for one way to implement Python. Python and C/C++ have completely different object and data models. You and Joe are completely welcome to understand/model Python in terms of the C implementation, if you wish, but it not necessary and, I believe, a disservice to push such a model on beginners as *the* way to model Python. You're asking about people's thought processes when they write a program. In chess, I sometimes think, If I move here, he moves there, etc., but not always; sometimes I just visualize pieces in places. In Python, if I want a function that, say, duplicates the first and last elements of a sequence type, I visualize one parameter, and some code that operates on it. def duper( a ): a.insert( 0, a[ 0 ] ) a.append( a[ -1 ] ) Someone else with no experience, or certain incompatible experience, might visualize this: def duper( a ): a= a[ 0 ] + a + a[ -1 ] As you can see, they know a lot of Python already. What are they missing? if variables can't be anything but pointers, parameters are all c-b-v, and you can't dereference the l-h-s of an assignment ( '*a= SomeClass()' ). I don't understand this. If you restricted a C program as follows: - variables can only be pointers - no pointers to pointers - no dereferencing l-h-s of assignment statements It would look at the very least a lot like Python, or as Joe holds, exactly like Python. snip. I disagree. In everyday life, we have multiple names for objects and classes of objects. We nearly always define procedures in terms of generic object classes (common nouns) rather than particular objects. We apply procedures by binding generic names to particular objects, by associating them with objects, by filling in the named blanks. This is what Python does. Except for the particular formalized syntax, there is nothing new, not even the idea of a specialized procedure language. To examine the natural language (NL) equivalents of these issues a little. Here's a question I posed to Joe: a) 'Fido' is a reference to a dog b) Fido is a reference to a dog c) 'Fido' is the name of a dog d) Fido is the name of a dog e) 'Fido' is a dog f) Fido is a dog Which are true? I have no problems with (c) and (f), and many natural languages (possibly being strictly spoken) do not distinguish (c) from (d). Similarly, Old McDonald had a dog and Bingo was it's name. (*) Old McDonald had a dog and Bingo was it. (* marks non-standard) (*) Old McDonald had a dog and it was Bingo. I want to give a code name to Fido: Rex. What language do I use to inform my audience (spies), and what statements are subsequently true? Then, I want to write instructions to friends on how to walk dogs in my neighborhood, still in natural language. _How to walk a dog_ Take the dog out the door Turn right at the end of the drive etc. Nothing mysterious. Same thing with instructions for vaccinating them. However, if I want to model dogs, simulate them, etc., I'll keep some running state information about them: think its chart at the vet. Dog: Fido: Last walked: 10 a.m. Needs to be walked: False At 4 p.m., I'm going through the charts, and I notice Fido hasn't been walked, so I change the 'Needs to be walked' entry to true. Then some members of spies walks into the vet, and ask if Rex needs to be walked. What things in this story are names, variables, dogs, references, objects, pointers, types, classes, procedures, functions, arguments, parameters, formal parameters, by-value parameters, by-reference parameters, by-share parameters, etc.? How many names does Fido have, what are they, what is Fido, what is Rex, etc.? Keep in mind there are seldom quotes in spoken language; people have to make gestures or be explicit in such cases as they need to indicate their presence. Quote Fido quote is the name of a dog, but Fido is not. (Actual transcription.) Keep answers to less than 500 words. Also, reevaluate the uses of 'the' and 'a' in the multiple choice question: Is 'Fido' the name of a dog, a name of a dog, or a name of the dog? def make_cookies(flour, oil, sugar, egg, bowl, spoon, cookie_pan, oven): flour, oil, and sugar are containers with respectively at least 2
Re: Finding the instance reference of an object
On Thu, 06 Nov 2008 09:59:37 -0700, Joe Strout wrote: that's pretty much the whole point: that variables in Python don't contain objects, but merely contain references to objects that are actually stored somewhere else (i.e. on the heap). You're wrong, Python variables don't contain *anything*. Python variables are names in a namespace. But putting that aside, consider the Python code x = 1. Which statement would you agree with? (A) The value of x is 1. (B) The value of x is an implementation-specific thing which is determined at runtime. At the level of the Python virtual machine, the value of x is arbitrary and can't be determined. If you answer (A), then your claim that Python is call-by-value is false. If you answer (B), then your claim that Python is call-by-value is true but pointless, obtuse and obfuscatory. This is explicitly stated in the Python docs [1], yet many here seem to want to deny it. [1] http://www.python.org/doc/2.5.2/ext/refcounts.html You have a mysterious and strange meaning of the word explicitly. Would you care to quote what you imagine is this explicit claim? Looks to me that even if there were ten levels of indirection you would still insist that its a pass by value because in the end, its the actual memory address of the first pointer in the queue that is passed. No, it's entirely possible for an OOP language to have pass by reference, and, to put it your way, this adds one more level of indirection. Look at the C++ and RB/VB.NET examples at [2]. But Python and Java do not offer this option. Yes, you are right, Python does not offer pass by reference. The canonical test for call by reference behaviour is to write a function that does this: x = 1 y = 2 swap(x, y) assert x == 2 and y == 1 If you can write such a function, your language may be call-by-reference. If you can't, it definitely isn't c-b-r. You can't write such a function in standard Python, so Python isn't c-b-r. The canonical test for call by value semantics is if you can write a function like this: x = [1] # an object that supports mutation mutate(x) assert x == [1] If mutations to an argument in a function are *not* reflected in the caller's scope, then your language may be call-by-value. But if mutations are visible to the caller, then your language is definitely not c-b-v. Python is neither call-by-reference nor call-by-value. If that is what you mean, it is obviously trivially true - but then ALL calling can only be described as call by value - which makes nonsense of what the CS people have been doing all these years. That would indeed be nonsense. But it's also not what I'm saying. See [2] again for a detailed discussion and examples. Call-by-value and call-by-reference are quite distinct. And also a false dichotomy. Calling by value is not a useful definition of Pythons behaviour. It really is, though. You have to know how the formal parameter relates to the actual parameter. Is it a copy of it, or an alias of it? And by definition, call by value means that the parameter is a copy. So if you pass a ten megabyte data structure to a function using call-by- value semantics, the entire ten megabyte structure is copied. Since this does not happen in Python, Python is not a call-by-value language. End of story. Without knowing that, you don't know what assignments to the formal parameter will do, or even what sort of arguments are valid. Answer: it's a copy of it. Lies, all lies. Python doesn't copy variables unless you explicitly ask for a copy. That some implementations of Python choose to copy pointers rather than move around arbitrarily large blocks of memory instead is an implementation detail. It's an optimization and irrelevant to the semantics of argument passing in Python. Assignments don't affect the actual parameter at all. This is exactly what call by value means. Nonsense. I don't know where you get your definitions from, but it isn't a definition anyone coming from a background in C, Pascal or Fortran would agree with. -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
First, I want to thank everyone for your patience -- I think we're making progress towards a consensus. On Nov 6, 2008, at 8:48 PM, Steven D'Aprano wrote: that's pretty much the whole point: that variables in Python don't contain objects, but merely contain references to objects that are actually stored somewhere else (i.e. on the heap). You're wrong, Python variables don't contain *anything*. Python variables are names in a namespace. I think we're saying the same thing. What's a name? It's a string of characters used to refer to something. That which refers to something is a reference. The thing it refers to is a referent. I was trying to avoid saying the value of an object reference is a reference to an object since that seems tautological and you don't like my use of the word value, but I see you don't like contains either. Maybe we can try something even wordier: a variable in Python is, by some means we're not specifying, associated with an object. (This is what I mean when I say it refers to the object.) Can we agree that far? Now, when you pass a variable into a method, the formal parameter gets associated with same object the actual parameter was associated with. I like to say that the object reference gets copied into the formal parameter, since that's a nice, simple, clear, and standard way of describing it. I think you object to this way of saying it. But are we at least in agreement that this is what happens? But putting that aside, consider the Python code x = 1. Which statement would you agree with? (A) The value of x is 1. Only speaking loosely (which we can get away with because numbers are immutable types, as pointed out in the last section of [1]). (B) The value of x is an implementation-specific thing which is determined at runtime. At the level of the Python virtual machine, the value of x is arbitrary and can't be determined. Hmm, this might be true to somebody working at the implementation level, but I think we're all agreed that that's not the level of this discussion. What's relevant here is how the language actually behaves, as observable by tests written in that language. If you answer (A), then your claim that Python is call-by-value is false. Correct. If you answer (B), then your claim that Python is call-by-value is true but pointless, obtuse and obfuscatory. Correct again. My answer is: (C) The value of x is a reference to an immutable object with the value of 1. (That's too wordy for casual conversation so we might casually reduce this to (A), as long as we all understand that (A) is not actually true. It's a harmless fiction as long as the object is immutable; it becomes important when we're dealing with mutable objects.) This is explicitly stated in the Python docs [1], yet many here seem to want to deny it. [1] http://www.python.org/doc/2.5.2/ext/refcounts.html You have a mysterious and strange meaning of the word explicitly. Would you care to quote what you imagine is this explicit claim? A few samples: The chosen method is called reference counting. The principle is simple: every object contains a counter, which is incremented when a reference to the object is stored somewhere, and which is decremented when a reference to it is deleted. When the counter reaches zero, the last reference to the object has been deleted and the object is freed. ...Python uses the traditional reference counting implementation... This seems like a point we really shouldn't need to argue. Do you really want to defend the claim that Python does not use references? Yes, you are right, Python does not offer pass by reference. The canonical test for call by reference behaviour is to write a function that does this: x = 1 y = 2 swap(x, y) assert x == 2 and y == 1 If you can write such a function, your language may be call-by- reference. If you can't, it definitely isn't c-b-r. You can't write such a function in standard Python, so Python isn't c-b-r. Whew! That's a relief. A week ago (or more?), it certainly sounded like some here were claiming that Python is c-b-r (usually followed by some extended hemming and hawing and except-for-ing to explain why you couldn't do the above). The canonical test for call by value semantics is if you can write a function like this: x = [1] # an object that supports mutation mutate(x) assert x == [1] If mutations to an argument in a function are *not* reflected in the caller's scope, then your language may be call-by-value. But if mutations are visible to the caller, then your language is definitely not c-b-v. Aha. So, in your view, neither C, nor C++, nor Java, nor VB.NET are c- b-v, since all of those support passing an object reference into a function, and using that reference to mutate the object. Your view is at odds with the standard definition, though; in fact I'm pretty sure we could dig
Re: Finding the instance reference of an object [long and probably boring]
Joe Strout wrote: On Nov 6, 2008, at 12:44 PM, Arnaud Delobelle wrote: I know this thread has grown quite personal for some of its participants. I am posting in a spirit of peace and understanding :) Thanks, I'll do the same. That's good to hear. Your arguments are sometimes pretty good, and usually well made, but there's been far too much insistence on all sides about being right and not enough on reaching agreement about how Python's well-defined semantics for assignment and function calling should best be described. In other words, it's a classic communication problem. Um, no, I've admitted that it's a reference all along. Indeed, that's pretty much the whole point: that variables in Python don't contain objects, but merely contain references to objects that are actually stored somewhere else (i.e. on the heap). This is explicitly stated in the Python docs [1], yet many here seem to want to deny it. You refer to docs about the *implementation* of Python in C. This is irrelevant. It's supportive. I don't understand how/why anybody would deny that Python names are references -- it's all over the place, from any discussion of reference counting (necessary to understand the life cycle of Python object) to understanding the basics of what a = b does. It seems absurd to argue that Python does NOT use references. So the official documentation calmly discussing Python references, with no caveats about it being internal implementation detail, seemed relevant. I must say I find it strange when people try to contradict my assertion that Python names are references to objects, when the (no pun intended) reference implementation of the language uses reference counting to track how many assignments have been made. Also, you talk about variables 'containing' something. In Python, variables don't contain anything, they're simply names for objects. Though there is an equally vociferous faction who will happily jump up and down all day shouting objects don't have names, a tendency I have myself been known to indulge from time to time (but usually only when some novitiate asks how they can find out what the name of an object is). Being of the old school, I do tend to think of Python names as being reference variables in the sense of Algol 68. Thus they are fixed-size and frequently of limited lifetime. Since assignment (whether by name binding or to a container element) copies the reference, and since strong references keep objects alive, this is one way to explain why Python doesn't suffer from C++'s dangling pointer issue. You say names for, I say references to. We're saying the same thing (though I'm saying it with terminology that is more standard, at least in the wider OOP world). Naughty, naughty, there's that little I'm right, you're wrong thing sneaking in again. I don't want to have to get the clue stick out here ... 'Pass by value' is not relevant to Python as variables do not contain anything. 'Pass by reference' is not relevant to Python as the language doesn't have the concept of object reference (in the sense of e.g. C++ reference). Variables do not contain anything seems to be a little extreme here. They must store information of some sort, or no Python program could ever produce a useful output. And while the concept of object reference may not exist in the language, it is definitely valid for implementers. Interestingly, while variable isn't an indexed term in the (2.6) documentation, reference count appears in the glossary and the Language Reference Manual (again, no pun intended) explicitly states in its discussion of Python's data model (vis a vis the exact meaning of immutability) that container objects contain references to other objects. It shortly thereafter mentions the reference-counting technique of the CPython implementation, but does not claim it as part of the language. The same section also mentions reference to 'external' resources such as files or windows ... and references to other objects. Interestingly it is also made explicit that for immutable types, operations that compute new values may return a reference to any existing object with the same type and value, while for mutable objects this is not allowed (and if any reader disagrees that the reasons for this are obvious their part in this thread was long since over). There's even a built-in type called a weak reference. So any argument that the language doesn't have the concept of object reference (in the sense of e.g. C++ reference) is simply stating the obvious: that Python has no way to declare reference variables. I would argue myself that it has no need of such a mechanism precisely because names are object references, and I'd like to hear counter-arguments. Consider my memory short -- I have a large dose of crotchety to go with that it you'd like. Both are relevant to answering simple questions, like what happens to x in this case: def foo(spam):
Re: Finding the instance reference of an object
Aaron Brady wrote: On Nov 6, 6:00 pm, Terry Reedy [EMAIL PROTECTED] wrote: 'Associating' is a primitive operation for Python interpreters. Interesting. If I may be so bold as to ask, is it for C code, C compilers, and/or C programs? Sorry, I should have specified for the abstract definition of a Python interpreter, and perhaps for people. Computer programs need an implementation in terms of computer memory, etc. -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
Steven D'Aprano wrote: On Thu, 06 Nov 2008 09:59:37 -0700, Joe Strout wrote: [...] And by definition, call by value means that the parameter is a copy. So if you pass a ten megabyte data structure to a function using call-by- value semantics, the entire ten megabyte structure is copied. Since this does not happen in Python, Python is not a call-by-value language. End of story. Without knowing that, you don't know what assignments to the formal parameter will do, or even what sort of arguments are valid. Answer: it's a copy of it. Lies, all lies. Python doesn't copy variables unless you explicitly ask for a copy. That some implementations of Python choose to copy pointers rather than move around arbitrarily large blocks of memory instead is an implementation detail. It's an optimization and irrelevant to the semantics of argument passing in Python. [...] Are you sure you meant to write this? regards Steve -- Steve Holden+1 571 484 6266 +1 800 494 3119 Holden Web LLC http://www.holdenweb.com/ -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
Joe Strout wrote: First, I want to thank everyone for your patience -- I think we're making progress towards a consensus. Phew. But putting that aside, consider the Python code x = 1. Which statement would you agree with? (A) The value of x is 1. Only speaking loosely (which we can get away with because numbers are immutable types, as pointed out in the last section of [1]). I'd agree this is a valid way to describe the post-condition of the assignment. (B) The value of x is an implementation-specific thing which is determined at runtime. At the level of the Python virtual machine, the value of x is arbitrary and can't be determined. Hmm, this might be true to somebody working at the implementation level, but I think we're all agreed that that's not the level of this discussion. What's relevant here is how the language actually behaves, as observable by tests written in that language. I'd actually say x contains a reference to 1, claim that was equivalent to (A) above and cite Humpty Dumpty as my justification [1]. If you answer (A), then your claim that Python is call-by-value is false. Correct. If you answer (B), then your claim that Python is call-by-value is true but pointless, obtuse and obfuscatory. Correct again. My answer is: (C) The value of x is a reference to an immutable object with the value of 1. (That's too wordy for casual conversation so we might casually reduce this to (A), as long as we all understand that (A) is not actually true. It's a harmless fiction as long as the object is immutable; it becomes important when we're dealing with mutable objects.) I am unsure here as to why you find it necessary to refer to 1's immutability. How does this alter the essence of the situation? [...] Not that I'm trying to argue from authority; I'm trying to argue from logic. I suspect, though, that your last comment gets to the crux of the matter, and reinforces my guess above: you don't think c-b-v means what most people think it means. Indeed, you don't think any of the languages shown at [1] are, in fact, c-b-v languages. If so, then we should focus on that and see if we can find a definitive answer. You're right. Observable progress, I think. regards Steve [1] http://www.sundials.org/about/humpty.htm -- Steve Holden+1 571 484 6266 +1 800 494 3119 Holden Web LLC http://www.holdenweb.com/ -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object [long and probably boring]
Steve Holden [EMAIL PROTECTED] writes: One of the reasons for Python's continue march towards world domination (allow me my fantasies) is its consistent simplicity. Those last two words would be my candidate for the definition of Pythonicity. +1 QOTW -- \ Eccles: “I'll get [the job] too, you'll see. I'm wearing a | `\Cambridge tie.” Greenslade: “What were you doing there?” | _o__) Eccles: “Buying a tie.” —The Goon Show, _The Greenslade Story_ | Ben Finney -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
Joe Strout [EMAIL PROTECTED] wrote: 4. You now see how a mutating an object within a function tells you NOTHING about how the reference to that object was passed. 5. You see that the first three languages above are passing a reference by value and using that to mutate and object, yet for reasons still mysterious, the Python example (which has exactly the same behavior) must be doing something different. This is dialectic nit picking - WTF makes passing a reference by value different from passing a reference - the salient point is that its a reference that is passed - would you expect another level of indirection - a reference to the reference, or what, before you admit that the thing that is passed is a reference and not a copied value of the OBJECT that is of interest. Looks to me that even if there were ten levels of indirection you would still insist that its a pass by value because in the end, its the actual memory address of the first pointer in the queue that is passed. If that is what you mean, it is obviously trivially true - but then ALL calling can only be described as call by value - which makes nonsense of what the CS people have been doing all these years. Calling by value is not a useful definition of Pythons behaviour. - Hendrik -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
Dennis Lee Bieber wrote: I'm sure all the programmers using FORTRAN for the last 50 years will be very surprised to hear that it uses call-by-value! That should be 'last 31 years'. Fortran IV *was* call-by-value, as least for scalars. I remember spending a couple of hours tracking down an obscure 'bug' in a once-working program when I ran it with F77. (I had not noticed the call-by-reference switch.) The reason was, as I remember, 'x = -x' in a function. I never forgot the difference. I've used it for 30 years Then you apparently missed the switch ;-). tjr -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
On Nov 4, 9:33 am, Joe Strout [EMAIL PROTECTED] wrote: On Nov 3, 2008, at 5:27 PM, Marc 'BlackJack' Rintsch wrote: Maybe this is a surprise for you, because we haven't discussed this in much detail in this group lately, but it applies to Python which does call-by-object or call-by-sharing. ;-) There's no such thing. Those are just terms made up by the Python community to in place of the more standard call-by-value terminology to make Python seem more mysterious than it really is. I guess you can call it purple bananas if you want, but the behavior is exactly the same as what every other language calls call-by-value. But I really am trying not to continue this debate. So that's my last reply about it for tonight, I promise. :) Cheers, - Joe http://www.strout.net/info/coding/valref/ I'm fed up with you. In Von Neumann Architecture computers, only pass-by-value is natively supported. Other idioms are made on top of pass-by-value. That's why exclusively pass-by-value languages like C is most flexible than other exclusively pass-by-insertanythinghere. BUT the difference is clear, if you want to do pass-by-reference in C (I prefer to call it faux pass-by-reference), you'd have to manually find a variable's address, pass it by-value, then dereference the address. Compare with VB's ByRef or C++'s , which does all that _automatically_ for you behind the scene. Another example: pass-by-object. I disagree with the term pass-by- object-reference, since the notion of object reference is unnecessary in a true pass-by-object mechanism (i.e. we should travel outside VNA realm for a true pass-by-object mechanism). Problem is: I'm not aware of any computer architecture that can accommodate pass-by-object natively or whether such architecture is feasible to be made. Solution: Emulate such architecture on a VNA computer. Limitations: pass-by-object implementation on a VNA computer requires the notion of object reference/pointer because VNA computers cannot pass object, it can only pass numbers. In pass-by-object, the whole object is passed around, not a copy of the object like in pass-by-value or a copy of the pointer to the object like in faux pass-by-reference. This makes pass-by-object actually closer to pass-by-reference than to pass-by-value, since the notion of VNA's requirement for Object Reference means passing pointers around. But don't let it confuse you, the pass-by-object mechanism itself does not recognize Object Reference, unlike pass-by- reference recognition of reference/pointer. Now that I have clearly defined the line between pass-by-object and pass-by-value, I'm left with you thinking what's the difference between pass-by-object and pass-by-reference. In pass-by-reference, names are _mnemonic to location in memory_. In pass-by-object, names are _mnemonic to objects_. In pass-by-reference, when we assign a value to the name, we'd assign a value _to the location in memory_. In pass-by-object, when we assign a value to the name, we assign an object _to the name_. When passing parameters, pass-by-reference systems passed the memory address and alias that memory address to a local name. In pass-by-object system, since the object itself has no idea of its own name, so it is rebound to a local name. You can say that pass-by-reference system is memory-location-centered, while pass- by-object system is name-centered. To summarize, the key bit you're missing is built-in _automatic_ abstraction from pass-by-value. All pass-by-insertanything except pass-by-value is an emulation over an architecture that can only natively pass-by-value. pass-by-reference is emulated in C, C++, and VB by passing memory address/pointer but C isn't a by-ref system because C doesn't provide the automatization. What makes python's parameter passing called as pass-by-object is because python provides the automatization to make it seems that you can do true pass-by- object. -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
If the assert statement fails (and it does), then no copy was made and Python is not call-by-value. So Python is not call-by-value, and it's not call-by-reference, so ... either Python doesn't exist, or it uses a different calling convention. coming from C/C++ Python seemed to me call by reference, for the pragmatic reason you said, modificaitons to function arguments do affect the variable in the caller. The confusing part of this then comes when immutable objects are passed in. You still get a reference, but rather than complaining if you change the value of that parameter at might happen if immutible was const and the code was const- correct. Honestly I understand how this can change the callBy paradigm I don't see it that way (though I've duly remembers call-by-sharing and call-by-object) for communication purposes). I see it as a factor of the way variable names are rebound, that is, the quirk I remember is not about how entities are passed to functions, but the quirk of how python deals with modifications to immutibles. That is, python lets you change object references pointing to immutibles, which looks like changing the value referenced, by rebinding. So is that objectionable? -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
Craig Allen wrote: That is, python lets you change object references pointing to immutibles, which looks like changing the value referenced, by rebinding. So is that objectionable? OK once in a while, but it wouldn't do for everyday. Python 2.5.2 (r252:60911, Jul 31 2008, 17:28:52) [GCC 4.2.3 (Ubuntu 4.2.3-2ubuntu7)] on linux2 Type help, copyright, credits or license for more information. # Case A: a=2 b=3 a+b 5 # Case B: id(a) 135720748 id(b) 135720736 id(a+b) 135720712 id(a)+id(b) 271441484 In talking about Python programs, we'd really like to talk like case A. Meaningful values are tagged with names, passed around, operated on. We get our result and leave. Case B adds a level of indirection that, if we mention it, just obscures our actual task of summing two numbers. Consider the fragment def f (x, y): return x+y a=2 b=3 c = f(a, b) We can imagine a cross-namespace assignment operator (which we could write =\= if we needed more weird glyphs.) It works exactly like ordinary assignment except that the LHS is evaluated in a different namespace from the RHS. We could use our new operator to trace the execution of this code fragment. The core of it would be x =\= a # outer to inner assignment y =\= b c =/= x+y # inner to outer assignment It's ordinary assignment all the way, except for being from an outer to an inner, or from an inner to an outer namespace. Note how changing to mutable arguments makes no difference (literal arguments this time): c = f ([2], [3]) x =\= [2] y =\= [3] c =/= x+y Replacing =\= and =/= with = loses us our cross-namespace conceit, but the code still runs and does what Python code does. So why import the wrong terminology from some other field, then try to save it by mangling the definition of 'value' so that it's no use in discussing what a program is supposed to do? ob: Python, I refer you to the _Beyond the Fringe_ sketch Portrait from Memory, a reminiscence by a pseudo Bertrand Russell (Moore, have you some apples in that basket?.) You want to have to talk like this all the time? See what I mean? -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
On Nov 4, 2008, at 7:42 AM, Craig Allen wrote: coming from C/C++ Python seemed to me call by reference, for the pragmatic reason you said, modificaitons to function arguments do affect the variable in the caller. The confusing part of this then comes when immutable objects are passed in. Yes, you stepped in the wrong direction right away and led yourself into a morass of contradictions. The correct way to look at it is that a Python reference is like a C++ pointer. C++ pointers are passed by value (unless you add to explicitly make a parameter by-reference), yet you can still use them to mutate the objects they point to, right? Same thing in Python. Nothing at all mysterious going on here. Compare this: typedef Spam* SpamPtr; // (where Spam is some class) // ... void foo(SpamPtr spam) { spam-count = 4; } When you call foo, it modifies the spam object passed in, even though the parameter is by-value. How? Because (looking more carefully), you didn't actually pass in a Spam object; you passed in a POINTER TO a Spam object. That pointer remained unchanged. You just used the pointer to change some other data living on the heap. This is the case exactly equivalent to Python: def foo(spam): spam.count = 4; Same thing here; the variable you pass in is a reference to a Spam object, and while that reference remains unchanged by the call, it is used to change some other data that lives on the heap. Here's a C++ example that has no analog in Python, because it uses call-by-reference: void throwOut(SpamPtr spam) { printf(throwing out %s\n, spam-brand); delete spam; spam = nil; } Now here, when you invoke throwOut on a SpamPtr, your own SpamPtr variable (the one that you pass in) actually gets set to nil. That's because the formal parameter here is just an alias of the actual parameter. You can't do that in Python; this attempt: def throwOut(spam): print throwing out %s\n, spam.brand spam = nil would entirely fail to have any effect whatsoever on the Spam reference you pass in. spam here is just a local variable within the throwOut function, which has no connection to the variable passed in other than it gets a copy of its value (i.e., it initially refers to the same object as the actual parameter). This doesn't work, and the C++ throwOut function has no analog in Python, because Python has no call-by-reference. Here's another C++ example that has no analog in Python, because it passes an object directly on the stack rather than a reference to it: void bar(Spam spam) { spam.count = 5; } This is the one that I know particularly confuses some users, because it LOOKS like what you could do in Python, and has the same behavior on the surface. But it's not analogous at all, because the spam local variable here (and presumably the one in the calling context) is an object stored directly on the stack, rather than a reference to an object on the heap. Python can't do that (nor can Java, nor REALbasic, etc.). This example is also call-by-value, but the value in this case is a type that has no analog in Python. Python object variables are references to objects on the heap, just like pointers in C++ to objects created with new. So this example is a red herring. I'd be very interested in hearing whether, as a C/C++ user, the above explanation is clear and makes sense to you. Thanks, - Joe -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
Joe Strout a écrit : On Nov 3, 2008, at 5:27 PM, Marc 'BlackJack' Rintsch wrote: Maybe this is a surprise for you, because we haven't discussed this in much detail in this group lately, but it applies to Python which does call-by-object or call-by-sharing. ;-) There's no such thing. Those are just terms made up by the Python community Did you read *any* of the many answers in this thread ? This term comes from lisp, and existed years before Python. to in place of the more standard call-by-value terminology to make Python seem more mysterious than it really is. Looks a bit paranoid to me. -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
On Nov 4, 11:06 am, Joe Strout [EMAIL PROTECTED] wrote: On Nov 4, 2008, at 7:42 AM, Craig Allen wrote: coming from C/C++ Python seemed to me call by reference, for the pragmatic reason you said, modificaitons to function arguments do affect the variable in the caller. The confusing part of this then comes when immutable objects are passed in. Yes, you stepped in the wrong direction right away and led yourself into a morass of contradictions. The correct way to look at it is that a Python reference is like a C++ pointer. C++ pointers are passed by value (unless you add to ... I'd be very interested in hearing whether, as a C/C++ user, the above explanation is clear and makes sense to you. joe, yes, it makes perfect sense. In my defense my priority was figuring out what was going on in terms of what happens passing in various types of arguments, rather than what things are called. Also, as a C/C++ programmer my perspective is that the program is the interpreter, and so I try to think what the interpreter is doing. This is ke because after 15 years of statically linked languages (no one calls them this any more due to dynamically linked libraries) you get used to things evaporating at compile time, the name x for a variable has no status as a real entity at run time. It is a name through which you communicate with the compiler only, the compiler has no need to represent it in the runtime program. I think a lot of this language history is based on terminology that does not have to consider this name as a real entity at runtime. When you consider the status of the entity x in x=1 in python, it is a pointer, and python looks like pass by value. The need for a different name comes from the fact that using pointers ubiquitously like this leads to behavior much more like pass by reference. I'm open to pass-by-sharing, or pass-by-object, but neither is perticularly intuitive, not as obvious in meaning as pass-by-val or pass-by-reference (or call-by-xxx). I suppose I'd like pass-by-name as more a description, as name to me has a similar sense to pointer, at least in a language that preserves the name as a runtime entitity (making C/C++ languages which compile away names). What happens in python is clear to me, I think I understand what the program, CPython is doing... the language still needs to settle. Thanks for the reply, it does help me find a better way to discuss what I understand about python and calling mechanics in general. cheers, craig -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
On Tue, 04 Nov 2008 09:16:05 -0800, Craig Allen wrote: I'm open to pass-by-sharing, or pass-by-object, but neither is perticularly intuitive, not as obvious in meaning as pass-by-val or pass-by-reference (or call-by-xxx). I suppose I'd like pass-by-name as more a description, as name to me has a similar sense to pointer, at least in a language that preserves the name as a runtime entitity (making C/C++ languages which compile away names). But call-by-name has a very different meaning from call-by-value, call-by- reference, or call-by-object or call-by-sharing. Call-by-name injects the expression used to call into the called function and evaluates it every time the argument is accessed within the function. Ciao, Marc 'BlackJack' Rintsch -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
Aaron Brady [EMAIL PROTECTED] wrote: I think we can conclude that Python passes by reference, since a function can modify objects that were passed in to it. Sort of - if the modification is by side effect - so you can append to a list, for instance. However, if you use the passed param name on the left of an assignment statement, you get a new local object. I think it is this that lies at the root of the confusion. - Hendrik -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
On Mon, 03 Nov 2008 19:33:52 -0700, Joe Strout wrote: On Nov 3, 2008, at 5:27 PM, Marc 'BlackJack' Rintsch wrote: Maybe this is a surprise for you, because we haven't discussed this in much detail in this group lately, but it applies to Python which does call-by-object or call-by-sharing. ;-) There's no such thing. Those are just terms made up by the Python community to in place of the more standard call-by-value terminology to make Python seem more mysterious than it really is. I call bullshit on you. We've already shown you that the term call-by- sharing (a.k.a. call-by-object or call-by-object-sharing) goes back to the 1970s and such computer scientists as Barbara Liskov. The language CLU used the term back in 1974, and it is possible that CLU wasn't the first language to use it. That's over fifteen years before the first release of Python. This is not the first time it's been pointed out to you. And it won't be the last. And I predict that it will make no difference to you at all: you will still continue to pretend that Liskov et al aren't even worth acknowledging, and you will continue to make the asinine definition that the value of x following x = 1 is 0x97b3250 rather than 1. I guess you can call it purple bananas if you want, but the behavior is exactly the same as what every other language calls call-by-value. Again, I call bullshit. Python's behaviour is not the same as what Pascal, or C, calls call-by-value. It is what many Java people call call- by-value, because they make the same idiotic definition that the value of a variable is some arbitrary and hidden reference to the thing of interest: Java is call-by-value, where value means a reference to the actual value, except for primitives, where the value is the actual value. It is an idiotic definition, the sort of thing that only a very smart person can make, twisting the plain and intuitive meaning of value (what is denoted by a symbol) just to avoid having to accept that there are more things in reality than their pet theory includes. It's not we Python folk who are guilty of misusing terminology, it is you and your fellow VB and Java folk who are misusing the term call-by-value to describe something which is nothing like call-by-value in Pascal and C. There is a simple test you can do: pass a value to a function, and have the function mutate that value. If the mutation appears in the caller's environment, then the value wasn't copied and it is not call-by- value. In Python: def mutate(alist): alist.append(1) L = [1, 2] mutate(L) # supposedly call by value assert L == [1, 2] If the assert statement fails (and it does), then no copy was made and Python is not call-by-value. So Python is not call-by-value, and it's not call-by-reference, so ... either Python doesn't exist, or it uses a different calling convention. -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
On Tue, 04 Nov 2008 09:06:45 -0700, Joe Strout wrote: This example is also call-by-value, but the value in this case is a type that has no analog in Python. I'm disappointed to see that my prediction that Joe would, yet again, utterly ignore all the arguments against his pet theory was correct. It's gratifying to be proven right, of course, but I'd prefer to be wrong and reduce the amount of confusion and obfuscation that Joe is causing. Over the years, I've had the misfortune to deal with many people like Joe. They get a fixed idea in their head, and regardless of the facts they will stick to it, no matter what: when the facts disprove your pet theory, ignore the facts. When we're talking about the value of a variable in Python, why on earth would you drag entities that do not exist in Python into the discussion? That is too low a level. It's analogous to my earlier tongue-in-cheek suggestion that all languages are in fact call-by-bit-flipping: technically true at some level of explanation, but not at the level of the Python virtual machine. -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: Finding the instance reference of an object
On Tue, 04 Nov 2008 09:16:05 -0800, Craig Allen wrote: When you consider the status of the entity x in x=1 in python, it is a pointer, and python looks like pass by value. Nonsense. Python doesn't have pointers. You're letting Joe confuse you. Python has objects: *everything* in Python is an object, and you have no access to pointers. Everything else is an implementation detail, and that is subject to change between implementations. The need for a different name comes from the fact that using pointers ubiquitously like this leads to behavior much more like pass by reference. And the confusion strikes again... you've just said that Python looks like pass by value, and now you say that Python's behaviour is much more like pass by reference. Can you not see that this is a contradiction? I'm open to pass-by-sharing, or pass-by-object, but neither is perticularly intuitive, not as obvious in meaning as pass-by-val or pass-by-reference (or call-by-xxx). There's nothing intuitive about call-by-reference or call-by-value either, they are modes of behaviour that need to be learned. And even if we accept that somehow people are born with in inherent knowledge of how C++ passes function parameters, that certainly doesn't apply to what Joe is peddling: that the value of a variable is an arbitrary and hidden reference to the actual value you want. I suppose I'd like pass-by-name as more a description, as name to me has a similar sense to pointer, at least in a language that preserves the name as a runtime entitity (making C/C++ languages which compile away names). Pass-by-name already has a meaning, and it isn't what Python does. Craig, please ignore all the implementation-specific details of how the C- implementation of Python works. That's not Python-the-language. IronPython works differently, so does Jython, so does PyPy. In fact, IronPython exposes to the Python programmer .Net objects where call-by- reference is actually correct (or so I'm told). At the level of Python code, Python operates on *objects*. When you call a function with an argument, the argument (an object) is NOT copied, it is passed to the function. If you mutate the argument inside the function, you are changing the object and the caller will see the mutation: this is just like call-by-reference, and unlike call-by-value. But if you assign a different object to the argument name, the caller does NOT see the change, which is just like call-by-value. So depending on what type of object the argument is, and depending on what you do inside the function, you get something that looks rather like call-by- value or call-by-reference semantics. But what the Python VM does is the same no matter what you do: Python's calling model is different from either byval or byref. The accepted name for that calling model is call- by-sharing, or sometimes call-by-object or even call-by-object- sharing, and it goes back at least to 1974 and the CLU language, and arguably even older than that to Lisp. -- Steven -- http://mail.python.org/mailman/listinfo/python-list