From kirby.urner at gmail.com Fri May 2 22:42:00 2008 From: kirby.urner at gmail.com (kirby urner) Date: Fri, 2 May 2008 13:42:00 -0700 Subject: [Edu-sig] More code for VPython (beginner) Message-ID: Below (appended code) is the kind of thing I use to introduce VPython, some high school math hoped for, in that there's a little bit of trig, an allusion to complex numbers. The fun here is VPython lets us put colorful geometric objects on screen then change their position at runtime, so it's not like some ray tracing program. So you can have a ball traveling around in a ring, or clock hands and stuff, all without any overwhelming amount of code. Six working examples in under 200 lines, including blank ones, ain't bad. But then I don't try out all the objects. This is a genre nothing exhaustive -- one could imagine thousands of such examples in a database somewhere. Another example on YouTube: http://www.youtube.com/watch?v=QXCPDsBN2Kc (looks like an obelisk, thinking of the late Arthur C.C.). Dr. Sonnenfeld in New Mexico provides the source underneath but Youtube de-indents for us, so here it is again: from visual import * from random import randint thecolors = [color.green, color.red, color.orange, color.magenta] for i in range(10000): place = (randint(-100,100), randint(-100, 100), randint(-10,10)) rcolor = randint(0,3) ball = sphere(pos = place, radius=0.5, color = thecolors[rcolor]) You can just hit F5 in IDLE's text editor and it'll run. Likewise for the examples below, I have students go to the bottom and progressively uncomment each test, hit F5 to run, always in the same IDLE session (shell restarts by itself, upon close of VPython window, very smooth). Dunno who many of you are using VPython in classes. I've got a Windows lab going at the local university with Python 2.5, VPython, POV-Ray on every workstation. For those on this list for a long time: Arthur Siegel wrote the most ambitious projective geometry package in Python, starting from his own fascination with that subject (not programming per se, he came from financial circles), and we used to argue about whether VPython should just be a part of the standard library, given how powerful it is (we argued about a lot of things -- miss the guy, he died very suddenly, the website is here: http://pygeo.sourceforge.net/ ). I do find that easy access to an OpenGL type space does marvels for language appeal, and given I'm recruiting in the open market, I'm glad to have VPython in my toolkit, really helps make my Saturday Academy class a viable elective. All the buzz about Python in general also helps of course. Kirby 4D Portland, Oregon """ Stuff to do with VPython vpython.org by Kirby Urner 4D Solutions 4dsolutions.net May 2, 2008 If you're on the Internet, why not keep a link to the documentation handy in your browser. """ from visual import * # get a lot of stuff import math # definitely wanna have math in the picture def stage(): scene = display(title='VPython Window', width=600, height=600, center=(0,0,0), background=(0,1,1)) return scene def firsttry(): # no arguments here """ The cylinder Object """ s = stage() s.autoscale = 0 s.scale = (0.5, 0.5, 0.5) # we figure out a good view s.select() rod = cylinder(pos=(0,0,0), axis=(5,0,0), radius=0.1) rod.color = color.green # but let's make it go around in circles: for i in range(500): angle = math.radians(i) # increment in degrees rod.axis = (math.cos(angle), math.sin(angle), 0) rate(100) def clock(): # no arguments here """ two arrow objects, one going around more slowly, night happens note: there's also a way to do rotation in XY by multiplying complex numbers, thanks to various identities (see orbits.py) """ s = stage() s.autoscale = 0 s.scale = (0.3, 0.3, 0.3) rod1 = arrow(pos=(0,0,0), axis=(3,0,0), shaftwidth=0.1) rod2 = arrow(pos=(0,0,0), axis=(1,0,0), shaftwidth=0.1) rod1.color = color.green rod2.color = color.red # clockwise this time, shorter one at 1/10th speed: for i in range(360*4,-1,-1): # four circles of angle angle1 = math.radians(i) # decrement in degrees angle2 = angle1/10.0 if i == 360*2: # switch to night view half way s.background = color.black rod1.axis = (3 * math.cos(angle1), 3 * math.sin(angle1), 0) rod2.axis = (1 * math.cos(angle2), 1 * math.sin(angle2), 0) rate(100) def balls(): # no arguments here """ arrow object leaves trail of balls """ s = stage() s.autoscale = 0 s.scale = (0.3, 0.3, 0.3) s.select() rod1 = arrow(pos=(0,0,0), axis=(3,0,0), shaftwidth=0.1) rod1.color = color.green # clockwise again for i in range(360,-1,-1): # one circles of angle angle1 = math.radians(i) # increment in degrees position = (3 * math.cos(angle1), 3 * math.sin(angle1), 0) rod1.axis = position ball = sphere(pos=position, radius=0.2) rate(100) def spaceballs(): # no arguments here """ arrow object leaves trail of balls, spaced by 10 degrees """ s = stage() s.autoscale = 0 s.scale = (0.3, 0.3, 0.3) rod1 = arrow(pos=(0,0,0), axis=(3,0,0), shaftwidth=0.1) rod1.color = color.green # clockwise again for i in range(360,-1,-1): # one circles of angle angle1 = math.radians(i) # increment in degrees position = (3 * math.cos(angle1), 3 * math.sin(angle1), 0) rod1.axis = position if not (i % 10): ball = sphere(pos=position, radius=0.2, color = color.orange) rate(100) def rings(): """ Have a ball travel around on a ring """ s = stage() s.autoscale = 0 s.scale = (0.3, 0.3, 0.3) s.select() thering = ring(pos=(0,0,0), axis=(0,0,1), # OK to comment this way radius=2.5, thickness=0.1, color=color.green) theball = sphere(pos=(2.5,0,0), radius=0.2, color = color.orange) # clockwise again for i in range(360*5,-1,-1): # five circles of angle angle1 = math.radians(i) # increment in degrees position = (2.5 * math.cos(angle1), 2.5 * math.sin(angle1), 0) theball.pos = position rate(100) def pyramids(): """ Desert plane, some Egyptian pyramids """ s = stage() s.backcolor = color.blue # dark blue sky s.autoscale = 0 s.scale = (0.1, 0.1, 0.1) mybox = box(pos=(0,0,0), length=10, height=0.1, width=10, color = color.yellow) p1 = pyramid(pos=(0,0,0), axis = (0,1,0), size=(4,2,2), color = color.red) p2 = pyramid(pos=(-4,0,-3), axis = (0,1,0), size=(5,1,1), color = color.green) p3 = pyramid(pos=(2,0,4), axis = (0,1,0), size=(6,2,2), color = color.orange) if __name__ == '__main__': # firsttry() # clock() # balls() # spaceballs() # rings() pyramids() From kirby.urner at gmail.com Sun May 4 01:26:05 2008 From: kirby.urner at gmail.com (kirby urner) Date: Sat, 3 May 2008 16:26:05 -0700 Subject: [Edu-sig] more class notes... Message-ID: Another class write-up with a YouTube: http://controlroom.blogspot.com/2008/05/sa-classnotes-200853.html How we do it in Portland (smile). Kirby in Portland From macquigg at ece.arizona.edu Sun May 4 22:21:28 2008 From: macquigg at ece.arizona.edu (David MacQuigg) Date: Sun, 04 May 2008 13:21:28 -0700 Subject: [Edu-sig] How does Python do Pointers? Message-ID: <5.2.1.1.0.20080504113849.016b0708@plus.pop.mail.yahoo.com> This was the question from a student at my recent lecture to a class of engineering students studying C. My answer was brief: It doesn't - arguments are passed by value. Then I thought, this is really misleading for students of C, where pass-by-value means making a copy of the passed object. So I'm looking for a simple answer that is complete, but doesn't baffle freshmen whose only experience so far is an introductory course in C. How about this: ''' Python doesn't use pointers, but they really aren't needed in Python, because the way objects in memory are accessed is fundamentally different than C. Objects in Python are "bound" to variable names. These names are associated with pointers, but that is at a lower level not seen by the Python programmer. If you need to get down to that level, you should be using C, not Python. ~ ''' That's a little better than my first answer, but I could elaborate with further discussion about argument passing. ''' You know that in C there are two ways to pass a value to a function: call-by-value and call-by-reference. Call-by-value puts a copy of the value in the function's memory area. Call-by-reference passes to the function a pointer to the original value in the caller's memory. In Python, passing a value to a function is done by "binding" the name of the parameter in the function to the value in the caller's memory. This is like call-by-reference in C, but the Python programmer never sees the pointer. ~ ''' Note that Martelli says "all argument passing in Python is by value" (Python in a Nutshell, p.74), but I think this may be an error. I would be interested in seeing how others would handle this question. -- Dave P.S. The lecture went very well. The students were enthusiastic, and the Mandelbrot images were stunning! http://ece.arizona.edu/~edatools/ece175/Lecture The purpose of the lecture was to introduce students to higher-level programming, and show how C can still play a role when performance is critical. I'm hoping to expand this to a 3-week sequence of lectures. From goldwamh at slu.edu Sun May 4 22:57:46 2008 From: goldwamh at slu.edu (Michael H. Goldwasser) Date: Sun, 4 May 2008 15:57:46 -0500 Subject: [Edu-sig] How does Python do Pointers? In-Reply-To: <5.2.1.1.0.20080504113849.016b0708@plus.pop.mail.yahoo.com> References: <5.2.1.1.0.20080504113849.016b0708@plus.pop.mail.yahoo.com> Message-ID: <18462.9034.542617.603108@Michael-Goldwassers-Computer.local> Hi Dave, For students familiar with C, the most straightforward analogy is that ALL of Python's names are akin to C's pointers. This is certainly the closest match of the three C/C++ models (value, pointer, reference). Even for new programmers with no previous knowledge, we make sure to portray names distinctly as pointers to the underlying object in memory, rather than to cloud the role of the name versus the value. Advantages of this analogy are the consistency of the following semantics: * Assignment "a = b" creates an alias, whereby a and b both reference the same underlying object. * Parameter passing is equivalent to passing a pointer in C. With a signature, def foo(bar):, the calling syntax foo(myList) simply assigns the formal parameter bar to point to the same underlying object as the actual parameter myList. In fact, it is exactly the semantics of the standard assignment "bar = myList" other than the distinction in scope between the local variable and the caller's. * None in Python is analogous to NULL in C. As an aside, this is why I prefer to compare Python's model to pointers in C/C++ rather than to references. When passing a reference variable in C++, the formal parameter must be bound to an actual object (you cannot pass a null reference). Having used this analogy, there are a few things that should be explained to those used to C. * You cannot directly manipulate memory addresses in Python as you can in C. Internally, Python's interpretter maintains those memory address. In fact, the value of id(x) is typically the underlying memory address. But you cannot use that address to access anything, nor can you do pointer arithmetic as in C. * There is an independent issue in that Python's primitive types (int/str/tuple) are immutable. So when passing an integer as a parameter, the mechanism is still pass-by-reference however this does not give the callee any power to alter the original value. I think this is why there are some who errantly characterize Python as using pass-by-value . As a final aside, if student have any familiarity with Java, the Python model is quite simple to explain. It is precisely that which Java uses for all object types. With regard, Michael On Sunday May 4, 2008, David MacQuigg wrote: > This was the question from a student at my recent lecture to a class of engineering students studying C. My answer was brief: It doesn't - arguments are passed by value. Then I thought, this is really misleading for students of C, where pass-by-value means making a copy of the passed object. So I'm looking for a simple answer that is complete, but doesn't baffle freshmen whose only experience so far is an introductory course in C. > > How about this: > > ''' > Python doesn't use pointers, but they really aren't needed in Python, because the way objects in memory are accessed is fundamentally different than C. Objects in Python are "bound" to variable names. These names are associated with pointers, but that is at a lower level not seen by the Python programmer. If you need to get down to that level, you should be using C, not Python. > ~ ''' > > That's a little better than my first answer, but I could elaborate with further discussion about argument passing. > > ''' > You know that in C there are two ways to pass a value to a function: call-by-value and call-by-reference. Call-by-value puts a copy of the value in the function's memory area. Call-by-reference passes to the function a pointer to the original value in the caller's memory. In Python, passing a value to a function is done by "binding" the name of the parameter in the function to the value in the caller's memory. This is like call-by-reference in C, but the Python programmer never sees the pointer. > ~ ''' > > Note that Martelli says "all argument passing in Python is by value" (Python in a Nutshell, p.74), but I think this may be an error. > > I would be interested in seeing how others would handle this question. > > -- Dave > > P.S. The lecture went very well. The students were enthusiastic, and the Mandelbrot images were stunning! http://ece.arizona.edu/~edatools/ece175/Lecture The purpose of the lecture was to introduce students to higher-level programming, and show how C can still play a role when performance is critical. I'm hoping to expand this to a 3-week sequence of lectures. +----------------------------------------------- | Michael Goldwasser | Associate Professor | Dept. Mathematics and Computer Science | Saint Louis University | 220 North Grand Blvd. | St. Louis, MO 63103-2007 From annaraven at gmail.com Sun May 4 23:47:10 2008 From: annaraven at gmail.com (Anna Ravenscroft) Date: Sun, 4 May 2008 14:47:10 -0700 Subject: [Edu-sig] Fwd: How does Python do Pointers? In-Reply-To: References: <5.2.1.1.0.20080504113849.016b0708@plus.pop.mail.yahoo.com> Message-ID: Martelli's response. ;-) ---------- Forwarded message ---------- From: Alex Martelli Date: Sun, May 4, 2008 at 2:36 PM Subject: Re: [Edu-sig] How does Python do Pointers? To: Anna Ravenscroft Cc: edu-sig at python.org With thanks to Anna for forwarding this... > From: David MacQuigg ... > Note that Martelli says "all argument passing in Python is by value" > (Python in a Nutshell, p.74), but I think this may be an error. Taken completely out of context, it might well be, because of the connotations often carried by the "by value" tag; if you however read the whole paragraph (just six short lines) you'll also see "Python passes the object itself, not a copy" which should abundantly suffice to dispel the mistaken belief that "by value means a copy". Within six short lines, I can't cover all the permutations and nuances that might best teach this issue to students coming from many different languages. Somebody coming from Java (perhaps the most popular first-language these days) has the least need for clarification, as I might basically say "it's just like in Java" (perhaps adding "without the complications and exceptions whereby e.g. int values appear to be treated differently";-). See for example http://javadude.com/articles/passbyvalue.htm -- "Java is Pass-by-Value, Dammit!" by Scott Stanchfield -- I do agree with the "Dammit!" part at least;-). A similar position is expounded at http://www.javaranch.com/campfire/StoryPassBy.jsp . Somebody coming from Fortran or Basic (still surprisingly popular first-languages, even though dated) needs most hand-holding, because they're used to think in terms of "passing a variable" rather than "passing a value". C of course is thoroughly by-value BUT with the added twist of an implied copy at each argument-passing (or assignment -- identical semantics to argument passing of course). (Scott would disagree as he claims that by-value MEANS copy -- but he also says Java has pointers, "Dog d;" declares a POINTER to a Dog, etc...). To somebody knowing only C, I might explain that "everything in Python is a pointer" (on which you however cannot perform pointer-arithmetic), much like the above Java articles explain things (but without the need to mention 'int' as somehow distinguished); or I might say a bit more precisely that every NAME is a pointer, and also ITEMS in containers are pointers. So argument passing (and assignment) most definitely ARE by value -- but of course, value of the POINTERS (_those_ pointers get copied around -- but the copy of a pointer points to the same object as the original pointer!), because that's what names always are in Python. Alex -- cordially, Anna -- Walking through the water. Trying to get across. Just like everybody else. From john.zelle at wartburg.edu Mon May 5 03:43:18 2008 From: john.zelle at wartburg.edu (John Zelle) Date: Sun, 04 May 2008 20:43:18 -0500 Subject: [Edu-sig] How does Python do Pointers? In-Reply-To: <18462.9034.542617.603108@Michael-Goldwassers-Computer.local> References: <5.2.1.1.0.20080504113849.016b0708@plus.pop.mail.yahoo.com> <18462.9034.542617.603108@Michael-Goldwassers-Computer.local> Message-ID: <1209951798.6366.26.camel@zelle> Hello all, This is all good explanation, but could use a bit of tweaking. Where the pointer analogy with C breaks down is that C pointers require explicit dereferencing. In this regard, the Python model is actually closer to C ++ reference variables, which are automatically dereferenced. Of course it also differs from references in that in Python the referent for a variable can change (just reassign it). Still the intuition should be just about right for C++ programmers. I myself like to think of Python variables as "sticky notes" that are attached to values so we can look them up later. This thinking is a clean break from pointers or references. Variables are not locations to have values placed in them. They are names that can be attached to objects. The discussion of NULL below is not quite accurate. NULL is a value stored into a variable in C/C++, that is, it is a value to say the the pointer/reference does not point to anything. However, None in Python is actually just the name (i.e. a variable) denoting a particular object. When you assign None, you are just setting the variable to point to that object. In C++, if you created a None object, then you could certainly pass any variable containing None as the actual argument for a reference parameter. In the final analysis Martelli is absolutely right. All parameters are passed by _value_ in Python. It's just that all variables are references to objects, so that means when you get a copy of the variable that copy is just another reference to the same object (i.e. you get a copy of the reference). Again, for C programmers, it is similar to getting a copy of a pointer. What I particularly like from a teaching standpoint is that parameter passing in Python works exactly like assignment. Just think: "assign the actual parameters of the caller to the formal parameters in the callee and execute the function body." There's nothing else to it. --John On Sun, 2008-05-04 at 15:57 -0500, Michael H. Goldwasser wrote: > Hi Dave, > > For students familiar with C, the most straightforward analogy is > that ALL of Python's names are akin to C's pointers. This is > certainly the closest match of the three C/C++ models (value, > pointer, reference). > > Even for new programmers with no previous knowledge, we make sure to > portray names distinctly as pointers to the underlying object in > memory, rather than to cloud the role of the name versus the value. > > Advantages of this analogy are the consistency of the following > semantics: > > * Assignment "a = b" creates an alias, whereby a and b both > reference the same underlying object. > > * Parameter passing is equivalent to passing a pointer in C. > With a signature, def foo(bar):, the calling syntax > foo(myList) simply assigns the formal parameter bar to point to > the same underlying object as the actual parameter myList. In > fact, it is exactly the semantics of the standard assignment > "bar = myList" other than the distinction in scope between the > local variable and the caller's. > > * None in Python is analogous to NULL in C. > > As an aside, this is why I prefer to compare Python's model to > pointers in C/C++ rather than to references. When passing a > reference variable in C++, the formal parameter must be bound to > an actual object (you cannot pass a null reference). > > > Having used this analogy, there are a few things that should be > explained to those used to C. > > * You cannot directly manipulate memory addresses in Python as you > can in C. Internally, Python's interpretter maintains those > memory address. In fact, the value of id(x) is typically the > underlying memory address. But you cannot use that address to > access anything, nor can you do pointer arithmetic as in C. > > * There is an independent issue in that Python's primitive types > (int/str/tuple) are immutable. So when passing an integer as a > parameter, the mechanism is still pass-by-reference however this > does not give the callee any power to alter the original value. > I think this is why there are some who errantly characterize > Python as using pass-by-value . > > As a final aside, if student have any familiarity with Java, the > Python model is quite simple to explain. It is precisely that which > Java uses for all object types. > > With regard, > Michael > > > On Sunday May 4, 2008, David MacQuigg wrote: > > > This was the question from a student at my recent lecture to a class of engineering students studying C. My answer was brief: It doesn't - arguments are passed by value. Then I thought, this is really misleading for students of C, where pass-by-value means making a copy of the passed object. So I'm looking for a simple answer that is complete, but doesn't baffle freshmen whose only experience so far is an introductory course in C. > > > > How about this: > > > > ''' > > Python doesn't use pointers, but they really aren't needed in Python, because the way objects in memory are accessed is fundamentally different than C. Objects in Python are "bound" to variable names. These names are associated with pointers, but that is at a lower level not seen by the Python programmer. If you need to get down to that level, you should be using C, not Python. > > ~ ''' > > > > That's a little better than my first answer, but I could elaborate with further discussion about argument passing. > > > > ''' > > You know that in C there are two ways to pass a value to a function: call-by-value and call-by-reference. Call-by-value puts a copy of the value in the function's memory area. Call-by-reference passes to the function a pointer to the original value in the caller's memory. In Python, passing a value to a function is done by "binding" the name of the parameter in the function to the value in the caller's memory. This is like call-by-reference in C, but the Python programmer never sees the pointer. > > ~ ''' > > > > Note that Martelli says "all argument passing in Python is by value" (Python in a Nutshell, p.74), but I think this may be an error. > > > > I would be interested in seeing how others would handle this question. > > > > -- Dave > > > > P.S. The lecture went very well. The students were enthusiastic, and the Mandelbrot images were stunning! http://ece.arizona.edu/~edatools/ece175/Lecture The purpose of the lecture was to introduce students to higher-level programming, and show how C can still play a role when performance is critical. I'm hoping to expand this to a 3-week sequence of lectures. > > +----------------------------------------------- > | Michael Goldwasser > | Associate Professor > | Dept. Mathematics and Computer Science > | Saint Louis University > | 220 North Grand Blvd. > | St. Louis, MO 63103-2007 > > _______________________________________________ > Edu-sig mailing list > Edu-sig at python.org > http://mail.python.org/mailman/listinfo/edu-sig > -- John M. Zelle, Ph.D. Wartburg College Professor of Computer Science Waverly, IA john.zelle at wartburg.edu (319) 352-8360 From macquigg at ece.arizona.edu Tue May 6 00:06:13 2008 From: macquigg at ece.arizona.edu (David MacQuigg) Date: Mon, 05 May 2008 15:06:13 -0700 Subject: [Edu-sig] How does Python do Pointers? In-Reply-To: <5.2.1.1.0.20080504113849.016b0708@plus.pop.mail.yahoo.com> Message-ID: <5.2.1.1.0.20080505131126.03bc9fe8@mail.ece.arizona.edu> Many thanks to Michael, Anna and John for the very thorough answers to this question. I especially like John's sticky-note analogy. I have been using a similar analogy with "labels", but that gets confused with the other more common uses of the word "label". Sticky Note is unique and more memorable. I'm disturbed that there doesn't seem to be any agreement on simple definitions for "call by reference" and "call by value". A Google search for [python "call by value"] shows there is widespread confusion in the Python world. I'm not a computer scientist, but somewhere I did learn these concepts as being simply copying the value of a variable vs passing just a reference to the original. I see that my simple understanding agrees with Kernighan and Ritchie and with http://en.wikipedia.org/wiki/Call_by_value. (Note that "call-by-reference", as defined in this article, clearly includes Python's calling method.) Luckily, we can answer the question without wading into this swamp. Here is my latest revision: ''' Python doesn't need pointers because of the simple relationship between variables and the objects they refer to. A variable has a name and a pointer to an object. An object has a type, a value, and an address in memory. Unlike C, the type is with the object, not the variable. A variable is "bound" to an object much like a sticky note on a box. Notes can be moved from one box to another, and a box can have more than one note, or no notes at all. Python's pointers are "under the hood", not something the programmer sees or ever needs to worry about. This part of what makes Python a higher level language than C. You gain a lot in simplicity and readability, while losing the ability to work directly with memory addresses. You also lose a little memory, because objects are more complex than raw data values. The sticky-note analogy has a flaw. You can't stick one note on top of another. When you say x = y = z, all three variables now point to the object originally pointed to by z. Then when you say y = 8, y now points to an integer object 8, but x doesn't move with y. Python's "sticky notes" have a special glue that sticks only to an object, not to another variable. See http://effbot.org/zone/python-objects.htm for more on Python objects and variables. Note: You can get the address of an object x with the function id(x), but this is used only to provide a unique identity for the object, not to access it. If id(x) == id(y), you know that variables x and y both point to the same object. ''' -- Dave From kirby.urner at gmail.com Tue May 6 01:00:21 2008 From: kirby.urner at gmail.com (kirby urner) Date: Mon, 5 May 2008 16:00:21 -0700 Subject: [Edu-sig] How does Python do Pointers? In-Reply-To: <5.2.1.1.0.20080505131126.03bc9fe8@mail.ece.arizona.edu> References: <5.2.1.1.0.20080504113849.016b0708@plus.pop.mail.yahoo.com> <5.2.1.1.0.20080505131126.03bc9fe8@mail.ece.arizona.edu> Message-ID: Useful discussion for me too, although my teenager students usually aren't that familiar with C, so mapping that shoptalk to Python is less of the issue. On the other hand, understanding that the same objects might have many names remains critical, also the idea of immutability, with reference to strings, tuples and such (a good counter to having so many names, each potentially a source of changes, as the name also "anchors" the "api" to its object i.e. any name might change objects' values as seen by others, via the various syntax triggers such as dot notation). I like that we call them "names" in Python and not variables so much, per the cited http://effbot.org/zone/python-objects.htm People new to programming know about objects, and that objects have names (maybe multiple, aliases and such), whereas the term "variable" is maybe not so accessible, sounds more like old algebra, plus its not the names that vary, but what they stick to. To say "the identity of x has changed" is to undo the work we just did, to distinguish x-the-name from what it points to (its object, not its identity). We also like calling them names because its namespaces they live in (have currency and defined meaning within) -- which is why a given name might reference different objects because defined in different namespaces (still a possibility for name collisions if not careful with importing -- why from "module import * " is often not a good idea). A key verb: "to disambiguate" (a purpose of namespaces). And having no names at all, in the sense of no references, no sticky notes, pointers from anywhere: that's what makes an object a candidate for garbage collection (reference count zero **), something else C doesn't provide out of the box either (but then CPython is C after all, made to do trix, behave like a snake (very agile)). Kirby On Mon, May 5, 2008 at 3:06 PM, David MacQuigg wrote: > Many thanks to Michael, Anna and John for the very thorough answers to this question. I especially like John's sticky-note analogy. I have been using a similar analogy with "labels", but that gets confused with the other more common uses of the word "label". Sticky Note is unique and more memorable. > > I'm disturbed that there doesn't seem to be any agreement on simple definitions for "call by reference" and "call by value". A Google search for [python "call by value"] shows there is widespread confusion in the Python world. I'm not a computer scientist, but somewhere I did learn these concepts as being simply copying the value of a variable vs passing just a reference to the original. I see that my simple understanding agrees with Kernighan and Ritchie and with http://en.wikipedia.org/wiki/Call_by_value. (Note that "call-by-reference", as defined in this article, clearly includes Python's calling method.) > > Luckily, we can answer the question without wading into this swamp. Here is my latest revision: > > ''' > Python doesn't need pointers because of the simple relationship between variables and the objects they refer to. A variable has a name and a pointer to an object. An object has a type, a value, and an address in memory. Unlike C, the type is with the object, not the variable. A variable is "bound" to an object much like a sticky note on a box. Notes can be moved from one box to another, and a box can have more than one note, or no notes at all. > > Python's pointers are "under the hood", not something the programmer sees or ever needs to worry about. This part of what makes Python a higher level language than C. You gain a lot in simplicity and readability, while losing the ability to work directly with memory addresses. You also lose a little memory, because objects are more complex than raw data values. > > The sticky-note analogy has a flaw. You can't stick one note on top of another. When you say x = y = z, all three variables now point to the object originally pointed to by z. Then when you say y = 8, y now points to an integer object 8, but x doesn't move with y. Python's "sticky notes" have a special glue that sticks only to an object, not to another variable. > > See http://effbot.org/zone/python-objects.htm for more on Python objects and variables. > > Note: You can get the address of an object x with the function id(x), but this is used only to provide a unique identity for the object, not to access it. If id(x) == id(y), you know that variables x and y both point to the same object. > ''' > > -- Dave > > > > > _______________________________________________ > Edu-sig mailing list > Edu-sig at python.org > http://mail.python.org/mailman/listinfo/edu-sig > From macquigg at ece.arizona.edu Tue May 6 02:24:15 2008 From: macquigg at ece.arizona.edu (David MacQuigg) Date: Mon, 05 May 2008 17:24:15 -0700 Subject: [Edu-sig] Introducing Python at our community college Message-ID: <5.2.1.1.0.20080505163509.04776cd8@plus.pop.mail.yahoo.com> I talked with the CIS department chairman and one of the faculty about the possibility of teaching Python at our community college, and they weren't interested. (Oh No, not another language ... ) Also, the lack of declarations was a show-stopper. I encountered this same objection from one of the faculty at U of A, where I just gave a lecture. It doesn't seem to help when I say: In four years of using Python, I can remember only one time when I had a subtle error from mistyping a variable name that took an hour to track down. I'll gladly trade that hour for the dozens I've saved not having to read and write all these declarations. I've added this to my QnA page at http://ece.arizona.edu/~edatools/ece175/Lecture/QnA.txt ''' Q2: Without variables declarations, isn't there a problem with mistyped variable names leading to subtle errors? A2: It can happen, but the subtle errors are rather rare. Usually you will get an immediate and clear message like: Traceback (most recent call last): - - - NameError: name 'z' is not defined where 'z' is the name you intended to type. The subtle error can occur if z is already defined, and you intended to re-define it. If you worry about errors like this, you can scan your program with a utility like pychecker, and it will detect any variables that are defined but never used. ''' Still, I wonder if there isn't a better way to handle this objection to Python. I'm thinking of a configuration option in IDLE, something that will either: 1) Run a subset of pychecker tests every time you hit the Run button, or 2) Insist on declarations in a comment at the start of every function (just the names, not data types). Any name that isn't already declared gets immediately painted red. I would use #1 if it was no time penalty. #2 seems like "training wheels" to me, but I would expect some folks who are religious about declarations might at least find it re-assuring. -- Dave From kirby.urner at gmail.com Tue May 6 02:54:36 2008 From: kirby.urner at gmail.com (kirby urner) Date: Mon, 5 May 2008 17:54:36 -0700 Subject: [Edu-sig] a philosophical aside about names and objects Message-ID: In followup to recent threads... On a related topic, though somewhat tangentially, in a smattering of posts scattered across the Internet I'm on record arguing *against* what I call the "name -> object" paradigm (that's like an arrow in between them) whereas here I've just been thinking how easily Python helps us make sense of this dogma. In philosophy going back to St. Augustine at least, you've got this picture of nouns or names "pointing" (in some magical unspecified way) to cows in the field or whatever. According to this school of though, language itself is essentially just "(word, thing) pairs" and the "process of meaning" involves doubling and mapping to make "word pictures" fit facts or fancies. Wittgenstein's first philosophy was a careful encoding of this view, using the in-vogue pre-computer logical notations of his day. In this view, language is all about nouns and their many "relationships" -- prototypical of "attributes" in later OO, reflective of state. Anyway, thanks to Wittgenstein's second take on the matter (an overhaul or recasting), a school of us came away seeing the word "cow" more as a part of some vast api for controlling stuff at runtime, less as a pointer to anything. Words become tools in this alternative summary vision, operational bits. Screwdrivers needn't "point" to be useful, and the screws they turn aren't their "meanings". Likewise with "cow" (another tool). ** We inherit these controller functions through our culture, plus pass on some innovations. [ I'm not saying I'm always proud of a culture I inherit from, vis-a-vis its treatment of cows for example -- redesigning the api seems in order, might clear up some other design flaws in the process ] In Python, the magic of "pointing" relates to our native concept of *dictionary* as that which pairs names with objects. The fact that module.__dict__ and self.__dict__ have a somewhat parallel meaning in Python helps get across how modules are themselves somewhat like class definitions, in terms of providing namespaces. My understanding of Perl is this identification actually got made when it went OO -- am I right about that? Anyway, just wanted to archive something along these lines, given all my work deprecating the name -> object paradigm elsewhere. That's work I don't want to undo, even as I admire Python's logical design. Kirby Key referent: http://www.grunch.net/synergetics/mathphil.html ** -- often useful to say when pointing, as when trying to single out that one animal (a cow) from some others. From kirby.urner at gmail.com Tue May 6 03:19:02 2008 From: kirby.urner at gmail.com (kirby urner) Date: Mon, 5 May 2008 18:19:02 -0700 Subject: [Edu-sig] Introducing Python at our community college In-Reply-To: <5.2.1.1.0.20080505163509.04776cd8@plus.pop.mail.yahoo.com> References: <5.2.1.1.0.20080505163509.04776cd8@plus.pop.mail.yahoo.com> Message-ID: Thanks Dave -- A wonderful question that points to the great cultural divide between compile-time versus runtime error trappers. The compile timers flirt with the notion that somehow the compiling step might actually constitute a *mathematical proof* that the program is correct (if only the language were tightly specified enough, Haskell maybe?). The run-timers think that by unit testing at the atomic level, never letting errors pass silently etc.,, they can patch any few remaining bugs, plus the code itself is just eminently more readable... Bruce Eckel is one of your best and most eloquent writers on this topic, pointing out the superstitions around compiling, as if all kinds of subtle errors couldn't sneak through, including at the level of algorithm. But he's refreshingly non-dogmatic, because after all, our VHLLs (very high level languages) are implemented in these faster lower level ones. It's not either/or but different tools for different jobs. Sometimes the difference between 100x slower than C, and not getting it done at all (or in time) is worth the sacrifice. Speed is the real payoff for type declarations, not immunity from error, as it's really *a lot* easier to write buggy yet executable C than Python, given your average newbie. Anyway, I'd make the argument on economic grounds: Python has a good track record, bright future, and lots of would-be students are eager to learn it, and look to community colleges as logical doors upon which to knock. Taking a side in the compile-time versus run-time debate needn't be a a high priority on anyone's list as we already know: it takes both approaches. But then a lot of faculty are just threatened by another language they don't know, so turning this into some philosophical fist fight works as a delaying maneuver. You may just have to live with the fact that your particular school feels no real competition, whereas in other towns, it's easier to jump on the bandwagon and give students the option. Ruby too while we're at it? Kirby On Mon, May 5, 2008 at 5:24 PM, David MacQuigg wrote: << SNIP >> > Still, I wonder if there isn't a better way to handle this objection to Python. I'm thinking of a configuration option in IDLE, something that will either: > > 1) Run a subset of pychecker tests every time you hit the Run button, or > 2) Insist on declarations in a comment at the start of every function (just the names, not data types). Any name that isn't already declared gets immediately painted red. > > I would use #1 if it was no time penalty. #2 seems like "training wheels" to me, but I would expect some folks who are religious about declarations might at least find it re-assuring. > > -- Dave > > > _______________________________________________ > Edu-sig mailing list > Edu-sig at python.org > http://mail.python.org/mailman/listinfo/edu-sig > From mdipierro at cs.depaul.edu Tue May 6 03:24:46 2008 From: mdipierro at cs.depaul.edu (Massimo Di Pierro) Date: Mon, 5 May 2008 20:24:46 -0500 Subject: [Edu-sig] Introducing Python at our community college In-Reply-To: <5.2.1.1.0.20080505163509.04776cd8@plus.pop.mail.yahoo.com> References: <5.2.1.1.0.20080505163509.04776cd8@plus.pop.mail.yahoo.com> Message-ID: <2949D705-0A79-4E64-94EA-5531DAB278B5@cs.depaul.edu> Hi David, I teach at DePaul university where we now use Python in multiple classes. The way we got it in was not by proposing Python in substitution to Java or C++. I tried it and that failed for the same reasons you mention. I got it in by starting to use Python in algorithms classes instead of pseudo code (and I did not permission to do it). Python also works great in web development courses (we have a course on web frameworks and we use web2py) and networking courses. Personally I believe that typical intro programming courses are obsolete because the target population has changed. When our students come in, although they cannot program, they already understand the concept of network, data transfer, input/output, files. I think it is easier to teach programming by teaching how to manipulate these high level structures and then work your way down to loops and conditionals that to do it the opposite way, the way we used to do it. Massimo On May 5, 2008, at 7:24 PM, David MacQuigg wrote: > I talked with the CIS department chairman and one of the faculty > about the possibility of teaching Python at our community college, > and they weren't interested. (Oh No, not another language ... ) > Also, the lack of declarations was a show-stopper. > > I encountered this same objection from one of the faculty at U of > A, where I just gave a lecture. It doesn't seem to help when I > say: In four years of using Python, I can remember only one time > when I had a subtle error from mistyping a variable name that took > an hour to track down. I'll gladly trade that hour for the dozens > I've saved not having to read and write all these declarations. > > I've added this to my QnA page at http://ece.arizona.edu/~edatools/ > ece175/Lecture/QnA.txt > > ''' > Q2: Without variables declarations, isn't there a problem with > mistyped > variable names leading to subtle errors? > > A2: It can happen, but the subtle errors are rather rare. Usually > you will > get an immediate and clear message like: > > Traceback (most recent call last): > - - - > NameError: name 'z' is not defined > > where 'z' is the name you intended to type. The subtle error can > occur if z > is already defined, and you intended to re-define it. > > If you worry about errors like this, you can scan your program with a > utility like pychecker, and it will detect any variables that are > defined > but never used. > ''' > > Still, I wonder if there isn't a better way to handle this > objection to Python. I'm thinking of a configuration option in > IDLE, something that will either: > > 1) Run a subset of pychecker tests every time you hit the Run > button, or > 2) Insist on declarations in a comment at the start of every > function (just the names, not data types). Any name that isn't > already declared gets immediately painted red. > > I would use #1 if it was no time penalty. #2 seems like "training > wheels" to me, but I would expect some folks who are religious > about declarations might at least find it re-assuring. > > -- Dave > > > _______________________________________________ > Edu-sig mailing list > Edu-sig at python.org > http://mail.python.org/mailman/listinfo/edu-sig -------------- next part -------------- An HTML attachment was scrubbed... URL: From enbody at cse.msu.edu Tue May 6 03:51:21 2008 From: enbody at cse.msu.edu (Richard Enbody) Date: Mon, 05 May 2008 21:51:21 -0400 Subject: [Edu-sig] Introducing Python at our community college In-Reply-To: <2949D705-0A79-4E64-94EA-5531DAB278B5@cs.depaul.edu> References: <5.2.1.1.0.20080505163509.04776cd8@plus.pop.mail.yahoo.com> <2949D705-0A79-4E64-94EA-5531DAB278B5@cs.depaul.edu> Message-ID: <481FB999.9030509@cse.msu.edu> David & Massimo, Our local community college will begin offering Python courses this Fall. As is common with community colleges there is a lot of 'training' for particular tools and languages to meet immediate needs of local employers. As a representative of the big, research university in town on the community college's advisory board I was pleased to see interest both at the college and with employers. I can put you in contact with them, if you are interested (contact me directly at enbody at cse.msu.edu). In our department we began using Python in our CS1 course (first programming course for majors) last Fall with the CS2 course still taught in C++. I've surveyed and collected data on whether there is a difference in the CS2 experience -- this spring was the first CS2 offering with students who began with Python. The course just finished so I expect to take a while to sort through the data. I can share it with anyone who is interested. It offers interesting possibilities since some students had Python first while others had something else (C++ and Java mostly). At this point, the instructor of the CS2 course is confident that at the very least the Python students are no worse. -rich enbody at cse.msu.edu Massimo Di Pierro wrote: > Hi David, > I teach at DePaul university where we now use Python in multiple > classes. The way we got it in was not by proposing Python in > substitution to Java or C++. I tried it and that failed for the same > reasons you mention. I got it in by starting to use Python in > algorithms classes instead of pseudo code (and I did not permission to > do it). Python also works great in web development courses (we have a > course on web frameworks and we use web2py) and networking courses. > > Personally I believe that typical intro programming courses are > obsolete because the target population has changed. When our students > come in, although they cannot program, they already understand the > concept of network, data transfer, input/output, files. I think it is > easier to teach programming by teaching how to manipulate these high > level structures and then work your way down to loops and conditionals > that to do it the opposite way, the way we used to do it. > > Massimo > > On May 5, 2008, at 7:24 PM, David MacQuigg wrote: > >> I talked with the CIS department chairman and one of the faculty >> about the possibility of teaching Python at our community college, >> and they weren't interested. (Oh No, not another language ... ) >> Also, the lack of declarations was a show-stopper. >> >> I encountered this same objection from one of the faculty at U of A, >> where I just gave a lecture. It doesn't seem to help when I say: In >> four years of using Python, I can remember only one time when I had a >> subtle error from mistyping a variable name that took an hour to >> track down. I'll gladly trade that hour for the dozens I've saved >> not having to read and write all these declarations. >> >> I've added this to my QnA page at >> http://ece.arizona.edu/~edatools/ece175/Lecture/QnA.txt >> >> >> ''' >> Q2: Without variables declarations, isn't there a problem with mistyped >> variable names leading to subtle errors? >> >> A2: It can happen, but the subtle errors are rather rare. Usually >> you will >> get an immediate and clear message like: >> >> Traceback (most recent call last): >> - - - >> NameError: name 'z' is not defined >> >> where 'z' is the name you intended to type. The subtle error can >> occur if z >> is already defined, and you intended to re-define it. >> >> If you worry about errors like this, you can scan your program with a >> utility like pychecker, and it will detect any variables that are defined >> but never used. >> ''' >> >> Still, I wonder if there isn't a better way to handle this objection >> to Python. I'm thinking of a configuration option in IDLE, something >> that will either: >> >> 1) Run a subset of pychecker tests every time you hit the Run button, or >> 2) Insist on declarations in a comment at the start of every function >> (just the names, not data types). Any name that isn't already >> declared gets immediately painted red. >> >> I would use #1 if it was no time penalty. #2 seems like "training >> wheels" to me, but I would expect some folks who are religious about >> declarations might at least find it re-assuring. >> >> -- Dave >> >> >> _______________________________________________ >> Edu-sig mailing list >> Edu-sig at python.org >> http://mail.python.org/mailman/listinfo/edu-sig > > ------------------------------------------------------------------------ > > _______________________________________________ > Edu-sig mailing list > Edu-sig at python.org > http://mail.python.org/mailman/listinfo/edu-sig > From bonelake at gmail.com Tue May 6 04:30:13 2008 From: bonelake at gmail.com (Brad Miller) Date: Mon, 5 May 2008 21:30:13 -0500 Subject: [Edu-sig] How does Python do Pointers? In-Reply-To: <5.2.1.1.0.20080505131126.03bc9fe8@mail.ece.arizona.edu> References: <5.2.1.1.0.20080505131126.03bc9fe8@mail.ece.arizona.edu> Message-ID: <82298BEE-0EC6-48BA-838F-E8DED48113A0@gmail.com> Just to muddy the waters even further, David Ranum and I have adopted the terminology call by assignment for our upcoming CS1 book. we found this terminology a few Python references and liked it. Here's an excerpt: There are many di?erent ways to pass parameters and di?erent programming languages have chosen to use a variety of them. In Python, however, all parameters are passed using a single mechanism known as call by assignment parameter passing. Call by assignment parameter passing uses a simple two step process to pass data when the function is called, also known as invocation. The ?rst thing that happens is that the actual parame- ters are evaluated. This evaluation results in an object reference to the result. In the ?rst case from Session 6.11, evaluating a literal number simply returns a reference to the number itself. In the second example, evaluating a variable name returns the object reference named by that variable. Once the evaluation of the actual parameters is complete, the object references are passed to and received by the formal parameters in the function. The formal parameter becomes a new name for the reference that is passed. In a sense it is as if we executed the assignment statement formal parameter = actual parameter. Here is Session 6.11: You can fill in the blanks for yourself on the definition of the hypotenuse function. >>> hypotenuse(3,4) 5.0 >>> >>> side1 = 3 >>> side2 = 4 >>> hypotenuse(side1,side2) 5.0 >>> >>> hypotenuse(side1*2, side2*2) 10.0 Brad On May 5, 2008, at 5:06 PM, David MacQuigg wrote: > Many thanks to Michael, Anna and John for the very thorough answers > to this question. I especially like John's sticky-note analogy. I > have been using a similar analogy with "labels", but that gets > confused with the other more common uses of the word "label". > Sticky Note is unique and more memorable. > > I'm disturbed that there doesn't seem to be any agreement on simple > definitions for "call by reference" and "call by value". A Google > search for [python "call by value"] shows there is widespread > confusion in the Python world. I'm not a computer scientist, but > somewhere I did learn these concepts as being simply copying the > value of a variable vs passing just a reference to the original. I > see that my simple understanding agrees with Kernighan and Ritchie > and with http://en.wikipedia.org/wiki/Call_by_value. (Note that > "call-by-reference", as defined in this article, clearly includes > Python's calling method.) > > Luckily, we can answer the question without wading into this swamp. > Here is my latest revision: > > ''' > Python doesn't need pointers because of the simple relationship > between variables and the objects they refer to. A variable has a > name and a pointer to an object. An object has a type, a value, and > an address in memory. Unlike C, the type is with the object, not > the variable. A variable is "bound" to an object much like a sticky > note on a box. Notes can be moved from one box to another, and a > box can have more than one note, or no notes at all. > > Python's pointers are "under the hood", not something the programmer > sees or ever needs to worry about. This part of what makes Python a > higher level language than C. You gain a lot in simplicity and > readability, while losing the ability to work directly with memory > addresses. You also lose a little memory, because objects are more > complex than raw data values. > > The sticky-note analogy has a flaw. You can't stick one note on top > of another. When you say x = y = z, all three variables now point > to the object originally pointed to by z. Then when you say y = 8, > y now points to an integer object 8, but x doesn't move with y. > Python's "sticky notes" have a special glue that sticks only to an > object, not to another variable. > > See http://effbot.org/zone/python-objects.htm for more on Python > objects and variables. > > Note: You can get the address of an object x with the function > id(x), but this is used only to provide a unique identity for the > object, not to access it. If id(x) == id(y), you know that > variables x and y both point to the same object. > ''' > > -- Dave > > > _______________________________________________ > Edu-sig mailing list > Edu-sig at python.org > http://mail.python.org/mailman/listinfo/edu-sig -------------- next part -------------- An HTML attachment was scrubbed... URL: From goldwamh at slu.edu Tue May 6 04:47:09 2008 From: goldwamh at slu.edu (Michael H. Goldwasser) Date: Mon, 5 May 2008 21:47:09 -0500 Subject: [Edu-sig] How does Python do Pointers? In-Reply-To: References: <5.2.1.1.0.20080504113849.016b0708@plus.pop.mail.yahoo.com> <5.2.1.1.0.20080505131126.03bc9fe8@mail.ece.arizona.edu> Message-ID: <18463.50861.595439.203305@Michael-Goldwassers-Computer.local> This is a great discussion. While on the topic, I'd like to share a few more thoughts. * The original discussion in comparing Python's model to close analogs from C was specifically in the context of Dave's original posting. I wholeheartedly agree with John/Kirby in that there is no reason to dig that deep with new (e.g., untainted) programmers. * For newbies, the sticky note analogy is wonderful. I carry around a pad of yellow post-it notes for the entire semester so that I can literally stick them to the objects on the classroom board. It allows us to instill a distinction between names and underlying objects and to portray the assignment semantics. * The analogy also carries over to portray the repeated assignment of a for loop variable to the container's elements. If you don't mind, take a quick peek at the figures on pages 127-132 in Ch. 4 of our book (http://esminfo.prenhall.com/computing/goldwasser/Goldwasser_ch04.pdf). You'll notice the portrayal of the names "guests" and "person" in the context of a "for person in guests:" loop. * As an aside, when picking the style for those images, we intentionally emphasize that the type-awareness is encapsulated within the state of each object (as opposed to with the label). * The analogy of sticky notes also cleanly portrays the parameter passing model. As John and I mentioned in earlier posts, it is precisely the same semantics as assignment. The formal parameter is assigned to the same object identified by the actual parameter. In the classroom we take this a step further and start using a second color post-it note to start laying the framework for the concept of namespaces. If we had been using yellow notes for the names in the caller's context, we start using green notes for names in the local namespace of the function. The same mechanism is used for the return value. BTW, as for the "pass-by-value", "pass-by-reference" terminology, part of the problem is that in the programming language community, those terms aren't always used consistently. In truth, Python is more akin to the notion of "pass-by-name" as in Algol (however the pass-by-name terminology has not really caught on in general). * There is one way in which the sticky note analogy breaks down. It does not accurately portray the internals of a container that references other objects. For example if you look back at our figure on page 127, it gives a false impression that the contents of the list are contained "within" the list. For beginners, this analogy suffices. Also, in this particular case, the elements of the list are immutable and so the distinction is less significant. But in the long run, it is important for students to understand that the list is a list of references (not a list of objects). The sticky note analogy does not work here because because there is no name per se to give an individual element (guests[i] is syntactically useful, but that is not a true name and the particular index is not persistent over time). To portray the underlying objects separate from the container's state, it becomes necessary to draw a picture more akin to the classic "pointer" diagrams. Yet by this point, it is helpful to do so and awareness of the underlying distinction is important. * As a final note, if students are subsequently introduced to the use of dictionaries in their own programming, you can go under the hood to give a true explanation of Python's model. Each namespace is implemented as a dictionary and the names are simply strings that are keys in the dictionary, mapped to the associated value. From within a function body, locals() command returns access to the dictionary representing the local namespace, while globals() returns the global namespace. Further lessons of name resolution can be explored as vars(x) gives the instance-level dictionary for an object x (other than for built-in primitives which do not rely on dictionaries for their internals). vars(Foo) gives the class-level dictionary for a class Foo. +----------------------------------------------- | Michael Goldwasser | Associate Professor | Dept. Mathematics and Computer Science | Saint Louis University | 220 North Grand Blvd. | St. Louis, MO 63103-2007 From goldwamh at slu.edu Tue May 6 05:11:05 2008 From: goldwamh at slu.edu (Michael H. Goldwasser) Date: Mon, 5 May 2008 22:11:05 -0500 Subject: [Edu-sig] How does Python do Pointers? In-Reply-To: <82298BEE-0EC6-48BA-838F-E8DED48113A0@gmail.com> References: <5.2.1.1.0.20080505131126.03bc9fe8@mail.ece.arizona.edu> <82298BEE-0EC6-48BA-838F-E8DED48113A0@gmail.com> Message-ID: <18463.52297.166450.857078@Michael-Goldwassers-Computer.local> Hi Brad, The problem I see with the "call-by-assignment" terminology is that it is ambiguous. In fact, all parameter passing in Python, Java, and C++ would satisfy your call-by-assignment description. The key is that the assignment semantics is different in different circumstances. To illustrate, consider a Java method with the following signature. public void doSomething(int x, Widget w) { ... } If a caller invokes this function using a syntax such as foo.doSomething(myAge, myToaster) The information passing is precisely the same as assigning formal parameters to actual parameters as in x = myAge; w = myToaster; The difference in parameter passing models really boils down to the distinction between assignment semantics for the int type versus an Object type. In C++, the different forms of parameter passing also are all based on the underlying assignment semantics. Calling a function with signature void doSomething(int x, Widget w) { ... } is essentially the same as if the first action within the body were the assignments int x = myAge; Widget w = myToaster; Notice that both of these are value variables and so we get a new int and a new Widget (techincally using the copy constructor rather than the assignment operator, but close enough). If we declare a signature such as void doSomething(int& x, Widget& w) { ... } it would be akin to the declaration and assignments int& x = myAge; Widget& w = myToaster; Finally, if pointers are passed with a signature void doSomething(int* x, Widget* w) { ... } and of course now the caller uses syntax doSomething(&myAge, &myToaster) to send pointers, we again get precisely the same semantics as the implicit assignments int* x = &myAge; Widget* w = &myToaster; So in all of these cases, as with Python, the key seems to be having a correct understanding of the assignment semantics. I wish there were a better commonly accepted name for the parameter passing. Python's model is quite clean, it just doesn't match up perfectly with the standard call-by-??? terminology. With regard, Michael On Monday May 5, 2008, Brad Miller wrote: > Just to muddy the waters even further, David Ranum and I have adopted > the terminology call by assignment for our upcoming CS1 book. we > found this terminology a few Python references and liked it. Here's > an excerpt: > > There are many di??????erent ways to pass parameters and di??????erent > programming languages have chosen to use a variety of them. In Python, > however, all parameters > are passed using a single mechanism known as call by assignment > parameter passing. > > Call by assignment parameter passing uses a simple two step process to > pass data when the > function is called, also known as invocation. The ??????rst thing that > happens is that the actual parame- > ters are evaluated. This evaluation results in an object reference to > the result. In the ??????rst case from > Session 6.11, evaluating a literal number simply returns a reference > to the number itself. In the > second example, evaluating a variable name returns the object > reference named by that variable. > > Once the evaluation of the actual parameters is complete, the object > references are passed to > and received by the formal parameters in the function. The formal > parameter becomes a new > name for the reference that is passed. In a sense it is as if we > executed the assignment statement > formal parameter = actual parameter. +----------------------------------------------- | Michael Goldwasser | Associate Professor | Dept. Mathematics and Computer Science | Saint Louis University | 220 North Grand Blvd. | St. Louis, MO 63103-2007 From macquigg at ece.arizona.edu Tue May 6 16:45:20 2008 From: macquigg at ece.arizona.edu (David MacQuigg) Date: Tue, 06 May 2008 07:45:20 -0700 Subject: [Edu-sig] How does Python do Pointers? In-Reply-To: <18463.52297.166450.857078@Michael-Goldwassers-Computer.loc al> References: <82298BEE-0EC6-48BA-838F-E8DED48113A0@gmail.com> <5.2.1.1.0.20080505131126.03bc9fe8@mail.ece.arizona.edu> <82298BEE-0EC6-48BA-838F-E8DED48113A0@gmail.com> Message-ID: <5.2.1.1.0.20080506035225.016dc9a0@mail.ece.arizona.edu> I agree, there is no reason to dig into call-by-??? terminology with new "untainted" programmers. The sticky-note analogy is all we need for these students. The figures in Michael's book are excellent. However, having been tainted by C, I am finding the discussion interesting. I just don't understand why there is so much confusion with these call-by terms. Does the function get a copy of the object or a reference to the original object? It's got to be one or the other. At 10:11 PM 5/5/2008 -0500, Michael H.Goldwasser wrote: > Python's model is quite clean, it just doesn't match up perfectly > with the standard call-by-??? terminology. In call-by-reference evaluation, a function receives an implicit reference to the argument, rather than a copy of its value. -- http://en.wikipedia.org/wiki/Call_by_value By this definition, Python's model is call-by-reference, even though the reference (pointer) is not seen by the user. C's model is call-by-value, even though that value can be an explicitly-evaluated address (pointer). -- Dave From kirby.urner at gmail.com Tue May 6 17:10:48 2008 From: kirby.urner at gmail.com (kirby urner) Date: Tue, 6 May 2008 08:10:48 -0700 Subject: [Edu-sig] How does Python do Pointers? In-Reply-To: <5.2.1.1.0.20080506035225.016dc9a0@mail.ece.arizona.edu> References: <5.2.1.1.0.20080505131126.03bc9fe8@mail.ece.arizona.edu> <82298BEE-0EC6-48BA-838F-E8DED48113A0@gmail.com> <5.2.1.1.0.20080506035225.016dc9a0@mail.ece.arizona.edu> Message-ID: On Tue, May 6, 2008 at 7:45 AM, David MacQuigg wrote: > I agree, there is no reason to dig into call-by-??? terminology with new "untainted" programmers. The sticky-note analogy is all we need for these students. The figures in Michael's book are excellent. > > However, having been tainted by C, I am finding the discussion interesting. I just don't understand why there is so much confusion with these call-by terms. Does the function get a copy of the object or a reference to the original object? It's got to be one or the other. A succinct summary?: A function gets its own referent for the duration of its scope, but its a referent to the original object, per names passed in the "function mouth" (OK to not call it that, but eat( ) has that emoticon mouth look). The name is what passes by value, in handing off its value to a local in-function name, a name behaving sort of like a C pointer, but more like a generic pointer i.e. like a finger or stick pointing. IDLE 1.2.1 >>> class Foo: pass >>> o = Foo() >>> id(o) 15107256 >>> def f(x): print id(x) >>> f(o) 15107256 Also (continuing in same namespace)... >>> def g(x): x.myname = 'dude' # add gratuitous attribute to Foo object >>> g(o) >>> o.myname # even though x is out of scope, the original object has changed 'dude' Thanks to default arguments, we can pass arguments in any order to some functions: >>> f() 1 2 >>> f(y=100, x='ardvarrk') # mentioning y first, types irrelevant ardvarrk 100 I think this is an important feature to dwell on, as many APIs give a lot of parameters, VPython a great example, but they're all given defaults, ergo ball(pos=(1,0,0)) and ball(color=(1,0,0)) are both meaningful. As the programmer using these APIs, you don't have to care about order of the names, just the names, and even then you can skip some. Kirby > > > At 10:11 PM 5/5/2008 -0500, Michael H.Goldwasser wrote: > > > Python's model is quite clean, it just doesn't match up perfectly > > with the standard call-by-??? terminology. > > In call-by-reference evaluation, a function receives an implicit reference to the argument, rather than a copy of its value. > -- http://en.wikipedia.org/wiki/Call_by_value > > By this definition, Python's model is call-by-reference, even though the reference (pointer) is not seen by the user. C's model is call-by-value, even though that value can be an explicitly-evaluated address (pointer). > > > > -- Dave > > > _______________________________________________ > Edu-sig mailing list > Edu-sig at python.org > http://mail.python.org/mailman/listinfo/edu-sig > From kirby.urner at gmail.com Tue May 6 17:14:47 2008 From: kirby.urner at gmail.com (kirby urner) Date: Tue, 6 May 2008 08:14:47 -0700 Subject: [Edu-sig] How does Python do Pointers? In-Reply-To: References: <5.2.1.1.0.20080505131126.03bc9fe8@mail.ece.arizona.edu> <82298BEE-0EC6-48BA-838F-E8DED48113A0@gmail.com> <5.2.1.1.0.20080506035225.016dc9a0@mail.ece.arizona.edu> Message-ID: > Thanks to default arguments, we can pass arguments in any order to > some functions: > Oops, I missed my redefinition of f: >>> def f(x=1, y=2): print x, y > >>> f() > 1 2 > >>> f(y=100, x='ardvarrk') # mentioning y first, types irrelevant > ardvarrk 100 > Plus misspelled 'aardvark' (sigh). Kirby From john.zelle at wartburg.edu Tue May 6 17:55:07 2008 From: john.zelle at wartburg.edu (John Zelle) Date: Tue, 06 May 2008 10:55:07 -0500 Subject: [Edu-sig] How does Python do Pointers? In-Reply-To: <5.2.1.1.0.20080506035225.016dc9a0@mail.ece.arizona.edu> References: <82298BEE-0EC6-48BA-838F-E8DED48113A0@gmail.com> <5.2.1.1.0.20080505131126.03bc9fe8@mail.ece.arizona.edu> <82298BEE-0EC6-48BA-838F-E8DED48113A0@gmail.com> <5.2.1.1.0.20080506035225.016dc9a0@mail.ece.arizona.edu> Message-ID: <1210089307.6138.33.camel@zelle> David, Actually, I don't think there is that much confusion among the folks who understand/design/study programming languages. Python uses call by value, period, as that term is technically used. But your note below shows the continued confusion (among programmers) about what parameter passing terminology. In classifying calling mechanisms, the question is what happens with a variable being passed and the value it (contains in the traditional usage of those words); it has nothing to do with objects. When modeling Python semantics, a variable actually holds a reference (pointer, address) of an object. When the variable is passed as a parameter, its value (the reference/pointer) is copied into the formal parameter variable. That's it. It's call by value. The confusion and fuzzy thinking comes because the automatic dereferencing of Python variables when they are used in expressions leads people to think about objects being "stored in" variables. Then they talk about whether objects being copied or not copied in function call parameters. But an object is _never_ stored into a Python variable. To see the difference between passing a mutable object in Python vs. a reference parameter in other languages, you just have to ask if you can change the value of the calling code's variable by assigning a value to the corresponding formal parameter in a function. In C++ or Pascal, setting the value of a reference parameter actually changes the contents of the variable in the calling program. def func(formal_param): # change the value of formal_param to be a reference to foo_object formal_param = foo_object x = bar_object func(x) # for pass by reference, x would now contain a foo_object # In Python (pass by value) x is still bar_object. In Python, you cannot change the actual parameter variable (x above). No matter what you do in the function, the actual parameter still contains the same thing, a reference to the same object it was always pointing to at the time of call. That's because the function operates on it own copy of that reference, not the _actual_variable_ of the caller. Summary: Python's parameter passing is just call by value. But Python variable values are always references and Python semantics dictates that those values are dereferenced when variables are used in expressions. That leads some programmers to (imprecisely) talk about parameter passing in terms of variables having objects as values. I often do this loosely myself, because it's easy to think of a Python name as a variable that stores and object. --John On Tue, 2008-05-06 at 07:45 -0700, David MacQuigg wrote: > I agree, there is no reason to dig into call-by-??? terminology with new "untainted" programmers. The sticky-note analogy is all we need for these students. The figures in Michael's book are excellent. > > However, having been tainted by C, I am finding the discussion interesting. I just don't understand why there is so much confusion with these call-by terms. Does the function get a copy of the object or a reference to the original object? It's got to be one or the other. > > At 10:11 PM 5/5/2008 -0500, Michael H.Goldwasser wrote: > > > Python's model is quite clean, it just doesn't match up perfectly > > with the standard call-by-??? terminology. > > In call-by-reference evaluation, a function receives an implicit reference to the argument, rather than a copy of its value. > -- http://en.wikipedia.org/wiki/Call_by_value > > By this definition, Python's model is call-by-reference, even though the reference (pointer) is not seen by the user. C's model is call-by-value, even though that value can be an explicitly-evaluated address (pointer). > > -- Dave > > > _______________________________________________ > Edu-sig mailing list > Edu-sig at python.org > http://mail.python.org/mailman/listinfo/edu-sig > From enbody at cse.msu.edu Tue May 6 18:08:39 2008 From: enbody at cse.msu.edu (Richard Enbody) Date: Tue, 06 May 2008 12:08:39 -0400 Subject: [Edu-sig] How does Python do Pointers? In-Reply-To: <5.2.1.1.0.20080506035225.016dc9a0@mail.ece.arizona.edu> References: <82298BEE-0EC6-48BA-838F-E8DED48113A0@gmail.com> <5.2.1.1.0.20080505131126.03bc9fe8@mail.ece.arizona.edu> <82298BEE-0EC6-48BA-838F-E8DED48113A0@gmail.com> <5.2.1.1.0.20080506035225.016dc9a0@mail.ece.arizona.edu> Message-ID: <48208287.9070802@cse.msu.edu> This discussion has been interesting: we could really drive this discussion into the obscure by bringing in 'passing by name' where actual parameters remain unevaluated until the point of use. :-) I also agree that Michael's 'post-it-note' analogy is a good one for novices. An interesting issue to consider is how to best set up students to understand pointers in subsequent languages. The 'post-it-note' analogy seems to be a reasonable starting point. If one understands naming from that standpoint, transitioning to pointers could be reasonable. I believe we found that to be the case in our transition to a C++ based CS2 course, but I haven't examined the data carefully yet. -rich enbody at cse.msu.edu David MacQuigg wrote: > I agree, there is no reason to dig into call-by-??? terminology with new "untainted" programmers. The sticky-note analogy is all we need for these students. The figures in Michael's book are excellent. > > However, having been tainted by C, I am finding the discussion interesting. I just don't understand why there is so much confusion with these call-by terms. Does the function get a copy of the object or a reference to the original object? It's got to be one or the other. > > At 10:11 PM 5/5/2008 -0500, Michael H.Goldwasser wrote: > > >> Python's model is quite clean, it just doesn't match up perfectly >> with the standard call-by-??? terminology. >> > > In call-by-reference evaluation, a function receives an implicit reference to the argument, rather than a copy of its value. > -- http://en.wikipedia.org/wiki/Call_by_value > > By this definition, Python's model is call-by-reference, even though the reference (pointer) is not seen by the user. C's model is call-by-value, even though that value can be an explicitly-evaluated address (pointer). > > -- Dave > > > _______________________________________________ > Edu-sig mailing list > Edu-sig at python.org > http://mail.python.org/mailman/listinfo/edu-sig > From macquigg at ece.arizona.edu Tue May 6 20:47:24 2008 From: macquigg at ece.arizona.edu (David MacQuigg) Date: Tue, 06 May 2008 11:47:24 -0700 Subject: [Edu-sig] How does Python do Pointers? In-Reply-To: <1210089307.6138.33.camel@zelle> References: <5.2.1.1.0.20080506035225.016dc9a0@mail.ece.arizona.edu> <82298BEE-0EC6-48BA-838F-E8DED48113A0@gmail.com> <5.2.1.1.0.20080505131126.03bc9fe8@mail.ece.arizona.edu> <82298BEE-0EC6-48BA-838F-E8DED48113A0@gmail.com> <5.2.1.1.0.20080506035225.016dc9a0@mail.ece.arizona.edu> Message-ID: <5.2.1.1.0.20080506094259.016b0708@mail.ece.arizona.edu> John, This is the best explanation I've heard so far for why Python is "call by value", but it still leaves me dissatisfied that what I thought was simple (call-by-value) is really complicated and not very useful to me, and what is truly simple (passing a copy of the object) is a useful concept with no name. I also wonder if I'm completely misunderstanding the Wikipedia article (and other texts like K&R - Kernighan and Ritchie p. 27), or if there aren't two schools of thought with conflicting terminology. As usual, the confusion in the discussion arises when there are differing underlying assumptions, unstated and unrecognized. I was assuming the word "value" referred to a part of the object in the simple scheme - variable:(name, pointer) --> object:(type, value, address). I see now that "value" can mean the pointer, and that making a copy of the pointer can be passing a "value". Perhaps we should refer to the object as having (type, data, address) and save the word "value" for the meaning you assume. At 10:55 AM 5/6/2008 -0500, John Zelle wrote: >David, > >Actually, I don't think there is that much confusion among the folks who >understand/design/study programming languages. Python uses call by >value, period, as that term is technically used. But your note below >shows the continued confusion (among programmers) about what parameter >passing terminology. In classifying calling mechanisms, the question is >what happens with a variable being passed and the value it (contains in >the traditional usage of those words); it has nothing to do with >objects. When modeling Python semantics, a variable actually holds a >reference (pointer, address) of an object. When the variable is passed >as a parameter, its value (the reference/pointer) is copied into the >formal parameter variable. That's it. It's call by value. Understood now. The value is the pointer, not the data. >The confusion and fuzzy thinking comes because the automatic >dereferencing of Python variables when they are used in expressions >leads people to think about objects being "stored in" variables. Then >they talk about whether objects being copied or not copied in function >call parameters. But an object is _never_ stored into a Python >variable. Never any misunderstanding for me. >To see the difference between passing a mutable object in Python vs. a >reference parameter in other languages, you just have to ask if you can >change the value of the calling code's variable by assigning a value to >the corresponding formal parameter in a function. With your definition of "value", it never changes. The assignment creates a new local variable in the function's namespace. > In C++ or Pascal, >setting the value of a reference parameter actually changes the contents >of the variable in the calling program. Understood, but now we are using the previous definition of "value". If we use the definition above, changing the "value" just points the parameter name in the function to some other address. In C if I have a parameter (int *x) then x is the address of an int. The actual value passed is an address, and an assignment statement in the function can change the data at that address. But it is still "call-by-value" according to K&R, since the value in this case is an explicit address, with 32 bits of data looking just like an unsigned integer. >def func(formal_param): > # change the value of formal_param to be a reference to foo_object > formal_param = foo_object > >x = bar_object >func(x) ># for pass by reference, x would now contain a foo_object ># In Python (pass by value) x is still bar_object. > >In Python, you cannot change the actual parameter variable (x above). No >matter what you do in the function, the actual parameter still contains >the same thing, a reference to the same object it was always pointing to >at the time of call. That's because the function operates on it own copy >of that reference, not the _actual_variable_ of the caller. > >Summary: Python's parameter passing is just call by value. But Python >variable values are always references and Python semantics dictates that >those values are dereferenced when variables are used in expressions. >That leads some programmers to (imprecisely) talk about parameter >passing in terms of variables having objects as values. I often do this >loosely myself, because it's easy to think of a Python name as a >variable that stores and object. When I hear "variable x has value y" I think of x pointing to object y, not storing y, not even loosely. My confusion is not due to misunderstanding what Python actually does. It seems like there might be a simple alternative to the traditional definition of "call-by-value" in terms of result rather than mechanism. The traditional definition (K&R) is simple if you think of mechanism. The new definition is simple if you think of result (argument in calling program not changeable by the called function). Should we add a note to that Wikipedia page? -- Dave >On Tue, 2008-05-06 at 07:45 -0700, David MacQuigg wrote: >> I agree, there is no reason to dig into call-by-??? terminology with new "untainted" programmers. The sticky-note analogy is all we need for these students. The figures in Michael's book are excellent. >> >> However, having been tainted by C, I am finding the discussion interesting. I just don't understand why there is so much confusion with these call-by terms. Does the function get a copy of the object or a reference to the original object? It's got to be one or the other. >> >> At 10:11 PM 5/5/2008 -0500, Michael H.Goldwasser wrote: >> >> > Python's model is quite clean, it just doesn't match up perfectly >> > with the standard call-by-??? terminology. >> >> In call-by-reference evaluation, a function receives an implicit reference to the argument, rather than a copy of its value. >> -- http://en.wikipedia.org/wiki/Call_by_value >> >> By this definition, Python's model is call-by-reference, even though the reference (pointer) is not seen by the user. C's model is call-by-value, even though that value can be an explicitly-evaluated address (pointer). >> >> -- Dave >> >> >> _______________________________________________ >> Edu-sig mailing list >> Edu-sig at python.org >> http://mail.python.org/mailman/listinfo/edu-sig >> From macquigg at ece.arizona.edu Tue May 6 22:21:05 2008 From: macquigg at ece.arizona.edu (David MacQuigg) Date: Tue, 06 May 2008 13:21:05 -0700 Subject: [Edu-sig] How does Python do Pointers? In-Reply-To: <5.2.1.1.0.20080506094259.016b0708@mail.ece.arizona.edu> References: <1210089307.6138.33.camel@zelle> <5.2.1.1.0.20080506035225.016dc9a0@mail.ece.arizona.edu> <82298BEE-0EC6-48BA-838F-E8DED48113A0@gmail.com> <5.2.1.1.0.20080505131126.03bc9fe8@mail.ece.arizona.edu> <82298BEE-0EC6-48BA-838F-E8DED48113A0@gmail.com> <5.2.1.1.0.20080506035225.016dc9a0@mail.ece.arizona.edu> Message-ID: <5.2.1.1.0.20080506124711.04776cd8@mail.ece.arizona.edu> Fredrik Lundh has yet another point-of-view: http://effbot.org/zone/call-by-object.htm ''' Python?s model is neither "call by value" nor "call by reference" (because any attempt to use those terms for Python requires you to use non-standard definitions of the words "value" and "reference"). The most accurate description is CLU?s "call by object" or "call by sharing". Or, if you prefer, "call by object reference". ... IT IS NOT CALL BY VALUE because mutations of arguments performed by the called routine will be visible to the caller. And IT IS NOT CALL BY REFERENCE because access is not given to the variables of the caller, but merely to certain objects. ~ ''' I guess what we need is a taxonomy of definitions: strict/loose, mechanism/result. I prefer a loose definition based on mechanism, like Kernighan and Ritchie. So for me it's call-by-reference, but I don't mind softening that a bit with "like call-by-reference". For Lundh, its strict definitions only, and Python fits neither. Anyway, it looks like the waters are so muddy now, that the simple concepts of the early days have lost their value. None of this should pollute our classrooms. Let's all stick with sticky notes. :>) -- Dave At 11:47 AM 5/6/2008 -0700, David MacQuigg wrote: >John, > >This is the best explanation I've heard so far for why Python is "call by value", but it still leaves me dissatisfied that what I thought was simple (call-by-value) is really complicated and not very useful to me, and what is truly simple (passing a copy of the object) is a useful concept with no name. I also wonder if I'm completely misunderstanding the Wikipedia article (and other texts like K&R - Kernighan and Ritchie p. 27), or if there aren't two schools of thought with conflicting terminology. > >As usual, the confusion in the discussion arises when there are differing underlying assumptions, unstated and unrecognized. I was assuming the word "value" referred to a part of the object in the simple scheme - variable:(name, pointer) --> object:(type, value, address). I see now that "value" can mean the pointer, and that making a copy of the pointer can be passing a "value". Perhaps we should refer to the object as having (type, data, address) and save the word "value" for the meaning you assume. > >At 10:55 AM 5/6/2008 -0500, John Zelle wrote: > >>David, >> >>Actually, I don't think there is that much confusion among the folks who >>understand/design/study programming languages. Python uses call by >>value, period, as that term is technically used. But your note below >>shows the continued confusion (among programmers) about what parameter >>passing terminology. In classifying calling mechanisms, the question is >>what happens with a variable being passed and the value it (contains in >>the traditional usage of those words); it has nothing to do with >>objects. When modeling Python semantics, a variable actually holds a >>reference (pointer, address) of an object. When the variable is passed >>as a parameter, its value (the reference/pointer) is copied into the >>formal parameter variable. That's it. It's call by value. > >Understood now. The value is the pointer, not the data. > >>The confusion and fuzzy thinking comes because the automatic >>dereferencing of Python variables when they are used in expressions >>leads people to think about objects being "stored in" variables. Then >>they talk about whether objects being copied or not copied in function >>call parameters. But an object is _never_ stored into a Python >>variable. > >Never any misunderstanding for me. > >>To see the difference between passing a mutable object in Python vs. a >>reference parameter in other languages, you just have to ask if you can >>change the value of the calling code's variable by assigning a value to >>the corresponding formal parameter in a function. > >With your definition of "value", it never changes. The assignment creates a new local variable in the function's namespace. > >> In C++ or Pascal, >>setting the value of a reference parameter actually changes the contents >>of the variable in the calling program. > >Understood, but now we are using the previous definition of "value". If we use the definition above, changing the "value" just points the parameter name in the function to some other address. > >In C if I have a parameter (int *x) then x is the address of an int. The actual value passed is an address, and an assignment statement in the function can change the data at that address. But it is still "call-by-value" according to K&R, since the value in this case is an explicit address, with 32 bits of data looking just like an unsigned integer. > >>def func(formal_param): >> # change the value of formal_param to be a reference to foo_object >> formal_param = foo_object >> >>x = bar_object >>func(x) >># for pass by reference, x would now contain a foo_object >># In Python (pass by value) x is still bar_object. >> >>In Python, you cannot change the actual parameter variable (x above). No >>matter what you do in the function, the actual parameter still contains >>the same thing, a reference to the same object it was always pointing to >>at the time of call. That's because the function operates on it own copy >>of that reference, not the _actual_variable_ of the caller. >> >>Summary: Python's parameter passing is just call by value. But Python >>variable values are always references and Python semantics dictates that >>those values are dereferenced when variables are used in expressions. >>That leads some programmers to (imprecisely) talk about parameter >>passing in terms of variables having objects as values. I often do this >>loosely myself, because it's easy to think of a Python name as a >>variable that stores and object. > >When I hear "variable x has value y" I think of x pointing to object y, not storing y, not even loosely. My confusion is not due to misunderstanding what Python actually does. > >It seems like there might be a simple alternative to the traditional definition of "call-by-value" in terms of result rather than mechanism. The traditional definition (K&R) is simple if you think of mechanism. The new definition is simple if you think of result (argument in calling program not changeable by the called function). > >Should we add a note to that Wikipedia page? > >-- Dave > > >>On Tue, 2008-05-06 at 07:45 -0700, David MacQuigg wrote: >>> I agree, there is no reason to dig into call-by-??? terminology with new "untainted" programmers. The sticky-note analogy is all we need for these students. The figures in Michael's book are excellent. >>> >>> However, having been tainted by C, I am finding the discussion interesting. I just don't understand why there is so much confusion with these call-by terms. Does the function get a copy of the object or a reference to the original object? It's got to be one or the other. >>> >>> At 10:11 PM 5/5/2008 -0500, Michael H.Goldwasser wrote: >>> >>> > Python's model is quite clean, it just doesn't match up perfectly >>> > with the standard call-by-??? terminology. >>> >>> In call-by-reference evaluation, a function receives an implicit reference to the argument, rather than a copy of its value. >>> -- http://en.wikipedia.org/wiki/Call_by_value >>> >>> By this definition, Python's model is call-by-reference, even though the reference (pointer) is not seen by the user. C's model is call-by-value, even though that value can be an explicitly-evaluated address (pointer). >>> >>> -- Dave >>> >>> >>> _______________________________________________ >>> Edu-sig mailing list >>> Edu-sig at python.org >>> http://mail.python.org/mailman/listinfo/edu-sig >>> > > >_______________________________________________ >Edu-sig mailing list >Edu-sig at python.org >http://mail.python.org/mailman/listinfo/edu-sig From kirby.urner at gmail.com Wed May 7 00:43:20 2008 From: kirby.urner at gmail.com (kirby urner) Date: Tue, 6 May 2008 15:43:20 -0700 Subject: [Edu-sig] How does Python do Pointers? In-Reply-To: <5.2.1.1.0.20080506124711.04776cd8@mail.ece.arizona.edu> References: <1210089307.6138.33.camel@zelle> <5.2.1.1.0.20080505131126.03bc9fe8@mail.ece.arizona.edu> <82298BEE-0EC6-48BA-838F-E8DED48113A0@gmail.com> <5.2.1.1.0.20080506035225.016dc9a0@mail.ece.arizona.edu> <5.2.1.1.0.20080506094259.016b0708@mail.ece.arizona.edu> <5.2.1.1.0.20080506124711.04776cd8@mail.ece.arizona.edu> Message-ID: Although I like the post-its analogy, good advertising for 3M, there's an implied thesis about proximity (post-its "stick to" something) whereas I'd like students to thing of objects as potentially very heavy and far removed, connected more by wire or rope. This matches very early conversations about edu-sig about Python's bias against copying, i.e. you need to import from a separate module, and even then, deepcopy is something special, considered usually unneeded, i.e. Python the design, like any design, encourages and discourages ways of thinking, and Guido is pretty clear about what he's trying to cut down on (copying). Because once your names really do point to objects, potentially associated with huge amounts of data (as objects may be), then you really *don't* want some x = y assignment to involve truly copying anything, as that implies potentially major consequences in memory sometimes. So I'd say Python's emphasis on names sharing an object, is consistent with Python's strong bias against copying. I like the point made earlier that parameter passing at the function gateway is all about assignment, and assignment is all about cloning a pointer or reference, for use within the local scope, and these names are by definition something tiny, whereas the objects themselves -- who knows how big these might be. Kirby 2008/5/6 David MacQuigg : > Fredrik Lundh has yet another point-of-view: > > http://effbot.org/zone/call-by-object.htm > ''' > Python's model is neither "call by value" nor "call by reference" (because any attempt to use those terms for Python requires you to use non-standard definitions of the words "value" and "reference"). The most accurate description is CLU's "call by object" or "call by sharing". Or, if you prefer, "call by object reference". > ... > IT IS NOT CALL BY VALUE because mutations of arguments performed by the called routine will be visible to the caller. And IT IS NOT CALL BY REFERENCE because access is not given to the variables of the caller, but merely to certain objects. > ~ ''' > > I guess what we need is a taxonomy of definitions: strict/loose, mechanism/result. I prefer a loose definition based on mechanism, like Kernighan and Ritchie. So for me it's call-by-reference, but I don't mind softening that a bit with "like call-by-reference". For Lundh, its strict definitions only, and Python fits neither. > > Anyway, it looks like the waters are so muddy now, that the simple concepts of the early days have lost their value. None of this should pollute our classrooms. Let's all stick with sticky notes. :>) > > -- Dave > > > > > At 11:47 AM 5/6/2008 -0700, David MacQuigg wrote: > > >John, > > > >This is the best explanation I've heard so far for why Python is "call by value", but it still leaves me dissatisfied that what I thought was simple (call-by-value) is really complicated and not very useful to me, and what is truly simple (passing a copy of the object) is a useful concept with no name. I also wonder if I'm completely misunderstanding the Wikipedia article (and other texts like K&R - Kernighan and Ritchie p. 27), or if there aren't two schools of thought with conflicting terminology. > > > >As usual, the confusion in the discussion arises when there are differing underlying assumptions, unstated and unrecognized. I was assuming the word "value" referred to a part of the object in the simple scheme - variable:(name, pointer) --> object:(type, value, address). I see now that "value" can mean the pointer, and that making a copy of the pointer can be passing a "value". Perhaps we should refer to the object as having (type, data, address) and save the word "value" for the meaning you assume. > > > >At 10:55 AM 5/6/2008 -0500, John Zelle wrote: > > > >>David, > >> > >>Actually, I don't think there is that much confusion among the folks who > >>understand/design/study programming languages. Python uses call by > >>value, period, as that term is technically used. But your note below > >>shows the continued confusion (among programmers) about what parameter > >>passing terminology. In classifying calling mechanisms, the question is > >>what happens with a variable being passed and the value it (contains in > >>the traditional usage of those words); it has nothing to do with > >>objects. When modeling Python semantics, a variable actually holds a > >>reference (pointer, address) of an object. When the variable is passed > >>as a parameter, its value (the reference/pointer) is copied into the > >>formal parameter variable. That's it. It's call by value. > > > >Understood now. The value is the pointer, not the data. > > > >>The confusion and fuzzy thinking comes because the automatic > >>dereferencing of Python variables when they are used in expressions > >>leads people to think about objects being "stored in" variables. Then > >>they talk about whether objects being copied or not copied in function > >>call parameters. But an object is _never_ stored into a Python > >>variable. > > > >Never any misunderstanding for me. > > > >>To see the difference between passing a mutable object in Python vs. a > >>reference parameter in other languages, you just have to ask if you can > >>change the value of the calling code's variable by assigning a value to > >>the corresponding formal parameter in a function. > > > >With your definition of "value", it never changes. The assignment creates a new local variable in the function's namespace. > > > >> In C++ or Pascal, > >>setting the value of a reference parameter actually changes the contents > >>of the variable in the calling program. > > > >Understood, but now we are using the previous definition of "value". If we use the definition above, changing the "value" just points the parameter name in the function to some other address. > > > >In C if I have a parameter (int *x) then x is the address of an int. The actual value passed is an address, and an assignment statement in the function can change the data at that address. But it is still "call-by-value" according to K&R, since the value in this case is an explicit address, with 32 bits of data looking just like an unsigned integer. > > > >>def func(formal_param): > >> # change the value of formal_param to be a reference to foo_object > >> formal_param = foo_object > >> > >>x = bar_object > >>func(x) > >># for pass by reference, x would now contain a foo_object > >># In Python (pass by value) x is still bar_object. > >> > >>In Python, you cannot change the actual parameter variable (x above). No > >>matter what you do in the function, the actual parameter still contains > >>the same thing, a reference to the same object it was always pointing to > >>at the time of call. That's because the function operates on it own copy > >>of that reference, not the _actual_variable_ of the caller. > >> > >>Summary: Python's parameter passing is just call by value. But Python > >>variable values are always references and Python semantics dictates that > >>those values are dereferenced when variables are used in expressions. > >>That leads some programmers to (imprecisely) talk about parameter > >>passing in terms of variables having objects as values. I often do this > >>loosely myself, because it's easy to think of a Python name as a > >>variable that stores and object. > > > >When I hear "variable x has value y" I think of x pointing to object y, not storing y, not even loosely. My confusion is not due to misunderstanding what Python actually does. > > > >It seems like there might be a simple alternative to the traditional definition of "call-by-value" in terms of result rather than mechanism. The traditional definition (K&R) is simple if you think of mechanism. The new definition is simple if you think of result (argument in calling program not changeable by the called function). > > > >Should we add a note to that Wikipedia page? > > > >-- Dave > > > > > >>On Tue, 2008-05-06 at 07:45 -0700, David MacQuigg wrote: > >>> I agree, there is no reason to dig into call-by-??? terminology with new "untainted" programmers. The sticky-note analogy is all we need for these students. The figures in Michael's book are excellent. > >>> > >>> However, having been tainted by C, I am finding the discussion interesting. I just don't understand why there is so much confusion with these call-by terms. Does the function get a copy of the object or a reference to the original object? It's got to be one or the other. > >>> > >>> At 10:11 PM 5/5/2008 -0500, Michael H.Goldwasser wrote: > >>> > >>> > Python's model is quite clean, it just doesn't match up perfectly > >>> > with the standard call-by-??? terminology. > >>> > >>> In call-by-reference evaluation, a function receives an implicit reference to the argument, rather than a copy of its value. > >>> -- http://en.wikipedia.org/wiki/Call_by_value > >>> > >>> By this definition, Python's model is call-by-reference, even though the reference (pointer) is not seen by the user. C's model is call-by-value, even though that value can be an explicitly-evaluated address (pointer). > >>> > >>> -- Dave > >>> > >>> > >>> _______________________________________________ > >>> Edu-sig mailing list > >>> Edu-sig at python.org > >>> http://mail.python.org/mailman/listinfo/edu-sig > >>> > > > > > >_______________________________________________ > >Edu-sig mailing list > >Edu-sig at python.org > >http://mail.python.org/mailman/listinfo/edu-sig > > > > _______________________________________________ > Edu-sig mailing list > Edu-sig at python.org > http://mail.python.org/mailman/listinfo/edu-sig > > From kirby.urner at gmail.com Wed May 7 01:05:14 2008 From: kirby.urner at gmail.com (kirby urner) Date: Tue, 6 May 2008 16:05:14 -0700 Subject: [Edu-sig] How does Python do Pointers? In-Reply-To: References: <1210089307.6138.33.camel@zelle> <5.2.1.1.0.20080505131126.03bc9fe8@mail.ece.arizona.edu> <82298BEE-0EC6-48BA-838F-E8DED48113A0@gmail.com> <5.2.1.1.0.20080506035225.016dc9a0@mail.ece.arizona.edu> <5.2.1.1.0.20080506094259.016b0708@mail.ece.arizona.edu> <5.2.1.1.0.20080506124711.04776cd8@mail.ece.arizona.edu> Message-ID: Just to add a few words, I think a big dog, like an English Mastiff, tugging really hard on a leash, would be a good place to start, in some cartoon YouTube about Python. When I get to some dog washing storefront, I hand another leash to the dog washer, same dog at the end, washer goes inside, has control of the dog object, does local scope thing with soap. The dog at the other end of my leash (was there the whole time) gets a good cleanup (thanks to this function). Maybe better than a post-it is a remote controller like for robot, or console game system? Lots of little buttons, some strangely shaped. Your having a name (handle, token) means you can do stuff like dog.attribute, dog( ) -- called calling, triggers __call__ -- dog[ ] (__getitem__) other syntax games (maybe use operators as in dogA + dogB). The point is your "post-it" (remote) has all these triggering abilities, makes you the puppet master of the (maybe faraway) object. So it's a combination of those images: like a leash, or a rope, a connection, but also a set of controls, ways to send messages, read state, trigger methods (however we want to talk about it -- standard OO ways of doing so). When we get to a function, we hand over a set of controls (a remote, an api), which get destroyed when they go out of scope, but in the meantime give the local scope some control or at least contact with the underlying controlees (the objects). These objects usually have no way of knowing the identities of their potentially many handlers -- you could code that in some higher level MVC, but Python out of the box keeps objects in the dark about such matters. Kirby 4D Sorry for typos below: On Tue, May 6, 2008 at 3:43 PM, kirby urner wrote: > Although I like the post-its analogy, good advertising for 3M, there's > an implied thesis about proximity (post-its "stick to" something) > whereas I'd like students to thing of objects as potentially very > heavy and far removed, connected more by wire or rope. > > This matches very early conversations about edu-sig about Python's > bias against copying, i.e. you need to import from a separate module, > and even then, deepcopy is something special, considered usually > unneeded, i.e. Python the design, like any design, encourages and > discourages ways of thinking, and Guido is pretty clear about what > he's trying to cut down on (copying). > > Because once your names really do point to objects, potentially > associated with huge amounts of data (as objects may be), then you > really *don't* want some x = y assignment to involve truly copying > anything, as that implies potentially major consequences in memory > sometimes. > > So I'd say Python's emphasis on names sharing an object, is consistent > with Python's strong bias against copying. > > I like the point made earlier that parameter passing at the function > gateway is all about assignment, and assignment is all about cloning a > pointer or reference, for use within the local scope, and these names > are by definition something tiny, whereas the objects themselves -- > who knows how big these might be. > > Kirby From kirby.urner at gmail.com Wed May 7 18:49:39 2008 From: kirby.urner at gmail.com (kirby urner) Date: Wed, 7 May 2008 09:49:39 -0700 Subject: [Edu-sig] How does Python do Pointers? In-Reply-To: References: <1210089307.6138.33.camel@zelle> <5.2.1.1.0.20080505131126.03bc9fe8@mail.ece.arizona.edu> <82298BEE-0EC6-48BA-838F-E8DED48113A0@gmail.com> <5.2.1.1.0.20080506035225.016dc9a0@mail.ece.arizona.edu> <5.2.1.1.0.20080506094259.016b0708@mail.ece.arizona.edu> <5.2.1.1.0.20080506124711.04776cd8@mail.ece.arizona.edu> Message-ID: > > I like the point made earlier that parameter passing at the function > > gateway is all about assignment, and assignment is all about cloning a > > pointer or reference, for use within the local scope, and these names > > are by definition something tiny, whereas the objects themselves -- > > who knows how big these might be. > > > > Kirby > Per my blog entry on this topic (mostly just pointing back here http://mybizmo.blogspot.com/2008/05/memory-managment.html ), you might explicitly do the assignment x = y right in the function header e.g. def g (x = y): is legal provide y has meaning in the global scope by the time we reach this definition. So to prove arguments "pass by assignment" you could go: >>> class MegaLith: pass >>> y = MegaLith() # y gets to control one >>> def f(x = y): x.color = "grey" # x does too, interimly... Note you'd get an error if y weren't already defined. The more normal think is to have your right side defaults be hard-coded values, not variables (names). >>> f( ) # don't forget to actually do the work >>> y.color 'grey' >>> # tada! >>> The picture here would be x and y both tied to the same MegaLith object, but x only while we're in the scope of function f. Kirby From jjposner at snet.net Thu May 8 17:05:45 2008 From: jjposner at snet.net (John Posner) Date: Thu, 08 May 2008 11:05:45 -0400 Subject: [Edu-sig] How does Python do Pointers? In-Reply-To: References: Message-ID: <002101c8b11c$fdf79140$65bda8c0@jposner> > The sticky-note analogy has a flaw. You can't stick one > note on top > of another. When you say x = y = z, all three variables > now point to > the object originally pointed to by z. Then when you say y = 8, > y now points to an integer object 8, but x doesn't move with y. > Python's "sticky notes" have a special glue that sticks only to an > object, not to another variable. IMHO it's not a flaw, but a blessing. Extending the "sticky notes" analogy by referring to "special glue" is a very intuitive way to explain the language feature you describe above -- assigning then reassigning "y". You might not like that language feature, but don't place the blame on the analogy! > In the classroom we take this a step further and start using a > second color post-it note to start laying the framework for the > concept of namespaces. If we had been using yellow notes for the > names in the caller's context, we start using green notes for names > in the local namespace of the function. Excellent! And you could also use multiple sticky-note colors (or multiple shapes -- they exist, too) to introduce the concept of typed variables. Switching for a moment to that other thread ("Introducing Python at our community college"), I don't think that anyone mentioned using "assert" to implement typed variables. Example: def myfunc(stringparm, listparm, intparm): """ function with typed parameters, courtesy of "assert" """ # check parameter types assert type(stringparm) is type('abc') assert type(listparm) is type(['a', 'b']) assert type(intparm) is type(123) # do the work print "All OK" return # ------------------------------------------ >>> f.myfunc('a', range(3), 44) All OK >>> f.myfunc(range(3), 44, 'a') Traceback (most recent call last): File "c:\temp\", line 1, in File "c:\temp\f.py", line 6, in myfunc assert type(stringparm) is type('abc') AssertionError: > * There is one way in which the sticky note analogy breaks down. It > does not accurately portray the internals of a container that > references other objects. For example if you look back at our > figure on page 127, it gives a false impression that the contents > of the list are contained "within" the list. For beginners, this > analogy suffices. Also, in this particular case, the elements of > the list are immutable and so the distinction is less significant. I'm not sure, but I think the sticky-notes analogy *can* be extended to container objects (though it seems that John Zelle doesn't do this in his textbook): * dictionary: an unordered set of sticky-notes * list: an ordered set of sticky-notes, in which the names on the notes can be changed dynamically by the Python interpreter -- e.g. when a new member of the list is inserted. I would agree, though, that analogies shouldn't be extended past the point where they help students understand the actual language features. And just to get a word in on the original question -- how does Python do pointers -- what about iterators? From a functional viewpoint, isn't the next() operation just like incrementing a pointer? -John From kirby.urner at gmail.com Thu May 8 18:31:59 2008 From: kirby.urner at gmail.com (kirby urner) Date: Thu, 8 May 2008 09:31:59 -0700 Subject: [Edu-sig] How does Python do Pointers? In-Reply-To: <002101c8b11c$fdf79140$65bda8c0@jposner> References: <002101c8b11c$fdf79140$65bda8c0@jposner> Message-ID: On Thu, May 8, 2008 at 8:05 AM, John Posner wrote: >> The sticky-note analogy has a flaw. You can't stick one >> note on top of another. When you say x = y = z, all three variables >> now point to the object originally pointed to by z. Then when you >> say y = 8, y now points to an integer object 8, but x doesn't move >> with y. Python's "sticky notes" have a special glue that sticks only >> to an object, not to another variable. > > IMHO it's not a flaw, but a blessing. Extending the "sticky notes" analogy > by referring to "special glue" is a very intuitive way to explain the > language feature you describe above -- assigning then reassigning "y". You > might not like that language feature, but don't place the blame on the > analogy! > A point someone made earlier, and important to emphasize, is that 8 is an object, but doesn't admit state changes i.e. 8.value = 9 is meaningless. Type int, like type string, like type tuple, is immutable and therefore suitable as a key to a dictionary. If you go x = y = z and then change the state of whatever y points to or references, then x and z will now both communicate this change if queried (triggering __getattribute__ or whatever). However to say y = 5 is to rebind it to another object entirely, leaving x and z to stay sticking to 8. Partly why it's misleading to speak of names as variables is that shoptalk tends to prevent us from seeing 8 as the *name* of an immutable object, one for which the name is hardwired (but feel free to bind, or assign, other not-spoken-for names to the same object). Note that 8 .__str__( ) has meaning but 8.__str__( ) does not (note space after 8 in the first expressioni) because in the latter case it thinks you're building a decimal then perversely switching to non-numeric characters. The parser needs that space to know you mean to trigger 8's string method, i.e. you're using dot notation on a name, communicating with its referenced object per the standard Python "special names" API (the __rib__ cage). >> In the classroom we take this a step further and start using a >> second color post-it note to start laying the framework for the >> concept of namespaces. If we had been using yellow notes for the >> names in the caller's context, we start using green notes for names >> in the local namespace of the function. > > Excellent! And you could also use multiple sticky-note colors (or multiple > shapes -- they exist, too) to introduce the concept of typed variables. > Switching for a moment to that other thread ("Introducing Python at our > community college"), I don't think that anyone mentioned using "assert" to > implement typed variables. Example: > > def myfunc(stringparm, listparm, intparm): > """ > function with typed parameters, > courtesy of "assert" > """ > # check parameter types > assert type(stringparm) is type('abc') > assert type(listparm) is type(['a', 'b']) > assert type(intparm) is type(123) > > # do the work > print "All OK" > return > # ------------------------------------------ > >>> f.myfunc('a', range(3), 44) > All OK > > >>> f.myfunc(range(3), 44, 'a') > Traceback (most recent call last): > File "c:\temp\", line 1, in > File "c:\temp\f.py", line 6, in myfunc > assert type(stringparm) is type('abc') > AssertionError: Good point that type checking is highly doable in Python, a good counter to those saying Python is only weakly typed or even untyped. Dynamically typed is better. Then of course we say "duck typing" a lot (if it walks like a duck, talks like a duck...), meaning in Javaspeak that if the interface is obeyed, then you can treat it as an object of that type, not that interface obedience is enforced at compile time (one assumes the programmer knows what a duck is) -- late binding is a runtime feature. >> * There is one way in which the sticky note analogy breaks down. It >> does not accurately portray the internals of a container that >> references other objects. For example if you look back at our >> figure on page 127, it gives a false impression that the contents >> of the list are contained "within" the list. For beginners, this >> analogy suffices. Also, in this particular case, the elements of >> the list are immutable and so the distinction is less significant. > > I'm not sure, but I think the sticky-notes analogy *can* be extended to > container objects (though it seems that John Zelle doesn't do this in his > textbook): > > * dictionary: an unordered set of sticky-notes > * list: an ordered set of sticky-notes, in which the names on the notes > can be changed dynamically by the Python interpreter -- e.g. when a new > member of the list is inserted. > > I would agree, though, that analogies shouldn't be extended past the point > where they help students understand the actual language features. > In the code below, I build a list of Rod objects, then create a "box" of rods as a dictionary, keyed by single letters (very *like* names, but not). In this implementation, Rod objects don't get names of their own, but have to rely on the built-in hash table mechanism, i.e. the eleven Rods are not bound to top level names, except indirectly through the names of collection objects (both "rodobjects" and "box" in this example): rodnames = ['z','w','r','g','p','y','d','b','t','B','o'] rodobjects = [ Rod(length = 0, color = 'none'), # zero rod Rod(length = 1, color = 'white'), Rod(length = 2, color = 'red'), Rod(length = 3, color = 'light green'), Rod(length = 4, color = 'pink'), Rod(length = 5, color = 'yellow'), Rod(length = 6, color = 'dark green'), Rod(length = 7, color = 'black'), Rod(length = 8, color = 'tan'), Rod(length = 9, color = 'blue'), Rod(length = 10, color = 'orange')] box = dict(zip(rodnames, rodobjects)) > > And just to get a word in on the original question -- how does Python do > pointers -- what about iterators? From a functional viewpoint, isn't the > next() operation just like incrementing a pointer? > > -John The interface for the iterator type is pretty simple, in that you need to have a next method (__next__ under the hood). In pointer arithemetic, there's this assumption of target memory already allocated (through malloc) and incrementing a pointer to move ahead to existing data. In Python, to next(iterable) is to probably trigger some code that creates new objects in memory, maybe destroys old ones. Lots of objects may change state. But there's no sense that these state changes were computed ahead of time, as is more usually the case in the shoptalk around pointers (when in the C family). Iterators derive from the idea of lazy or just in time evaluation, important in many languages. Generators very closely related (use them to implement iterators a lot). Kirby From macquigg at ece.arizona.edu Thu May 8 19:48:40 2008 From: macquigg at ece.arizona.edu (David MacQuigg) Date: Thu, 08 May 2008 10:48:40 -0700 Subject: [Edu-sig] Sticky-note Analogy In-Reply-To: <002101c8b11c$fdf79140$65bda8c0@jposner> References: Message-ID: <5.2.1.1.0.20080508102606.047926c8@mail.ece.arizona.edu> At 11:05 AM 5/8/2008 -0400, John Posner wrote: >> The sticky-note analogy has a flaw. You can't stick one note on top >> of another. When you say x = y = z, all three variables now point to >> the object originally pointed to by z. Then when you say y = 8, >> y now points to an integer object 8, but x doesn't move with y. >> Python's "sticky notes" have a special glue that sticks only to an >> object, not to another variable. > >IMHO it's not a flaw, but a blessing. Extending the "sticky notes" analogy >by referring to "special glue" is a very intuitive way to explain the >language feature you describe above -- assigning then reassigning "y". You >might not like that language feature, but don't place the blame on the >analogy! I too was a little uncomfortable with the wording of this paragraph, but I think it isn't the first sentence that needs revision. We really *don't want* to stick one note on top of another, as the second sentence might imply. Here is a suggested revision: The sticky-note analogy has a small flaw. If you put one note on top of another, they both move together, and that is not what happens in Python. When you say x = y = 0, both variables now point to an integer object with value 0. Then when you say y = 8, y now points to another object, but x doesn't move with y. Python's "sticky notes" have a special glue that sticks only to an object, not to another variable. >> In the classroom we take this a step further and start using a >> second color post-it note to start laying the framework for the >> concept of namespaces. If we had been using yellow notes for the >> names in the caller's context, we start using green notes for names >> in the local namespace of the function. > >Excellent! And you could also use multiple sticky-note colors (or multiple >shapes -- they exist, too) to introduce the concept of typed variables. >Switching for a moment to that other thread ("Introducing Python at our >community college"), I don't think that anyone mentioned using "assert" to >implement typed variables. Example: > > def myfunc(stringparm, listparm, intparm): > """ > function with typed parameters, > courtesy of "assert" > """ > # check parameter types > assert type(stringparm) is type('abc') > assert type(listparm) is type(['a', 'b']) > assert type(intparm) is type(123) > > # do the work > print "All OK" > return > # ------------------------------------------ > >>> f.myfunc('a', range(3), 44) > All OK > > >>> f.myfunc(range(3), 44, 'a') > Traceback (most recent call last): > File "c:\temp\", line 1, in > File "c:\temp\f.py", line 6, in myfunc > assert type(stringparm) is type('abc') > AssertionError: The idiom I prefer is assert isinstance(stringparm, str) assert isinstance(m, MegaList) This allows the argument to be a subclass, not just a perfect match. Allowing subclasses is usually what you want. -- Dave From kirby.urner at gmail.com Thu May 8 22:15:52 2008 From: kirby.urner at gmail.com (kirby urner) Date: Thu, 8 May 2008 13:15:52 -0700 Subject: [Edu-sig] Sticky-note Analogy In-Reply-To: <5.2.1.1.0.20080508102606.047926c8@mail.ece.arizona.edu> References: <002101c8b11c$fdf79140$65bda8c0@jposner> <5.2.1.1.0.20080508102606.047926c8@mail.ece.arizona.edu> Message-ID: On Thu, May 8, 2008 at 10:48 AM, David MacQuigg wrote: > I too was a little uncomfortable with the wording of this paragraph, but I think it isn't the first sentence that needs revision. We really *don't want* to stick one note on top of another, as the second sentence might imply. Here is a suggested revision: > The sticky-note analogy has a small flaw. If you put one note on top of another, they both move together, and that is not what happens in Python. When you say x = y = 0, both variables now point to an integer object with value 0. Then when you say y = 8, y now points to another object, but x doesn't move with y. Python's "sticky notes" have a special glue that sticks only to an object, not to another variable. Yes, x = y = z = 0 is a way of passing through an assignment, from a single legal right sider (in this case an object designated with a literal) to three legal left siders (variable names, assignable tokens, invented for the namespace and not hardwired in Python to immutables like True or False or 0 are hardwired). Left siders may be Chinese ideograms or Hebrew strings since Python 3.0, likewise function and class names, as used in their definitions with the keywords def and class respectively (keywords stay in their Latin-1 forms, as does the __rib__ cage etc.). A question is whether existing or future PEPs will suggest opening the __rib__ cage to non-Latin-1 characters, such as for operator overloading i.e. new operators in Klingon or whatever. As of now, the list of special names is closed to the programmer. x = y wouldn't make any sense if y weren't already a name of some object, which is why def f ( x = y ): is only legal Python if there's a y already defined in the namespace. def f (x = 0): always makes sense, because 0 is in every Pythonic namespace, as is '0'. >>> del 8 SyntaxError: can't delete literal >>> del '8' SyntaxError: can't delete literal I've suggested seeing 8 as a name ("seeing as" as in "temporary gestalt switch"), even though it's a literal, just so we briefly understand it's also a token, like eight, such that 8 .__add__(5) means essentially the same thing as eight = 8; eight.__add__(5), except we add to the namespace in the latter example (by contributing the name eight). In terms of the postit analogy, I would agree that we don't stick post-its on post-its (we just don't), because to assign is to pass-by-value an object reference or pointer (something more than a memory address, because it provides an API to the referenced object), and top-level names aren't themselves something we point to. We *use* names, we don't *reference* them. Names conspire amongst themselves to only point off stage to objects. A namespace as a whole (think of a module) is a memory management scheme (it works with stuff in memory, on the heap), with the various objects managed in the guts of the Python interpreter (very agile). I think it's helpful in some cases to say "all objects are essentially anonymous including the one designated by 8." This is another way of saying that average workaday objects don't really care what they're called. Objects are blissfully ignorant of their own names. However, with the gc module and such, it's possible for the Python interpreter to introspect, i.e. there are ways to get at this information, outside of interrogating the objects. Kirby From warren.sande at rogers.com Thu May 8 22:37:44 2008 From: warren.sande at rogers.com (Warren Sande) Date: Thu, 8 May 2008 13:37:44 -0700 (PDT) Subject: [Edu-sig] Programming book for Kids Message-ID: <714466.21302.qm@web88102.mail.re2.yahoo.com> A few months ago, I made a post looking for reviewers for a programming book for kids, which uses Python. Several members of this list responded and were involved in reviewing the manuscript. The book is now in the final stages of production, and it is available for pre-order on Amazon. It is scheduled for release in September. The title is: "Hello World! Computer Programming for Kids and Other Beginners" Here is the link on Amazon: http://www.amazon.com/Hello-World-Computer-Programming-Beginners/dp/1933988495/ref=pd_bbs_sr_1?ie=UTF8&s=books&qid=1210278845&sr=8-1 Here is the page on the publishers web site: http://www.manning.com/sande/ Amazon has it on sale at the moment. (Don't ask me why - I don't have a clue how their pricing works.) Regards, Warren Sande -------------- next part -------------- An HTML attachment was scrubbed... URL: From jjposner at snet.net Fri May 9 07:08:05 2008 From: jjposner at snet.net (John Posner) Date: Fri, 09 May 2008 01:08:05 -0400 Subject: [Edu-sig] Sticky-note Analogy In-Reply-To: References: Message-ID: <008201c8b192$a9d1ce20$65bda8c0@jposner> > Partly why it's misleading to speak of names as variables is > that shoptalk tends to prevent us from seeing 8 as the *name* > of an immutable object, one for which the name is hardwired > (but feel free to bind, or assign, other not-spoken-for names > to the same object). I don't see the advantage of thinking of "8" as a name. It's just some syntax that creates an unnamed object. In that sense, all of these are similar: 8 8 + 3 Rod(length = 9, color = 'blue') In all these cases, the resulting object gets a name only if it's the RHS of an assignment. If not, the object disappears (from the user's viewpoint, anyway) as soon as the containing statement/expression is executed. Also, what do you say to the student who points out that "8 is a name" violates the rule that Python names must begin with a letter or underscore? -John From kirby.urner at gmail.com Fri May 9 16:30:07 2008 From: kirby.urner at gmail.com (kirby urner) Date: Fri, 9 May 2008 07:30:07 -0700 Subject: [Edu-sig] Sticky-note Analogy In-Reply-To: <008201c8b192$a9d1ce20$65bda8c0@jposner> References: <008201c8b192$a9d1ce20$65bda8c0@jposner> Message-ID: I've suggesting seeing 8 as a name only briefly, temporary gestalt switch, then go back to seeing it as a literal, kind of like a name in that you can do dot notation on it, i.e. there's an underlying object that's responsive to these triggers (like 8 .__add__(5) instead of just 8 + 5). But is the underlying object "anonymous"? It has a memory location: >>> id(8) 12015636 >>> id('8') 13259744 And I'm able to refer to it. I didn't make up a name for it, like eight, because I didn't need to, it's already permanently accessible through 8. It's more like an already assigned global in that it'll never go out of scope. It's available as a literal and is in that sense a spoken-for, pre-named name, but we call it a literal, leaving name to mean what the programmer makes up, following those rules you mention (and so "variable" in the sense of being a user-defined alphanumeric string, not in the sense of being "a container of varied contents some of which is dumb data like 8" -- 8 is not dumb, and assignment is assignment, sharing accessibility to objects in memory). What I'm working against is the C picture of 8 as "dumb data" (objects not yet invented, though struct is the prototype for a class definition, evolves to C++, with C# more deriving from Java in a lot of ways -- which in turn learns from C++ no? -- so I tend to include Java when I say "C family"). When I look at x = 8 and go "x is a variable and 8 is data" then I'm working against Python's "everything is an object" paradigm. By momentarily seeing 8 as a kind of name, you get the sense that x = 8 and x = Rod(color="orange") aren't two different kinds of assignment, are both passing (cloning) a sticky note that points to an object. Kirby On Thu, May 8, 2008 at 10:08 PM, John Posner wrote: > >> Partly why it's misleading to speak of names as variables is >> that shoptalk tends to prevent us from seeing 8 as the *name* >> of an immutable object, one for which the name is hardwired >> (but feel free to bind, or assign, other not-spoken-for names >> to the same object). > > I don't see the advantage of thinking of "8" as a name. It's just some > syntax that creates an unnamed object. In that sense, all of these are > similar: > > 8 > 8 + 3 > Rod(length = 9, color = 'blue') > > In all these cases, the resulting object gets a name only if it's the RHS of > an assignment. If not, the object disappears (from the user's viewpoint, > anyway) as soon as the containing statement/expression is executed. > > Also, what do you say to the student who points out that "8 is a name" > violates the rule that Python names must begin with a letter or underscore? > > -John > > > > > _______________________________________________ > Edu-sig mailing list > Edu-sig at python.org > http://mail.python.org/mailman/listinfo/edu-sig > From metolone+gmane at gmail.com Fri May 9 18:21:19 2008 From: metolone+gmane at gmail.com (Mark Tolonen) Date: Fri, 9 May 2008 09:21:19 -0700 Subject: [Edu-sig] Sticky-note Analogy References: <008201c8b192$a9d1ce20$65bda8c0@jposner> Message-ID: "kirby urner" wrote in message news:f604188c0805090730v2163d12dw9970fcf4b96220ac at mail.gmail.com... > I've suggesting seeing 8 as a name only briefly, temporary gestalt > switch, then go back to seeing it as a literal, kind of like a name > in that you can do dot notation on it, i.e. there's an underlying > object that's responsive to these triggers (like 8 .__add__(5) > instead of just 8 + 5). But is the underlying object "anonymous"? > > It has a memory location: > >>>> id(8) > 12015636 > >>>> id('8') > 13259744 > > And I'm able to refer to it. I didn't make up a name for it, like > eight, because I didn't need to, it's already permanently > accessible through 8. > Numbers are just language syntax to create objects. If they aren't assigned a name, they disappear. >>> x=1000 >>> y=x >>> z=x >>> y is z True x is the name of an object. y and z also are names for that object. 1000 is not a name: >>> x=1000 >>> y=1000 >>> z=1000 >>> x is y False >>> x is z False >>> y is z False a new object is created each time. -Mark P.S. Note, at least in CPython, that same example won't work for small numbers because of an implementation detail that caches the common 'small number' objects for performance reasons. >>> x=1 >>> y=1 >>> z=1 >>> x is y True >>> y is z True From kirby.urner at gmail.com Fri May 9 20:06:21 2008 From: kirby.urner at gmail.com (kirby urner) Date: Fri, 9 May 2008 11:06:21 -0700 Subject: [Edu-sig] Sticky-note Analogy In-Reply-To: References: <008201c8b192$a9d1ce20$65bda8c0@jposner> Message-ID: On Fri, May 9, 2008 at 9:21 AM, Mark Tolonen wrote: > > "kirby urner" wrote in message > news:f604188c0805090730v2163d12dw9970fcf4b96220ac at mail.gmail.com... >> >> I've suggesting seeing 8 as a name only briefly, temporary gestalt >> switch, then go back to seeing it as a literal, kind of like a name >> in that you can do dot notation on it, i.e. there's an underlying >> object that's responsive to these triggers (like 8 .__add__(5) >> instead of just 8 + 5). But is the underlying object "anonymous"? >> >> It has a memory location: >> >>>>> id(8) >> >> 12015636 >> >>>>> id('8') >> >> 13259744 >> >> And I'm able to refer to it. I didn't make up a name for it, like >> eight, because I didn't need to, it's already permanently >> accessible through 8. >> > > Numbers are just language syntax to create objects. If they aren't assigned > a name, they disappear. > I think that's way ahead of where most C programmers would start, so yes, agreed. On the other hand, 8 doesn't disappear but remains equally available in all scopes. However, it's a read-only object, so there's no sense of other handles, like eight (after eight = 8) communicating state changes to other objects. There's no 8 .value = 9 or such nonsense. But I like your picture of 8 "giving birth" (triggering a constructor somewhere, almost like 8 = 8 ( ) except you don't need that step ). Intuitively, we know 88592389182 can't "already be there" before we start applying dot notation to the thing. It must be created "out of the blue" -- and so the idea of a birth event (ala __new__ and __init__). And let's not forget strings like 'abc', other literals. This thing about 'ABC'.lower() == 'abc' returning True is that object 'ABC', in the time it exists, has all these inherited magical powers in virtue of being type string -- lots of talent, lots of vim. In the C world, there's this strong prejudice against what's called "data" (like a string) having executive powers. "Mere data" shouldn't be able to "run code" as it were. But in Python, where "everything is an object" we think of 8 + 5 as triggering 8's "add method" i.e. running some code, maybe a lot of it (multiplication gets complicated, may involve trig in some algorithms). Is >>> 8 "giving birth" or mentioning something "already born"? We might take an empirical approach to that question: >>> id(98204958298347923) 12756632 >>> id(98204958298347923) 12756728 >>> id(98204958298347923) 12755816 >>> id(8) 12015636 >>> id(8) 12015636 >>> id(8) 12015636 >>> id(8) 12015636 >>> id(20) 12015492 >>> id(20) 12015492 >>> id(200) 12017300 >>> id(200) 12017300 >>> id(200) 12017300 >>> id(2000) 13756860 >>> id(2000) 13756788 >>> id(2000) 13541792 I'd say 8 is "already born" whereas 2000 is "created on the fly". But this is an implementation detail so we can agree these both amount to the same thing at the end of the day. Literals behave as literals, regardless of whether Python preallocates for low numbers. Regarding persistence: You could easily write a whole program that executes within an "anonymous (unnamed) class" in the sense >>> Rod( ) stays anonymous and goes out of scope if no other name tags it.** >>> class Main: def __init__(self): runtime() >>> def runtime(): print "A huge Python script, like Zope, runs for days" >>> Main() A huge Python script, like Zope, runs for days <__main__.Main instance at 0x00E68558> So Main (a name within __main__) is created as an "anonymous object" in the sense that we don't tag it with anything else top level -- and that's OK, because we can give birth to a Main object without bothering with assignment, and get all the work done we need. I mention this because I think students need to get that naming is all about preservation or persistence through time ("saving"), and persistence is defined against the backdrop of "scopes" -- names going in and out of 'em (via whatever syntax -- you have some control, might use attribute syntax yet trigger a method, per the property feature). We've already established that what goes on in a function call is essentially assignment, i.e. passed names do the same kind of thing as when we just go x = y, however we choose to characterize it (by value? by reference? trying to shoehorn into K&R categories seems a little misguided from the beginning as I think we should be coaching C programmers into *escaping* from K&R's conceptual model -- which is about a different language, not so apropos). A bias in Python is against cluttering your namespace, which is where those collection objects come in, with APIs for communicating with pretty much any number of objects through a common switchboard. But then, that's a bias in almost any good programming language, so Python is inheriting from (benefiting from) earlier work (no question C an inspiration, though Guido circles ABC mostly, also in the sense of not wanting to repeat some mistakes, of providing new freedoms). Literals are not bound by scope, in the sense of their being equally available in all contexts. They're "already saved" but go ahead and tag 'em with variables if you wish. Names are definitely scope-bound mortals in contrast, globals coming closest (not saying globals are better -- they often get in the way, add unnecessary overhead). Literals are *like* names in being tokens supporting dot notation, other syntax associated with named objects (depends on the type, exactly what syntax you might get away with). Mental exercise: Imagine using Unicode greek letter pi (lowercase) as a literal in Python, such that pi(1000) would spit back pi to 1000 significant digits and so on, but also pi + 1 would give 4.14159 and so on i.e. it behaves like a Decimal type (which let's say it is, under the hood). This would be a change to the language specification, to offer such a pi (greek letter) as a literal across all scopes. On the other hand, there's already nothing to stop a coder from offering precisely this feature in a 3rd party module, as Unicode greek letter pi as already available for naming a class. from trig import pi # <-- greek letter would be all you'd need for this new "literal" (actually name) to be available. Which is why there's no need to enhance the Python language specification with such a beast -- it's already allowed, may be out there in some Python 3.x code already (not quite the same as math.pi, but usable in all the same ways, as input to trig functions etc.). Kirby ** note that at birth, an object can bootstrap itself into becoming a global, even if the programmer doesn't do explicit assignment at birth: >>> class Foo: def __init__(self): global r r = self def __repr__(self): return 'Some object at %s' % str(id(self)) >>> Foo() Some object at 15106896 >>> r Some object at 15106896 >>>> x=1000 >>>> y=x >>>> z=x >>>> y is z > > True > > x is the name of an object. y and z also are names for that object. > 1000 is not a name: > >>>> x=1000 >>>> y=1000 >>>> z=1000 >>>> x is y > > False >>>> >>>> x is z > > False >>>> >>>> y is z > > False > > a new object is created each time. > > -Mark > > P.S. Note, at least in CPython, that same example won't work for small > numbers because of an implementation detail that caches the common 'small > number' objects for performance reasons. > >>>> x=1 >>>> y=1 >>>> z=1 >>>> x is y > > True >>>> >>>> y is z > > True > > > _______________________________________________ > Edu-sig mailing list > Edu-sig at python.org > http://mail.python.org/mailman/listinfo/edu-sig > From mtobis at gmail.com Fri May 9 20:51:07 2008 From: mtobis at gmail.com (Michael Tobis) Date: Fri, 9 May 2008 13:51:07 -0500 Subject: [Edu-sig] How does Python do Pointers? In-Reply-To: <5.2.1.1.0.20080506124711.04776cd8@mail.ece.arizona.edu> References: <1210089307.6138.33.camel@zelle> <5.2.1.1.0.20080505131126.03bc9fe8@mail.ece.arizona.edu> <82298BEE-0EC6-48BA-838F-E8DED48113A0@gmail.com> <5.2.1.1.0.20080506035225.016dc9a0@mail.ece.arizona.edu> <5.2.1.1.0.20080506094259.016b0708@mail.ece.arizona.edu> <5.2.1.1.0.20080506124711.04776cd8@mail.ece.arizona.edu> Message-ID: Many people find this useful. I sure did when I needed it. http://effbot.org/zone/python-objects.htm mt From kirby.urner at gmail.com Sat May 10 17:05:44 2008 From: kirby.urner at gmail.com (kirby urner) Date: Sat, 10 May 2008 08:05:44 -0700 Subject: [Edu-sig] Simple game framework Message-ID: """ Tiny game framework, using a maze of rooms randomly populated with mentors. There might be treasure in one of them. K. Urner 4D Solutions May 10, 2008 Basic idea.... class Mentor: ''' Gatekeeper, gets in the way with a dumb question ''' pass class Hero: ''' a star is born ''' def __init__(self, name): self.name = name class Maze: pass class Room: pass class Game: def __init__(self): ''' get a maze of interconnected rooms, maybe with treasure, welcome hero to the game ''' def run(self): ''' loop through turns until treasure found or hero runs out of time ''' def turn(self): ''' some turn mechanism, advancing us from start to finish ''' To start: >>> from sgf import Game >>> thegame = Game() >>> thegame.run() """ from random import choice class Mentor: ''' Gatekeeper, gets in the way with a dumb question. Of course you might want a lot more variety, consider subclassing options ''' def __init__(self, myquestion, myanswer, reward = 1, punishment = -1): self.q = myquestion self.a = myanswer self.r = reward self.p = punishment def check(self, usersays): if usersays == self.a: print "Rewarding with " + str(self.r) return self.r else: print "Punishing with " + str(self.p) return self.p class Hero: ''' a star is born ''' def __init__(self, name): # we're keeping it simple, but remember this # is just a framework to give you ideas self.name = name self.vitality = 10 self.lifeclock = 15 def stats(self): print "%s's stats: Vitality: %s Lifeclock: %s" % (self.name, self.vitality, self.lifeclock) class Room: def __init__(self, name): self.name = name self.has_treasure = False self.has_mentor = False def __repr__(self): return self.name # ============= GLOBALS ======================== """ You can build a maze using generic names like Lobby, but then give a different flavor to the game when defining what the Room tells the user -- what we accomplish in the specialrooms dictionary """ specialrooms = {"Lobby":Room("Gang Plank"), "Kitchen":Room("Galley"), "Den":Room("Captain's Quarters"), "Bathroom":Room("Head"), "Safe":Room("Treasure Chest")} # Getting more creative with the questions would # make for a funner game thementors = [Mentor("2+2? ","4", reward = 2, punishment = 7), Mentor("Capital of Oregon ","Salem", punishment = -5), Mentor("5*5? ","25"), Mentor("Python fits your brain? ","Yes sir!", punishment = 5), # trick question Mentor("Are we having fun yet? ","Yes", reward = 10), # wow, lots of vitality Mentor("Is fast food good for you?", "Not usually", # who would guess this? reward = 3, punishment = 5)] # =========== END GLOBALS ======================== class Maze: """ Interconnects rooms and keeps track of which is occupied. No access to hero from this class. depends on specialrooms global (above) defines a layout (hardwired here, but randomizable with some work) Note there may be no treasure anywhere in the Maze, so you can't win no matter what, just wait out your life clock and die a loser, oh well. Very pre-destined in flavor, feel free to change. """ def __init__(self): # got treasure? specialrooms['Safe'].has_treasure = choice([True, False]) # map names like Kitchen give us a generic view, with # specialrooms used to customize (provide a theme, skin) self.layout = {"Lobby":["Kitchen","Bathroom"], "Kitchen":["Lobby","Den"], "Den":["Kitchen","Bathroom"], "Bathroom":["Safe","Den"], "Safe":["Bathroom","Bathroom"]} # populate with random mentors for i in range(len(self.layout)//2): somementor = choice(thementors) someroom = choice(specialrooms.keys()) specialrooms[someroom].has_mentor = True specialrooms[someroom].mentor = somementor self.mapkey = "Lobby" self.thisroom = specialrooms[self.mapkey] print self.thisroom def getroom(self): ''' take us to a next room -- what? Doesn't the user get to choose? This would be a good place to get some raw_input don't you think? ''' self.mapkey = choice(self.layout[self.mapkey]) self.thisroom = specialrooms[self.mapkey] class Game: def __init__(self): ''' get a maze of interconnected rooms, maybe with treasure, welcome hero to the game ''' self.themaze = Maze() print "Welcome to the game." def run(self): ''' loop through turns until treasure found or hero runs out of time ''' myname = raw_input("What is the name of your Hero? ") self.hero = Hero(myname) while self._turn(): self.themaze.getroom() def _turn(self): ''' some turn mechanism, advancing us from start to finish ''' print print "Location: " + str(self.themaze.thisroom) print self.hero.stats() if self.themaze.thisroom.has_mentor: print "Oh oh, a mentor!" thementor = self.themaze.thisroom.mentor ans = raw_input(thementor.q) self.hero.vitality += thementor.check(ans) else: print "No mentor here, whew." self.hero.lifeclock -= 1 self.hero.stats() if self.hero.vitality <= 0: print "No more vitality.\nG A M E O V E R" return False if self.hero.lifeclock <= 0: print "Time limit reached.\nG A M E O V E R" return False if self.themaze.thisroom.has_treasure: print "Treasure found!\nY O U W I N ! !" return False else: print "Onward!" return True if __name__ == '__main__': thegame = Game() thegame.run() From krstic at solarsail.hcs.harvard.edu Sat May 10 17:44:56 2008 From: krstic at solarsail.hcs.harvard.edu (=?UTF-8?Q?Ivan_Krsti=C4=87?=) Date: Sat, 10 May 2008 17:44:56 +0200 Subject: [Edu-sig] Sticky-note Analogy In-Reply-To: References: <008201c8b192$a9d1ce20$65bda8c0@jposner> Message-ID: <35B96718-4FE5-4E2E-B8D4-756712DE5775@solarsail.hcs.harvard.edu> On May 9, 2008, at 8:06 PM, kirby urner wrote: > I'd say 8 is "already born" whereas 2000 is "created on the fly". In default builds, integers in the range [-5, 256] are cached by the interpreter. -- Ivan Krsti? | http://radian.org From kirby.urner at gmail.com Sun May 11 00:48:59 2008 From: kirby.urner at gmail.com (kirby urner) Date: Sat, 10 May 2008 15:48:59 -0700 Subject: [Edu-sig] sociality.tv update... Message-ID: Note: Ian Benson has been busy updating his website, including with links to some of the Pycon material: http://www.youtube.com/socialitydottv Caleb Gattegno was a visionary who saw the foundations of mathematics more as Wittgenstein did **, as a complex social activity: http://mentor.sociality.tv/groups/evidence/wiki/f4846/The_crisis_in_maths_education.html Anyway, just thought I'd mention, also posted my class notes for today: http://controlroom.blogspot.com/2008/05/sa-classnotes-2008510.html Kirby ** http://www.amazon.com/Remarks-Foundation-Mathematics-Ludwig-Wittgenstein/dp/0631125051/ From chris at cthoday.uklinux.net Tue May 13 23:10:26 2008 From: chris at cthoday.uklinux.net (Christopher Thoday) Date: Tue, 13 May 2008 22:10:26 +0100 Subject: [Edu-sig] Sticky-note Analogy In-Reply-To: <35B96718-4FE5-4E2E-B8D4-756712DE5775@solarsail.hcs.harvard.edu> References: <008201c8b192$a9d1ce20$65bda8c0@jposner> <35B96718-4FE5-4E2E-B8D4-756712DE5775@solarsail.hcs.harvard.edu> Message-ID: <482A03C2.9090009@cthoday.uklinux.net> Would it not be better to describe the differences between C and Python variables directly rather than using an analogy? In C, a variable is the address of a storage location that contains its value. If that value is itself an address then the variable is described as a pointer. In Python, a variable is a reference to an object that has a type as well as a value. The statement: a= b = c; results in three separate values in C but only one in Python. The effect is the same in both languages provided that c refers to a constant. However, if c is a mutable object, such as a list, then changing the value of one variable changes them all. Anyone coming to Python from C may be confused by this as it is not clearly described in any of the books on Python that I have read. When passing an argument to a function, C uses pass-by-value whereas Python uses what is in effect pass-by-reference. In order to obtain pass-by-reference in C the value must be a pointer. Inside the function the pointer must be dereferenced by prefixing it with an asterisk to obtain the value. Eur Ing Christopher Thoday Software Engineer From kirby.urner at gmail.com Wed May 14 02:49:23 2008 From: kirby.urner at gmail.com (kirby urner) Date: Tue, 13 May 2008 17:49:23 -0700 Subject: [Edu-sig] Sticky-note Analogy In-Reply-To: <482A03C2.9090009@cthoday.uklinux.net> References: <008201c8b192$a9d1ce20$65bda8c0@jposner> <35B96718-4FE5-4E2E-B8D4-756712DE5775@solarsail.hcs.harvard.edu> <482A03C2.9090009@cthoday.uklinux.net> Message-ID: On Tue, May 13, 2008 at 2:10 PM, Christopher Thoday wrote: > > Would it not be better to describe the differences between C and Python > variables directly rather than using an analogy? > Sometimes pure analogies are better though because if you talk too literally in terms of computer memory then what you're giving are implementation details, not necessarily useful heuristics. It so happens that C is very much about computer memory (even conceptually), which tends to erode this distinction. That's why it's considered a low level language, Python a high one -- not a moral distinction about better vs. worse, but a technical one about how close to the metal (conceptually). > In C, a variable is the address of a storage location that contains its > value. If that value is itself an address then the variable is described as > a pointer. > > In Python, a variable is a reference to an object that has a type as well > as a value. In C, the conceptual model includes this "wall of memory bricks" (each brick with an address) that contain data but no awareness of type. Raw content is all crammed into these bricks as tightly as feasible (holes unavoidable sometimes). You can decode the same data as a different type simply by reading it with a different type of pointer. When you advance a pointer to a struct, C skips by the right number of bytes thanks to the type awareness originally provided by struct declarations in source code. > > The statement: > > a= b = c; > > results in three separate values in C but only one in Python. The effect > is the same in both languages provided that c refers to a constant. However, > if c is a mutable object, such as a list, then changing the value of one > variable changes them all. Anyone coming to Python from C may be confused by > this as it is not clearly described in any of the books on Python that I > have read. Python names have a many-to-one relationship to objects. You can go x = y = z = 8; del y; and still have x and z in the namespace, both referencing the 8 object. The fact of 8 being immutable shouldn't be allowed to confuse the picture of a many-to-one relationship. Going y = 10 is merely rebinding the name y to a different object, leaving the others alone. C has this same many-to-one capability with respect to its pointers, which may be passed by assignment. http://cslibrary.stanford.edu/106/ > When passing an argument to a function, C uses pass-by-value whereas Python > uses what is in effect pass-by-reference. In order to obtain > pass-by-reference in C the value must be a pointer. Inside the function the > pointer must be dereferenced by prefixing it with an asterisk to obtain the > value. > > Eur Ing Christopher Thoday > Software Engineer I'd say that in C, type awareness stays with the variables, as the data bricks know nothing of type, yet the pointers know what they point to, how many bytes to advance, or to read when dereferenced. Struct variables also support -> notation, prototypical of dot notation (historically, structs and struct notation were the basis of the first object oriented implementation of C, i.e. C++). You could tell C programmers "everything is a struct in Python, except structs may include functions, access their own data etc." Then say "all variables are pointers to structs". But you have to be careful to explain this is just an analogy, not a literal fact about implementation (obviously). In Python, type awareness resides with the objects, with namespaces being dictionaries of name:object pairs (many-to one). There's no concept of "dumb data" (even 8 is an object) or addressing bricks per se, although we can get integer ids for our objects as in id(y). You can't do much with that id though, except figure out if another name has the same one (the purpose of "is"). Names are little more than Unicode string literals with top-level significance, each paired with an object in a dictionary (the namespace). So in C, intelligence about type remains with the variables (we might say), whereas in Python it remains with the objects, which are quite introspective. Kirby From kirby.urner at gmail.com Wed May 14 03:01:10 2008 From: kirby.urner at gmail.com (kirby urner) Date: Tue, 13 May 2008 18:01:10 -0700 Subject: [Edu-sig] Sticky-note Analogy In-Reply-To: References: <008201c8b192$a9d1ce20$65bda8c0@jposner> <35B96718-4FE5-4E2E-B8D4-756712DE5775@solarsail.hcs.harvard.edu> <482A03C2.9090009@cthoday.uklinux.net> Message-ID: On Tue, May 13, 2008 at 5:49 PM, kirby urner wrote: > Names are little more than Unicode string literals with top-level > significance, each paired with an object in a dictionary (the > namespace). > Postscript to the above remark: I finally got around to using some Chinese characters as actual Python names, vs. simply as string literals, as in from testuni import [chinese ideogram] # import a class Here's a screen shot: http://mybizmo.blogspot.com/2008/05/chinese-names-in-python.html > So in C, intelligence about type remains with the variables > (we might say), whereas in Python it remains with the objects, > which are quite introspective. > > Kirby > From john.zelle at wartburg.edu Wed May 14 23:30:12 2008 From: john.zelle at wartburg.edu (John Zelle) Date: Wed, 14 May 2008 16:30:12 -0500 Subject: [Edu-sig] Sticky-note Analogy In-Reply-To: <482A03C2.9090009@cthoday.uklinux.net> References: <008201c8b192$a9d1ce20$65bda8c0@jposner> <35B96718-4FE5-4E2E-B8D4-756712DE5775@solarsail.hcs.harvard.edu> <482A03C2.9090009@cthoday.uklinux.net> Message-ID: <1210800612.6060.15.camel@zelle> At some point, I have to just let this go, as I think we all on this list have a pretty good understanding of the differences between C and Python in terms of assignment and parameter passing. But let's _not_ use the term "pass by reference" when talking about Python. You CANNOT CHANGE THE CONTENTS OF THE VARIABLE THAT IS SUPPLIED AS AN ACTUAL PARAMETER. It will still refer to the same object (contain the same reference) regardless of what is done to the formal parameter. Hence, the variable IS NOT passed by reference. The value of the variable (which happens to be a reference) is copied. Pass by value is the accepted label for this mechanism. Pass by reference means something else (as I've pointed out in previous posts). Christopher's point on teaching the differences directly is, I think, a good one. But we don't need to worry about that for beginners. --John On Tue, 2008-05-13 at 22:10 +0100, Christopher Thoday wrote: > Would it not be better to describe the differences between C and Python > variables directly rather than using an analogy? > > In C, a variable is the address of a storage location that contains its > value. If that value is itself an address then the variable is described > as a pointer. > > In Python, a variable is a reference to an object that has a type as > well as a value. > > The statement: > > a= b = c; > > results in three separate values in C but only one in Python. The > effect is the same in both languages provided that c refers to a > constant. However, if c is a mutable object, such as a list, then > changing the value of one variable changes them all. Anyone coming to > Python from C may be confused by this as it is not clearly described in > any of the books on Python that I have read. > > When passing an argument to a function, C uses pass-by-value whereas > Python uses what is in effect pass-by-reference. In order to obtain > pass-by-reference in C the value must be a pointer. Inside the function > the pointer must be dereferenced by prefixing it with an asterisk to > obtain the value. > > Eur Ing Christopher Thoday > Software Engineer > > _______________________________________________ > Edu-sig mailing list > Edu-sig at python.org > http://mail.python.org/mailman/listinfo/edu-sig > -- John M. Zelle, Ph.D. Wartburg College Professor of Computer Science Waverly, IA john.zelle at wartburg.edu (319) 352-8360 From kirby.urner at gmail.com Thu May 15 03:42:34 2008 From: kirby.urner at gmail.com (kirby urner) Date: Wed, 14 May 2008 18:42:34 -0700 Subject: [Edu-sig] Sticky-note Analogy In-Reply-To: <1210800612.6060.15.camel@zelle> References: <008201c8b192$a9d1ce20$65bda8c0@jposner> <35B96718-4FE5-4E2E-B8D4-756712DE5775@solarsail.hcs.harvard.edu> <482A03C2.9090009@cthoday.uklinux.net> <1210800612.6060.15.camel@zelle> Message-ID: On Wed, May 14, 2008 at 2:30 PM, John Zelle wrote: > At some point, I have to just let this go, as I think we all on this > list have a pretty good understanding of the differences between C and > Python in terms of assignment and parameter passing. But let's _not_ use > the term "pass by reference" when talking about Python. You CANNOT > CHANGE THE CONTENTS OF THE VARIABLE THAT IS SUPPLIED AS AN ACTUAL > PARAMETER. It will still refer to the same object (contain the same > reference) regardless of what is done to the formal parameter. Hence, > the variable IS NOT passed by reference. The value of the variable > (which happens to be a reference) is copied. Pass by value is the > accepted label for this mechanism. Pass by reference means something > else (as I've pointed out in previous posts). > This seems an especially clear statement. Comparing two programs, one C and one Python: C: #include void f (char* r){ *r = 'b'; } int main() { char p = 'a'; char* s = &p; printf("p = %c\n", p); f(s); printf("p = %c\n", p); } kirby at dell:~$ cc testing.c kirby at dell:~$ ./a.out p = a p = b Python: IDLE 1.2.2 >>> def f(r): r = 'b' >>> def main(): p = 'a' print p f (p) print p >>> main() a a We say copy-by-value because the local variable has its own identity and rebinding it to another object within f isn't going to affect the corresponding variable in the caller (as John was just mentioning). In the C example, *r is essentially identical to *p, hence pass-by-reference. The fact that the local and calling variables might share references to a mutable object is obscuring the fact that these aren't two names for the same door, as in C, but two separate doors to the same object. Kirby > Christopher's point on teaching the differences directly is, I think, a > good one. But we don't need to worry about that for beginners. > > --John > > > > On Tue, 2008-05-13 at 22:10 +0100, Christopher Thoday wrote: >> Would it not be better to describe the differences between C and Python >> variables directly rather than using an analogy? >> >> In C, a variable is the address of a storage location that contains its >> value. If that value is itself an address then the variable is described >> as a pointer. >> >> In Python, a variable is a reference to an object that has a type as >> well as a value. >> >> The statement: >> >> a= b = c; >> >> results in three separate values in C but only one in Python. The >> effect is the same in both languages provided that c refers to a >> constant. However, if c is a mutable object, such as a list, then >> changing the value of one variable changes them all. Anyone coming to >> Python from C may be confused by this as it is not clearly described in >> any of the books on Python that I have read. >> >> When passing an argument to a function, C uses pass-by-value whereas >> Python uses what is in effect pass-by-reference. In order to obtain >> pass-by-reference in C the value must be a pointer. Inside the function >> the pointer must be dereferenced by prefixing it with an asterisk to >> obtain the value. >> >> Eur Ing Christopher Thoday >> Software Engineer >> >> _______________________________________________ >> Edu-sig mailing list >> Edu-sig at python.org >> http://mail.python.org/mailman/listinfo/edu-sig >> > -- > John M. Zelle, Ph.D. Wartburg College > Professor of Computer Science Waverly, IA > john.zelle at wartburg.edu (319) 352-8360 > > _______________________________________________ > Edu-sig mailing list > Edu-sig at python.org > http://mail.python.org/mailman/listinfo/edu-sig > From macquigg at ece.arizona.edu Thu May 15 21:41:51 2008 From: macquigg at ece.arizona.edu (David MacQuigg) Date: Thu, 15 May 2008 12:41:51 -0700 Subject: [Edu-sig] Pass by Reference In-Reply-To: <1210800612.6060.15.camel@zelle> References: <482A03C2.9090009@cthoday.uklinux.net> <008201c8b192$a9d1ce20$65bda8c0@jposner> <35B96718-4FE5-4E2E-B8D4-756712DE5775@solarsail.hcs.harvard.edu> <482A03C2.9090009@cthoday.uklinux.net> Message-ID: <5.2.1.1.0.20080515115035.016e3310@mail.ece.arizona.edu> At 04:30 PM 5/14/2008 -0500, John Zelle wrote: >At some point, I have to just let this go, as I think we all on this >list have a pretty good understanding of the differences between C and >Python in terms of assignment and parameter passing. But let's _not_ use >the term "pass by reference" when talking about Python. You CANNOT >CHANGE THE CONTENTS OF THE VARIABLE THAT IS SUPPLIED AS AN ACTUAL >PARAMETER. It will still refer to the same object (contain the same >reference) regardless of what is done to the formal parameter. Hence, >the variable IS NOT passed by reference. The value of the variable >(which happens to be a reference) is copied. Pass by value is the >accepted label for this mechanism. Pass by reference means something >else (as I've pointed out in previous posts). > >Christopher's point on teaching the differences directly is, I think, a >good one. But we don't need to worry about that for beginners. I agree, the topic should not come up in a class for beginners, but the question I got was from a student in a class on C. In that situation, it does help to explain Python's calling mechanism in terms that these students understand. I've posted my answer at http://ece.arizona.edu/~edatools/ece175/Lecture/QnA.txt I used the phrase "like pass-by-reference" to avoid the controversy as much as I can. As you can see from the references cited in my answer, the terms call-by-value and call-by-reference do not have universally accepted definitions, even among experts. The differences seem to come down to what we mean by the words "value" and "reference". Everyone seems to have unstated assumptions about their meaning, probably depending on what language they are thinking about. Perhaps it will help if we can agree on models for variables in C and Python. Here are my models: In C, the type of an "object" (char, int, float, etc.) is associated with the variable name, not the object. variable:(name, type, pointer) --> object:(value, address) In Python, type is associated with the object, not the variable name. variable:(name, pointer) --> object:(type, value, address) As you can see, I've used the word "value" to mean the actual data associated with the object, and the word "pointer" to mean whatever it is that references the object (a real pointer in C, I assume a C-pointer in Python). I realize my diagrams may bias the discussion, so perhaps I should stop at this point and ask for alternative models or terminology. -- Dave From jjposner at snet.net Fri May 16 13:23:32 2008 From: jjposner at snet.net (John Posner) Date: Fri, 16 May 2008 07:23:32 -0400 Subject: [Edu-sig] Pass by Reference In-Reply-To: References: Message-ID: <000901c8b747$4663b640$65bda8c0@jposner> > ... In that situation, it does help to explain > Python's calling mechanism in terms that these students > understand. I've posted my answer at > http://ece.arizona.edu/~edatools/ece175/Lecture/QnA.txt > One tiny "wordsmithing" suggestion ... Note: A call-by-reference in C is really just a call-by-value with the value being an explicitly computed address &x. In both cases the underlying mechanism is call-by-value. ... change "is really just" to "is accomplished by performing" -John From macquigg at ece.arizona.edu Fri May 16 22:41:03 2008 From: macquigg at ece.arizona.edu (David MacQuigg) Date: Fri, 16 May 2008 13:41:03 -0700 Subject: [Edu-sig] Pass by Reference In-Reply-To: <000901c8b747$4663b640$65bda8c0@jposner> References: Message-ID: <5.2.1.1.0.20080516133019.03c468c8@mail.ece.arizona.edu> At 07:23 AM 5/16/2008 -0400, you wrote: >> ... In that situation, it does help to explain >> Python's calling mechanism in terms that these students >> understand. I've posted my answer at >> http://ece.arizona.edu/~edatools/ece175/Lecture/QnA.txt >> > >One tiny "wordsmithing" suggestion ... > > Note: A call-by-reference in C is really just a call-by-value with the >value > being an explicitly computed address &x. In both cases the underlying > mechanism is call-by-value. > > >... change "is really just" to "is accomplished by performing" Good suggestion. I've made the change. -- Dave From macquigg at ece.arizona.edu Fri May 16 22:48:26 2008 From: macquigg at ece.arizona.edu (David MacQuigg) Date: Fri, 16 May 2008 13:48:26 -0700 Subject: [Edu-sig] Pass by Reference In-Reply-To: <5.2.1.1.0.20080515115035.016e3310@mail.ece.arizona.edu> References: <1210800612.6060.15.camel@zelle> <482A03C2.9090009@cthoday.uklinux.net> <008201c8b192$a9d1ce20$65bda8c0@jposner> <35B96718-4FE5-4E2E-B8D4-756712DE5775@solarsail.hcs.harvard.edu> <482A03C2.9090009@cthoday.uklinux.net> Message-ID: <5.2.1.1.0.20080516112819.03c54a20@mail.ece.arizona.edu> If there are no objections to my models and terminology, the next step is to describe exactly what happens when we pass an argument in C and in Python. C is very helpful, since there is nothing hidden in this primitive language, and we can see exactly what is happening. Also, there is no confusion about the definitions of "call-by-value" and "call-by-reference". See Kernighan & Ritchie, 2nd ed. p.27. Let's call these the "traditional" definitions. In C there are only two ways to pass an argument - copy its value or copy a reference (pointer) to that value. Again, the model and terminology for C in this discussion is: variable:(name, type, pointer) --> object:(value, address) The variable name, type, and pointer are kept by the compiler. The compiled module has just the actual data bits representing the value stored at a particular address. Here is a simple program that calls a function with two parameters, one called by value, the other by reference. f(int a, int *b) { a += 1; // modifies a local variable *b += 10; // modifies the caller's variable } main() { int x = 0; f(x, &x); // pass the value and the pointer printf("x = %d\n", x); } // output is x = 10 In the call to function f, the value of the caller's variable x is copied to the function's parameter a. The function then operates on its own copy of this value, and the original data value is safe from any modification by the function. This is "call-by-value" in C. In that same call, the address of the caller's variable x is copied to the function's parameter b. Operations on b then change the value of x, but not its type or address. This is "call-by-reference" in C. In Python, there is only one way to pass an argument. There may be pointers flying around, but we never see them. We will have to infer what is going on by doing some tests. Again, the model and terminology for our discussion is: variable:(name, pointer) --> object:(type, value, address) Here is a simple program that calls a function with one parameter. >>> def f(b): b[:] = range(9) >>> x = ['abc', 'xyz'] >>> f(x) >>> x [0, 1, 2, 3, 4, 5, 6, 7, 8] In the call to function f, we must infer that a reference to the caller's variable x is copied to the function's variable b. Operations on b then change the value of x, but not its type or address. I know there are later complications ( What if x is immutable? What if b gets re-assigned within the function? ), but right now I would like to focus on exactly what happens in the call to function f. I'll pause once more to see if I've made any mistakes, before the third and final step - deciding what to call this thing that Python does in passing an argument. -- Dave At 12:41 PM 5/15/2008 -0700, David MacQuigg wrote: >At 04:30 PM 5/14/2008 -0500, John Zelle wrote: > >>At some point, I have to just let this go, as I think we all on this >>list have a pretty good understanding of the differences between C and >>Python in terms of assignment and parameter passing. But let's _not_ use >>the term "pass by reference" when talking about Python. You CANNOT >>CHANGE THE CONTENTS OF THE VARIABLE THAT IS SUPPLIED AS AN ACTUAL >>PARAMETER. It will still refer to the same object (contain the same >>reference) regardless of what is done to the formal parameter. Hence, >>the variable IS NOT passed by reference. The value of the variable >>(which happens to be a reference) is copied. Pass by value is the >>accepted label for this mechanism. Pass by reference means something >>else (as I've pointed out in previous posts). >> >>Christopher's point on teaching the differences directly is, I think, a >>good one. But we don't need to worry about that for beginners. > >I agree, the topic should not come up in a class for beginners, but the question I got was from a student in a class on C. In that situation, it does help to explain Python's calling mechanism in terms that these students understand. I've posted my answer at http://ece.arizona.edu/~edatools/ece175/Lecture/QnA.txt > >I used the phrase "like pass-by-reference" to avoid the controversy as much as I can. As you can see from the references cited in my answer, the terms call-by-value and call-by-reference do not have universally accepted definitions, even among experts. > >The differences seem to come down to what we mean by the words "value" and "reference". Everyone seems to have unstated assumptions about their meaning, probably depending on what language they are thinking about. Perhaps it will help if we can agree on models for variables in C and Python. Here are my models: > >In C, the type of an "object" (char, int, float, etc.) is associated with >the variable name, not the object. > > variable:(name, type, pointer) --> object:(value, address) > >In Python, type is associated with the object, not the variable name. > > variable:(name, pointer) --> object:(type, value, address) > >As you can see, I've used the word "value" to mean the actual data associated with the object, and the word "pointer" to mean whatever it is that references the object (a real pointer in C, I assume a C-pointer in Python). > >I realize my diagrams may bias the discussion, so perhaps I should stop at this point and ask for alternative models or terminology. > >-- Dave From kirby.urner at gmail.com Sat May 17 02:54:49 2008 From: kirby.urner at gmail.com (kirby urner) Date: Fri, 16 May 2008 17:54:49 -0700 Subject: [Edu-sig] Pass by Reference In-Reply-To: <5.2.1.1.0.20080516112819.03c54a20@mail.ece.arizona.edu> References: <1210800612.6060.15.camel@zelle> <008201c8b192$a9d1ce20$65bda8c0@jposner> <35B96718-4FE5-4E2E-B8D4-756712DE5775@solarsail.hcs.harvard.edu> <482A03C2.9090009@cthoday.uklinux.net> <5.2.1.1.0.20080515115035.016e3310@mail.ece.arizona.edu> <5.2.1.1.0.20080516112819.03c54a20@mail.ece.arizona.edu> Message-ID: On Fri, May 16, 2008 at 1:48 PM, David MacQuigg wrote: > In Python, there is only one way to pass an argument. There may be pointers flying around, but we never see them. We will have to infer what is going on by doing some tests. Again, the model and terminology for our discussion is: Sounds like you're wanting to dig into the C, Java or C# code to see Python's implementation? PyObject is going to be a big blip on your radar then. I like Guido's quick overview at Stanford by the way, just to give students some context: http://www.stanford.edu/class/cs242/slides/2006/python-vanRossum.ppt (a Powerpoint). While you're working on this, you might want to remind your C students to think of functions as objects as well (everything is an object) and therefore passable as parameters, just like other objects. Not every C programmer will expect this, so a heads up. In the example below, we change the documentation string on one of our functions: >>> def f(x): """docs""" pass >>> def g( thefunc ): thefunc.func_doc = "hey, different!" >>> f.func_doc 'docs' >>> g( f ) >>> f.func_doc 'hey, different!' >>> Same pass-by-value of a reference idea, but to a function type this time. >>> type(f) Of course we can propagate function references using the assignment operator, per usual: >>> r = f >>> r >>> r is f True The verbs "to call" and "to pass" are similar, such that r = f is passing a reference whereas g ( f ) is calling a reference and passing an argument (by value, in the sense that thefunc, a local name, adds to the underlying PyObject's reference count, i.e. it copies f's reference to PyObject, changing PyObject in the process (just a little)). >>> import sys >>> sys.getrefcount( f ) 3 >>> del r >>> sys.getrefcount( f ) 2 >>> h = f >>> sys.getrefcount( f ) 3 Trying to think why the refcount jumps to 5 when I check it inside g: >>> h = f >>> sys.getrefcount( f ) 3 >>> def g(thefunc): thefunc.func_doc = "hey, different!" print sys.getrefcount(thefunc) >>> g(h) 5 >>> sys.getrefcount(h) 3 Clues anyone? I'm not much of an under-the-hood guy. Kirby From goldwamh at slu.edu Sat May 17 03:19:53 2008 From: goldwamh at slu.edu (Michael H. Goldwasser) Date: Fri, 16 May 2008 20:19:53 -0500 Subject: [Edu-sig] Reference Count In-Reply-To: References: <1210800612.6060.15.camel@zelle> <008201c8b192$a9d1ce20$65bda8c0@jposner> <35B96718-4FE5-4E2E-B8D4-756712DE5775@solarsail.hcs.harvard.edu> <482A03C2.9090009@cthoday.uklinux.net> <5.2.1.1.0.20080515115035.016e3310@mail.ece.arizona.edu> <5.2.1.1.0.20080516112819.03c54a20@mail.ece.arizona.edu> Message-ID: <18478.12985.145742.287300@Michael-Goldwassers-Computer.local> On Friday May 16, 2008, kirby urner wrote: > Trying to think why the refcount jumps to 5 when I check it inside g: > > >>> h = f > >>> sys.getrefcount( f ) > 3 > > >>> def g(thefunc): > thefunc.func_doc = "hey, different!" > print sys.getrefcount(thefunc) > > >>> g(h) > 5 > >>> sys.getrefcount(h) > 3 > > Clues anyone? I'm not much of an under-the-hood guy. > > Kirby We've gotten quite off track of the original thread, but to answer your question, one of the extra counts is because of the local variable 'thefunc' within the scope of g. The other is due to the formal parameter from within the scope of getrefcount. That is also why it was originally 3 rather than 2 when you had h and f referencing the object. See help(sys.getrefcount) for documentation. >>> a = [] >>> sys.getrefcount(a) 2 +----------------------------------------------- | Michael Goldwasser | Associate Professor | Dept. Mathematics and Computer Science | Saint Louis University | 220 North Grand Blvd. | St. Louis, MO 63103-2007 From kirby.urner at gmail.com Sat May 17 04:00:32 2008 From: kirby.urner at gmail.com (kirby urner) Date: Fri, 16 May 2008 19:00:32 -0700 Subject: [Edu-sig] Reference Count In-Reply-To: <18478.12985.145742.287300@Michael-Goldwassers-Computer.local> References: <1210800612.6060.15.camel@zelle> <35B96718-4FE5-4E2E-B8D4-756712DE5775@solarsail.hcs.harvard.edu> <482A03C2.9090009@cthoday.uklinux.net> <5.2.1.1.0.20080515115035.016e3310@mail.ece.arizona.edu> <5.2.1.1.0.20080516112819.03c54a20@mail.ece.arizona.edu> <18478.12985.145742.287300@Michael-Goldwassers-Computer.local> Message-ID: On Fri, May 16, 2008 at 6:19 PM, Michael H. Goldwasser wrote: > We've gotten quite off track of the original thread, Just a little, as passing by assignment ( = ) and/or calling a callable, affect an object's reference count, and that adds to the copy by value idea (if nothing were being copied, we wouldn't need to increment any counter -- what's being copied is of course a reference to an object). Thanks for your quick and informative reply. Kirby From jjposner at snet.net Sat May 17 14:19:35 2008 From: jjposner at snet.net (John Posner) Date: Sat, 17 May 2008 08:19:35 -0400 Subject: [Edu-sig] Pass by Reference In-Reply-To: References: Message-ID: <000901c8b818$44d27bf0$65bda8c0@jposner> > Here is a simple program that calls a function with two > parameters, one called by value, the other by reference. > f(int a, int *b) { > a += 1; // modifies a local variable > *b += 10; // modifies the caller's variable } > main() { > int x = 0; > f(x, &x); // pass the value and the pointer > printf("x = %d\n", x); > } > // output is x = 10 Passing "x" twice in the same function call is distracting, IMHO. Try this rewrite. [ Also, more comments, please. I'm a tech writer by trade. :-) ] -John ---------------- f(int a, int *b) { a += 1; /* modifies a local variable */ *b += 12; /* modifies the caller's variable */ } main() { int x = 5; int y = 30; /* pass value of x, reference to y */ f(x, &y); /* show results */ printf("x = %d\n", x); printf("y = %d\n", y); } program output: x = 5 y = 42 ---------------- From macquigg at ece.arizona.edu Mon May 19 19:41:30 2008 From: macquigg at ece.arizona.edu (David MacQuigg) Date: Mon, 19 May 2008 10:41:30 -0700 Subject: [Edu-sig] Pass by Reference In-Reply-To: <5.2.1.1.0.20080516112819.03c54a20@mail.ece.arizona.edu> References: <5.2.1.1.0.20080515115035.016e3310@mail.ece.arizona.edu> <1210800612.6060.15.camel@zelle> <482A03C2.9090009@cthoday.uklinux.net> <008201c8b192$a9d1ce20$65bda8c0@jposner> <35B96718-4FE5-4E2E-B8D4-756712DE5775@solarsail.hcs.harvard.edu> <482A03C2.9090009@cthoday.uklinux.net> Message-ID: <5.2.1.1.0.20080519025135.03c54a20@mail.ece.arizona.edu> Summarizing our earlier discussion, we now have some simple terminology and a model for what happens when a parameter is passed to a function in Python. A variable in the calling program has a name and a pointer to an object, which has a type, value, and address in memory. variable:(name, pointer) --> object:(type, value, address) When this variable is passed to a function, the pointer is copied to a new variable in the function's namespace. The original object stays exactly where it was, and no copy is made. Now we need to decide whether this process is a "call-by-reference", a "call-by-value", or something else. There seem to be two schools of thought. If we look just at the machinery above, we could say "clearly, it's a call-by-reference." Some Python experts say "Not so fast! It's the result that matters to users, not the underlying machinery." {see section 6.5.2 of John Zelle's Python Programming for a good presentation of the "call-by-value" point-of-view, and section 10.3.1 of Michael Goldwasser's Object-Oriented Programming in Python for a good presentation of the "call-by-reference" point-of-view.} In the traditional definitions {Kernighan & Ritchie, 2nd ed. p.27} "call-by-value" means copying the original value from the caller to the function. "Call-by-reference" means copying only a reference (pointer) to the original value. The results, which students will remember, are that call-by-value is safe, and call-by-reference is efficient. In a call-by-value, the original object is safe from any modification by the function. In a call-by-reference, passing a pointer takes minimum time and memory, no matter how big the object is. The problem is that Python doesn't exactly fit our expectations in using either of the traditional definitions. If we look just at the machinery, its a call-by-reference. Then we run into problems if we expect to modify the original object. Unlike C, there is no way to simply stuff a value into a location specified by a pointer. The result is much like call-by-value, at least for immutable objects. If look just at this result, and say "call-by-value", we run into problems with mutable objects, and have to resort to explanations that students find vague and counter-intuitive, like - "the object itself is passed" or, "the value IS the pointer". My preference at this point (perhaps my engineer's bias) is to say Python is "like call-by-reference". That keeps the explanation a lot closer to the underlying machinery (which engineering students will remember). It is safer to err on the side of call-by-reference (no nasty surprises with mutable objects). The apparent deviations from the simple model can be explained with concepts that students need to learn anyway (mutability and re-binding). I said earlier that we shouldn't raise this topic in a class for beginners, but now I think it is quite appropriate for college freshmen. I'm an electrical engineer, not a computer scientist, but I do remember learning about call-by-value/reference decades ago. I think there is value in keeping the definitions simple, even if modern languages don't conform. Let's not muddy the waters with "call by object" or other ill-defined concepts. There really are only two ways to pass an argument to a function - copy the value or copy a reference. -- Dave At 01:48 PM 5/16/2008 -0700, David MacQuigg wrote: >If there are no objections to my models and terminology, the next step is to describe exactly what happens when we pass an argument in C and in Python. > >C is very helpful, since there is nothing hidden in this primitive language, and we can see exactly what is happening. Also, there is no confusion about the definitions of "call-by-value" and "call-by-reference". See Kernighan & Ritchie, 2nd ed. p.27. Let's call these the "traditional" definitions. In C there are only two ways to pass an argument - copy its value or copy a reference (pointer) to that value. > >Again, the model and terminology for C in this discussion is: > > variable:(name, type, pointer) --> object:(value, address) > >The variable name, type, and pointer are kept by the compiler. The compiled module has just the actual data bits representing the value stored at a particular address. > >Here is a simple program that calls a function with two parameters, one called by value, the other by reference. >f(int a, int *b) { > a += 1; // modifies a local variable > *b += 10; // modifies the caller's variable >} >main() { > int x = 0; > f(x, &x); // pass the value and the pointer > printf("x = %d\n", x); >} >// output is x = 10 >In the call to function f, the value of the caller's variable x is copied to the function's parameter a. The function then operates on its own copy of this value, and the original data value is safe from any modification by the function. This is "call-by-value" in C. > >In that same call, the address of the caller's variable x is copied to the function's parameter b. Operations on b then change the value of x, but not its type or address. This is "call-by-reference" in C. > >In Python, there is only one way to pass an argument. There may be pointers flying around, but we never see them. We will have to infer what is going on by doing some tests. Again, the model and terminology for our discussion is: > > variable:(name, pointer) --> object:(type, value, address) > >Here is a simple program that calls a function with one parameter. > > >>> def f(b): b[:] = range(9) > > >>> x = ['abc', 'xyz'] > >>> f(x) > >>> x > [0, 1, 2, 3, 4, 5, 6, 7, 8] > >In the call to function f, we must infer that a reference to the caller's variable x is copied to the function's variable b. Operations on b then change the value of x, but not its type or address. > >I know there are later complications ( What if x is immutable? What if b gets re-assigned within the function? ), but right now I would like to focus on exactly what happens in the call to function f. > >I'll pause once more to see if I've made any mistakes, before the third and final step - deciding what to call this thing that Python does in passing an argument. > >-- Dave > > >At 12:41 PM 5/15/2008 -0700, David MacQuigg wrote: >>At 04:30 PM 5/14/2008 -0500, John Zelle wrote: >> >>>At some point, I have to just let this go, as I think we all on this >>>list have a pretty good understanding of the differences between C and >>>Python in terms of assignment and parameter passing. But let's _not_ use >>>the term "pass by reference" when talking about Python. You CANNOT >>>CHANGE THE CONTENTS OF THE VARIABLE THAT IS SUPPLIED AS AN ACTUAL >>>PARAMETER. It will still refer to the same object (contain the same >>>reference) regardless of what is done to the formal parameter. Hence, >>>the variable IS NOT passed by reference. The value of the variable >>>(which happens to be a reference) is copied. Pass by value is the >>>accepted label for this mechanism. Pass by reference means something >>>else (as I've pointed out in previous posts). >>> >>>Christopher's point on teaching the differences directly is, I think, a >>>good one. But we don't need to worry about that for beginners. >> >>I agree, the topic should not come up in a class for beginners, but the question I got was from a student in a class on C. In that situation, it does help to explain Python's calling mechanism in terms that these students understand. I've posted my answer at http://ece.arizona.edu/~edatools/ece175/Lecture/QnA.txt >> >>I used the phrase "like pass-by-reference" to avoid the controversy as much as I can. As you can see from the references cited in my answer, the terms call-by-value and call-by-reference do not have universally accepted definitions, even among experts. >> >>The differences seem to come down to what we mean by the words "value" and "reference". Everyone seems to have unstated assumptions about their meaning, probably depending on what language they are thinking about. Perhaps it will help if we can agree on models for variables in C and Python. Here are my models: >> >>In C, the type of an "object" (char, int, float, etc.) is associated with >>the variable name, not the object. >> >> variable:(name, type, pointer) --> object:(value, address) >> >>In Python, type is associated with the object, not the variable name. >> >> variable:(name, pointer) --> object:(type, value, address) >> >>As you can see, I've used the word "value" to mean the actual data associated with the object, and the word "pointer" to mean whatever it is that references the object (a real pointer in C, I assume a C-pointer in Python). >> >>I realize my diagrams may bias the discussion, so perhaps I should stop at this point and ask for alternative models or terminology. >> >>-- Dave > > >_______________________________________________ >Edu-sig mailing list >Edu-sig at python.org >http://mail.python.org/mailman/listinfo/edu-sig From john.zelle at wartburg.edu Tue May 20 01:36:27 2008 From: john.zelle at wartburg.edu (John Zelle) Date: Mon, 19 May 2008 18:36:27 -0500 Subject: [Edu-sig] Pass by Reference In-Reply-To: <5.2.1.1.0.20080519025135.03c54a20@mail.ece.arizona.edu> References: <5.2.1.1.0.20080515115035.016e3310@mail.ece.arizona.edu> <1210800612.6060.15.camel@zelle> <482A03C2.9090009@cthoday.uklinux.net> <008201c8b192$a9d1ce20$65bda8c0@jposner> <35B96718-4FE5-4E2E-B8D4-756712DE5775@solarsail.hcs.harvard.edu> <482A03C2.9090009@cthoday.uklinux.net> <5.2.1.1.0.20080519025135.03c54a20@mail.ece.arizona.edu> Message-ID: <1211240187.6330.35.camel@zelle> Hi David, This is not a bad summary of where the discussion is at, but you still are (to my mind at least) being somewhat sloppy with your language. You keep conflating what a reference points to with the "value" of a variable. My recollection of the literature on programming languages is that a variable is a bundle of attributes that includes minimally, a name, a location, the value is what is stored in that location. Optionally, a variable may also have a type attribute associated with it (and possibly other attributes as well). The key is that "variable" is an abstraction of a named location. A primitive variable is a (name,location) pair. In C++/C, a variable's value (i.e. what is stored in its location) can be anything. It can be primitive data (an int) or an arbitrarily complex object. In Java, a variable's value be a primitive type (int, float, etc.), NULL, or a reference to an object. In Python, the value of a variable can _only_ be a reference to an object. When a variable is used, its value is dereferenced to produce that object. Now a formal parameter is also just a variable. It's a variable whose exact name-location binding is determined at the time of call. In call by value, the name is bound to a local location that is initialized with a copy of the value of the actual argument. Assigning to this variable has no effect on the _value_ of the caller's variable. In call by reference, the local name is bound to the caller variable's location. Thus the local name becomes an alias for the callers variable. Assigning to the formal parameter therefore changes the value in the caller's variable. From this point of view, it is clear that Python's mechanism for parameter passing is just call-by-value as it is traditionally defined. No more, no less. You insist on writing/thinking/reasoning as if Python variables "contain" the objects they refer to, but that simply is not the case for the traditional use of the term "variable." Now I suppose you could say that Python calls for a different view of the term. Since variables are automatically dereferenced, maybe the object _should_ be considered the "value" of a Python variable. But that is simply not consistent with the rest of the literature in defining "variable". Literally, your model, with the traditional definition would require that every assignment statement in Python create a new variable. Consider this sequence: a = 3 # creates the variable "a" a = 4 # "a" is now bound to another location a = 5 # "a" is now bound to yet another location Since the address of the value changes with each assignment, the pair (name, location) is changing each time, and hence we have here three different variables with the same name. That's certainly not the way I think about what's happening in Python! So, my question is why don't we just stick with the traditional notion of a variable being a (name, location) pair. Realize that Python dereferences the values for us when we use variables in expressions and stop trying to invent new names for a parameter passing mechanism that is identical in function to traditional call by value. --John On Mon, 2008-05-19 at 10:41 -0700, David MacQuigg wrote: > Summarizing our earlier discussion, we now have some simple terminology and a model for what happens when a parameter is passed to a function in Python. A variable in the calling program has a name and a pointer to an object, which has a type, value, and address in memory. > > variable:(name, pointer) --> object:(type, value, address) > > When this variable is passed to a function, the pointer is copied to a new variable in the function's namespace. The original object stays exactly where it was, and no copy is made. > > Now we need to decide whether this process is a "call-by-reference", a "call-by-value", or something else. There seem to be two schools of thought. If we look just at the machinery above, we could say "clearly, it's a call-by-reference." Some Python experts say "Not so fast! It's the result that matters to users, not the underlying machinery." {see section 6.5.2 of John Zelle's Python Programming for a good presentation of the "call-by-value" point-of-view, and section 10.3.1 of Michael Goldwasser's Object-Oriented Programming in Python for a good presentation of the "call-by-reference" point-of-view.} > > In the traditional definitions {Kernighan & Ritchie, 2nd ed. p.27} "call-by-value" means copying the original value from the caller to the function. "Call-by-reference" means copying only a reference (pointer) to the original value. The results, which students will remember, are that call-by-value is safe, and call-by-reference is efficient. In a call-by-value, the original object is safe from any modification by the function. In a call-by-reference, passing a pointer takes minimum time and memory, no matter how big the object is. > > The problem is that Python doesn't exactly fit our expectations in using either of the traditional definitions. If we look just at the machinery, its a call-by-reference. Then we run into problems if we expect to modify the original object. Unlike C, there is no way to simply stuff a value into a location specified by a pointer. The result is much like call-by-value, at least for immutable objects. > > If look just at this result, and say "call-by-value", we run into problems with mutable objects, and have to resort to explanations that students find vague and counter-intuitive, like - "the object itself is passed" or, "the value IS the pointer". > > My preference at this point (perhaps my engineer's bias) is to say Python is "like call-by-reference". That keeps the explanation a lot closer to the underlying machinery (which engineering students will remember). It is safer to err on the side of call-by-reference (no nasty surprises with mutable objects). The apparent deviations from the simple model can be explained with concepts that students need to learn anyway (mutability and re-binding). > > I said earlier that we shouldn't raise this topic in a class for beginners, but now I think it is quite appropriate for college freshmen. I'm an electrical engineer, not a computer scientist, but I do remember learning about call-by-value/reference decades ago. I think there is value in keeping the definitions simple, even if modern languages don't conform. Let's not muddy the waters with "call by object" or other ill-defined concepts. There really are only two ways to pass an argument to a function - copy the value or copy a reference. > > -- Dave > > > At 01:48 PM 5/16/2008 -0700, David MacQuigg wrote: > > >If there are no objections to my models and terminology, the next step is to describe exactly what happens when we pass an argument in C and in Python. > > > >C is very helpful, since there is nothing hidden in this primitive language, and we can see exactly what is happening. Also, there is no confusion about the definitions of "call-by-value" and "call-by-reference". See Kernighan & Ritchie, 2nd ed. p.27. Let's call these the "traditional" definitions. In C there are only two ways to pass an argument - copy its value or copy a reference (pointer) to that value. > > > >Again, the model and terminology for C in this discussion is: > > > > variable:(name, type, pointer) --> object:(value, address) > > > >The variable name, type, and pointer are kept by the compiler. The compiled module has just the actual data bits representing the value stored at a particular address. > > > >Here is a simple program that calls a function with two parameters, one called by value, the other by reference. > >f(int a, int *b) { > > a += 1; // modifies a local variable > > *b += 10; // modifies the caller's variable > >} > >main() { > > int x = 0; > > f(x, &x); // pass the value and the pointer > > printf("x = %d\n", x); > >} > >// output is x = 10 > >In the call to function f, the value of the caller's variable x is copied to the function's parameter a. The function then operates on its own copy of this value, and the original data value is safe from any modification by the function. This is "call-by-value" in C. > > > >In that same call, the address of the caller's variable x is copied to the function's parameter b. Operations on b then change the value of x, but not its type or address. This is "call-by-reference" in C. > > > >In Python, there is only one way to pass an argument. There may be pointers flying around, but we never see them. We will have to infer what is going on by doing some tests. Again, the model and terminology for our discussion is: > > > > variable:(name, pointer) --> object:(type, value, address) > > > >Here is a simple program that calls a function with one parameter. > > > > >>> def f(b): b[:] = range(9) > > > > >>> x = ['abc', 'xyz'] > > >>> f(x) > > >>> x > > [0, 1, 2, 3, 4, 5, 6, 7, 8] > > > >In the call to function f, we must infer that a reference to the caller's variable x is copied to the function's variable b. Operations on b then change the value of x, but not its type or address. > > > >I know there are later complications ( What if x is immutable? What if b gets re-assigned within the function? ), but right now I would like to focus on exactly what happens in the call to function f. > > > >I'll pause once more to see if I've made any mistakes, before the third and final step - deciding what to call this thing that Python does in passing an argument. > > > >-- Dave > > > > > >At 12:41 PM 5/15/2008 -0700, David MacQuigg wrote: > >>At 04:30 PM 5/14/2008 -0500, John Zelle wrote: > >> > >>>At some point, I have to just let this go, as I think we all on this > >>>list have a pretty good understanding of the differences between C and > >>>Python in terms of assignment and parameter passing. But let's _not_ use > >>>the term "pass by reference" when talking about Python. You CANNOT > >>>CHANGE THE CONTENTS OF THE VARIABLE THAT IS SUPPLIED AS AN ACTUAL > >>>PARAMETER. It will still refer to the same object (contain the same > >>>reference) regardless of what is done to the formal parameter. Hence, > >>>the variable IS NOT passed by reference. The value of the variable > >>>(which happens to be a reference) is copied. Pass by value is the > >>>accepted label for this mechanism. Pass by reference means something > >>>else (as I've pointed out in previous posts). > >>> > >>>Christopher's point on teaching the differences directly is, I think, a > >>>good one. But we don't need to worry about that for beginners. > >> > >>I agree, the topic should not come up in a class for beginners, but the question I got was from a student in a class on C. In that situation, it does help to explain Python's calling mechanism in terms that these students understand. I've posted my answer at http://ece.arizona.edu/~edatools/ece175/Lecture/QnA.txt > >> > >>I used the phrase "like pass-by-reference" to avoid the controversy as much as I can. As you can see from the references cited in my answer, the terms call-by-value and call-by-reference do not have universally accepted definitions, even among experts. > >> > >>The differences seem to come down to what we mean by the words "value" and "reference". Everyone seems to have unstated assumptions about their meaning, probably depending on what language they are thinking about. Perhaps it will help if we can agree on models for variables in C and Python. Here are my models: > >> > >>In C, the type of an "object" (char, int, float, etc.) is associated with > >>the variable name, not the object. > >> > >> variable:(name, type, pointer) --> object:(value, address) > >> > >>In Python, type is associated with the object, not the variable name. > >> > >> variable:(name, pointer) --> object:(type, value, address) > >> > >>As you can see, I've used the word "value" to mean the actual data associated with the object, and the word "pointer" to mean whatever it is that references the object (a real pointer in C, I assume a C-pointer in Python). > >> > >>I realize my diagrams may bias the discussion, so perhaps I should stop at this point and ask for alternative models or terminology. > >> > >>-- Dave > > > > > >_______________________________________________ > >Edu-sig mailing list > >Edu-sig at python.org > >http://mail.python.org/mailman/listinfo/edu-sig > > > _______________________________________________ > Edu-sig mailing list > Edu-sig at python.org > http://mail.python.org/mailman/listinfo/edu-sig > -- John M. Zelle, Ph.D. Wartburg College Professor of Computer Science Waverly, IA john.zelle at wartburg.edu (319) 352-8360 From kirby.urner at gmail.com Tue May 20 01:49:37 2008 From: kirby.urner at gmail.com (kirby urner) Date: Mon, 19 May 2008 16:49:37 -0700 Subject: [Edu-sig] Pass by Reference In-Reply-To: <5.2.1.1.0.20080519025135.03c54a20@mail.ece.arizona.edu> References: <5.2.1.1.0.20080515115035.016e3310@mail.ece.arizona.edu> <008201c8b192$a9d1ce20$65bda8c0@jposner> <35B96718-4FE5-4E2E-B8D4-756712DE5775@solarsail.hcs.harvard.edu> <482A03C2.9090009@cthoday.uklinux.net> <5.2.1.1.0.20080516112819.03c54a20@mail.ece.arizona.edu> <5.2.1.1.0.20080519025135.03c54a20@mail.ece.arizona.edu> Message-ID: On Mon, May 19, 2008 at 10:41 AM, David MacQuigg wrote: << SNIP >> > I said earlier that we shouldn't raise this topic in a class for beginners, but now I think it is quite appropriate for college freshmen. I'm an electrical engineer, not a computer scientist, but I do remember learning about call-by-value/reference decades ago. I think there is value in keeping the definitions simple, even if modern languages don't conform. Let's not muddy the waters with "call by object" or other ill-defined concepts. There really are only two ways to pass an argument to a function - copy the value or copy a reference. > > -- Dave My view remains that "calling a function" is a subcategory of "assignment" (aka "binding") more generally, as what happens in x = y versus f ( x = y) or f (y) with x local to f, is not different in principle. The question is how one adds to a namespace, never mind the scope changes. Also, let's make sure C students appreciate the flexibility of being able to have differently typed pointers sharing the same reference (address). Python has nothing exactly like it, given how type info rests with the object. In calling by reference, you're free to change type of pointer, as well as scope (you can do this by simple assignment as well). I'm skeptical that K&R concepts should be applied de rigueur, no matter what the intended paradigm, but it's certainly an interesting exercise, and translators differ. Kirby From jjposner at snet.net Tue May 20 16:50:38 2008 From: jjposner at snet.net (John Posner) Date: Tue, 20 May 2008 10:50:38 -0400 Subject: [Edu-sig] Pass by Reference In-Reply-To: References: Message-ID: <006101c8ba88$de306010$65bda8c0@jposner> > ... and stop trying to invent new names for a parameter passing mechanism > that is identical in function to traditional call by value. > Yeah, but ... it will be difficult to stick to a call-by-value characterization when confronted with this example, which is straight from "Call by Reference 101": def AddArtist(mylist): mylist.append('TheOtherTerry') >>> troupe ['Graham', 'John', 'Eric', 'Michael', 'Terry'] >>> AddArtist(troupe) >>> troupe ['Graham', 'John', 'Eric', 'Michael', 'Terry', 'TheOtherTerry'] Most students (especially newbies) won't care about what happens under the hood -- not at first. If it looks like a duck, walks like a duck, and quacks like a duck ... -John From warren.sande at rogers.com Tue May 20 17:59:50 2008 From: warren.sande at rogers.com (Warren Sande) Date: Tue, 20 May 2008 08:59:50 -0700 (PDT) Subject: [Edu-sig] Pass by Reference Message-ID: <868920.55445.qm@web88104.mail.re2.yahoo.com> Agreed. Python "behaves like" call-by-value for immutable types and "behaves like" call-by-reference for mutable types. Newbies care about how a thing behaves, not what's going on behind the scenes. Because understanding the behavior lets them write working programs. This seemingly inconsistent behavior is one thing that makes teaching with Python a bit more difficult. Beginners want the answer to the question: "If I pass something to a function, can the function change it or not?" And the answer is, "It depends." That's not a great answer for a beginner. Warren Sande ----- Original Message ---- From: John Posner To: edu-sig at python.org Sent: Tuesday, May 20, 2008 10:50:38 AM Subject: Re: [Edu-sig] Pass by Reference > ... and stop trying to invent new names for a parameter passing mechanism > that is identical in function to traditional call by value. > Yeah, but ... it will be difficult to stick to a call-by-value characterization when confronted with this example, which is straight from "Call by Reference 101": def AddArtist(mylist): mylist.append('TheOtherTerry') >>> troupe ['Graham', 'John', 'Eric', 'Michael', 'Terry'] >>> AddArtist(troupe) >>> troupe ['Graham', 'John', 'Eric', 'Michael', 'Terry', 'TheOtherTerry'] Most students (especially newbies) won't care about what happens under the hood -- not at first. If it looks like a duck, walks like a duck, and quacks like a duck ... -John _______________________________________________ Edu-sig mailing list Edu-sig at python.org http://mail.python.org/mailman/listinfo/edu-sig -------------- next part -------------- An HTML attachment was scrubbed... URL: From john.zelle at wartburg.edu Tue May 20 18:10:25 2008 From: john.zelle at wartburg.edu (John Zelle) Date: Tue, 20 May 2008 11:10:25 -0500 Subject: [Edu-sig] Pass by Reference In-Reply-To: <006101c8ba88$de306010$65bda8c0@jposner> References: <006101c8ba88$de306010$65bda8c0@jposner> Message-ID: <1211299825.6171.50.camel@zelle> Hi John, I can't agree with this. On Tue, 2008-05-20 at 10:50 -0400, John Posner wrote: > > ... and stop trying to invent new names for a parameter passing mechanism > > that is identical in function to traditional call by value. > > > > Yeah, but ... it will be difficult to stick to a call-by-value > characterization when confronted with this example, which is straight from > "Call by Reference 101": > > def AddArtist(mylist): > mylist.append('TheOtherTerry') > > >>> troupe > ['Graham', 'John', 'Eric', 'Michael', 'Terry'] > > >>> AddArtist(troupe) > > >>> troupe > ['Graham', 'John', 'Eric', 'Michael', 'Terry', 'TheOtherTerry'] Great example, but the result here has NOTHING WHATSOEVER to do with parameter passing by reference. If I do this: mylist = troupe myList.append("TheOtherTerry") I get exactly the same result. That's because the value of a variable in Python IS A REFERENCE. Aliasing is aliasing, and it has nothing to do in this case with how parameters are passed. As I keep explaining, when the term pass-by-reference is applied to parameter passing, it means that the formal parameter becomes a reference to the actual variable used in the argument (more technically, the formal parameter name is bound to the storage location of the argument variable). That means changes to the value of the formal parameter actually change the contents of the calling variable. Python does not do this! You can change the state of the object that's referred to, but you _cannot change the contents of the variable_ (what it refers to). The example you give illustrates what happens with call-by-value in _any language_ that allows the value of a variable to be a reference (pointer). Java has no "reference parameters" or "call by reference" mechanism, but it exhibits exactly the same behavior (when the argument is a reference). Similarly in C, if I pass a pointer and change the state of the object that it points to, then the change will be visible to the caller even though the pointer itself is passed-by-value. The C trick of sending an address of the variable (&foo) is a way of simulating or "effecting" call by reference. Technically, the parameter is still passed by value. The programmer must send the reference and also do the appropriate dereferencing in the function (using *formal_param). Perhaps the confusion comes because these other languages allow some variables to be references and others not. In Python all variable values are references. Furthermore Python has no C-like trick to effect pass-by-reference, because even if you can get the value of a variable's contents (say by doing id(a)) you cannot set up a way for a different variable to change that value (even if b = a, setting b = c cannot change the contents of a). This mechanism (pass-by-value) is distinct from pass-by-reference as found in languages like FORTRAN, Pascal, or (arguably) C++. > Most students (especially newbies) won't care about what happens under the > hood -- not at first. If it looks like a duck, walks like a duck, and quacks > like a duck ... First up, there is no reason to discuss these distinctions in detail with newbies. Tell them how it works. That's all you need to do. Newbies won't give a hoot about call-by-reference or call-by-value, as they have not yet learned those terms. But don't teach them the wrong term! Second, it doesn't quack like a reference parameter because Python doesn't allow changing the value of the callers variable!!! It walks and quacks exactly like a variable whose value is a reference being passed-by-value. So if you insist on giving the newbie a label, give them the right label. The _parameter_ passing_ mechanism is plain old pass-by-value. When dealing with more experienced folks, explain that all Python variables are references. That's what's different from (most) traditional languages. That explains many things about the Python. Then when you tell them parameters are passed by value, they will understand the implications of that. Another reference to the same object allows changes in the object state through one to be visible to the other. But please don't pretend that the parameter passing mechanism is some strange and bizarre hybrid and not like other languages, because that's just not true. --John ps. OK, now I'm letting go of the issue. > > -John > > _______________________________________________ > Edu-sig mailing list > Edu-sig at python.org > http://mail.python.org/mailman/listinfo/edu-sig > -- John M. Zelle, Ph.D. Wartburg College Professor of Computer Science Waverly, IA john.zelle at wartburg.edu (319) 352-8360 From goldwamh at slu.edu Tue May 20 19:25:48 2008 From: goldwamh at slu.edu (Michael H. Goldwasser) Date: Tue, 20 May 2008 12:25:48 -0500 Subject: [Edu-sig] Pass by Reference In-Reply-To: <1211299825.6171.50.camel@zelle> References: <006101c8ba88$de306010$65bda8c0@jposner> <1211299825.6171.50.camel@zelle> Message-ID: <18483.2460.643170.120633@Michael-Goldwassers-Computer.local> As much as I know that I should stop flaming the fires, I'd like to jump in with some of my own thoughts on the recent thread. John Zelle and I have been somewhat cast as on opposite extremems. If you look at the pictures we draw for students to explain parameter passing and function calls, they are inherently the same. Python's model is very self-consistent and quite straightforward to explain to beginners. As I've said in an earlier post, everything comes down to understanding what an assignment statement does. Well before discussing functions, it is important for students to understand the semantics of x = 5 y = x x = 6 print y # still bound to 5 This is the issue that must be explained to students well before they broach the topic of functions. Yet once the assignment semantics is understood, the passing mechanism is a straightforward application of the assignment statement FORMAL = ACTUAL. Its the surrounding discussion that differs. We seem to be completely bogged down in the debate over the "call-by-value" and "call-by-reference" terminology. Part of the problem is that I don't believe there is a consistent, canonical source for definitions. On issue is whether this terminology is meant to describe purely the semantics of a programming language or to describe the internal implementations. This is the very first issue raised in the section on parameter passing in the Noonan/Bynum chapter of The Computer Science and Engineering Handbook (ed. Tucker). You could presumably draw a different conclusion depending on whether the focus is semantics or implementation. I certainly think that for the laymen, the verbs "call" and "pass" are more suggestive of the runtime implementation. Another problem is the hangup on a viewing a variable as a classic named memory slot, which simply is not the case in Python. When passing an argument, the issue in applying the verbs is the IMPLICIT object of that verb, that is WHAT IS BEING PASSED? If we cannot agree on what we're passing then we cannot agree on how it is passed. John has made the case that the "value" of a variable is an implicit REFERENCE, and therefore that a copy of that "value" is being passed. I disagree with forcing this characterization upon students (or programmers). Those references are not a tangible entity of the language, but an internal implementation detail in some sense. I am of the view that the "value" of a variable is the underlying object to which it is bound. Namespaces enforce a mapping from identifiers to objects. When I make a call to paint(foo), I consider the argument to be that object currently referenced by the name foo. So then the question arises how that object is communicated upon the call of a function. In this regard, I think we all agree that the information (i.e., the object) is being passed by reference rather than by value. A few other technical objections: * If we go back to the issue of what is placed on the runtime call stack, consider even a basic call sqrt(42). In a classic call-by-value language, I would reasonably expect for the binary representation of the value 42 to be placed on the call stack as the form of communication. With call-by-reference I would reasonably expect for the bits on the call stack to be an indirect reference to some memory location at which the value 42 is stored. In Python, this number will be passed at runtime as an indirect reference, not as 0000000000101010. The same is true if I make a call to data.append(sqrt(42)); the calling mechansim will not be placing the floating-point value on the call stack but rather a reference to an (unnamed) object that was the result of the nested call. I have a hard time seeing any reason for portraying this as call-by-value. * In many of the languages being discussed, the issue is that a variable is a (name,memory) binding where bits are stored in memory and the name is used syntactially to access those bits (with this mapping typically performed at compile time) This is not even the mechanism in Python. An identifier is a string. There is no specific memory address associated with than name that is used to store a pointer as its value. The identifiers in the namespace are strings that serve as dictionary keys, and those are mapped by the dictionary to those underlying pointers. Arguments portraying the by-value vs. by-reference argument as a simple test of wheter calling bar(x) allows the function to change the "value" of variable x, where value is thought of as this implicit pointer are misguided. John writes: > As I keep explaining, when the term pass-by-reference is applied to > parameter passing, it means that the formal parameter becomes a > reference to the actual variable used in the argument (more technically, > the formal parameter name is bound to the storage location of the > argument variable). That means changes to the value of the formal > parameter actually change the contents of the calling variable. Python > does not do this! You can change the state of the object that's referred > to, but you _cannot change the contents of the variable_ (what it refers > to). Even in the classic call-by-reference of the C++ example void bar(int &formal) { formal++; } A call to bar(x) cannot change the binding for the caller's variable x. It refers to a particular memory slot and the callee can not change that binding. The callee simply has access to alter the bits that are stored in that slot. Paraphrasing John's own words, you can change the state of the data that the name x refers to but you cannot make the name x refer to something else. I would say that Python meets the criteria that "the formal parameter name is bound to the storage location of the argument" if we were to agree to the fact that the argument is the underlying object (not the identifier that I presume John has in mind when he wrote "argument variable"). On that note, I'll join in support of John's conclusion: "OK, now I'm letting go of the issue." With regard, Michael +----------------------------------------------- | Michael Goldwasser | Associate Professor | Dept. Mathematics and Computer Science | Saint Louis University | 220 North Grand Blvd. | St. Louis, MO 63103-2007 From macquigg at ece.arizona.edu Tue May 20 19:29:44 2008 From: macquigg at ece.arizona.edu (David MacQuigg) Date: Tue, 20 May 2008 10:29:44 -0700 Subject: [Edu-sig] Pass by Reference In-Reply-To: <1211240187.6330.35.camel@zelle> References: <5.2.1.1.0.20080519025135.03c54a20@mail.ece.arizona.edu> <5.2.1.1.0.20080515115035.016e3310@mail.ece.arizona.edu> <1210800612.6060.15.camel@zelle> <482A03C2.9090009@cthoday.uklinux.net> <008201c8b192$a9d1ce20$65bda8c0@jposner> <35B96718-4FE5-4E2E-B8D4-756712DE5775@solarsail.hcs.harvard.edu> <482A03C2.9090009@cthoday.uklinux.net> <5.2.1.1.0.20080519025135.03c54a20@mail.ece.arizona.edu> Message-ID: <5.2.1.1.0.20080520100855.03e41b20@mail.ece.arizona.edu> Hi John, I did some more searching on this question, and I see it has been discussed many times before. I read a few of the threads, and they seem to go on forever with no resolution, just a lack of communication. It comes down to the definition of "value". One camp says a value is only the actual data in an object, the other says the value can be the reference. I've been using it to mean only the data. variable:(name, pointer) --> object:(type, value, address) Looks like this controversy is not just in the Python community. I found a good discussion in Bruce Eckel's Thinking in Java, 2nd ed, Appendix A: Passing and Returning Objects. On p. 1018, he has a discussion of pass-by-value with a nice summary of the views of "two distinct camps". He concludes with "I will attempt to sidestep the issue. In the end, it isn't that important. What is important is that you understand that passing a reference allows the caller's object to be changed unexpectedly." I think that is what we need to focus on. What will students remember in later years? Which explanation will be most beneficial in helping them avoid problems? I hope that you will recognize the validity of other views, and not just say they are wrong. I think that is the only way this discussion can move forward. I wrote a detailed response to your last post, but decided to delete most of it. I'll just leave a few parts where I need to correct a serious misunderstanding of what I am saying. At 06:36 PM 5/19/2008 -0500, John Zelle wrote: >You insist on writing/thinking/reasoning as if Python variables >"contain" the objects they refer to, but that simply is not the case for >the traditional use of the term "variable." That is not at all what I meant. In my model the variable has only a name and a pointer. The variable refers to an object, but it does not "contain" the object, in the sense that a variable in C is like a box containing a value. variable:(name, pointer) --> object:(type, value, address) > Literally, your model, >with the traditional definition would require that every assignment >statement in Python create a new variable. Consider this sequence: > >a = 3 # creates the variable "a" >a = 4 # "a" is now bound to another location >a = 5 # "a" is now bound to yet another location > >Since the address of the value changes with each assignment, the pair >(name, location) is changing each time, and hence we have here three >different variables with the same name. That's certainly not the way I >think about what's happening in Python! In my model, the pointer associated with the variable named "a" is moved from one object to the next, leaving the old object for the garbage collector. >So, my question is why don't we just stick with the traditional notion >of a variable being a (name, location) pair. I've been calling it a (name, pointer) meaning the same thing. > Realize that Python >dereferences the values for us when we use variables in expressions and >stop trying to invent new names for a parameter passing mechanism that >is identical in function to traditional call by value. We seem to be coming from different traditions. In my tradition, call-by-value means copying the actual data to the function, and call-by-reference means copying a reference (pointer). These definitions include all possibilities, and lead to simple inferences about safety and efficiency, which is the only benefit I can see for discussing the topic with students who are nowhere near being language theory specialists. The message to my students will be simple - It's like call by reference in C - efficient, but watch out for functions that might modify the objects you send as arguments. The alternative - like call by value but ... seems a lot more difficult to explain. ... but it is efficient, because the "values" being passed are really just pointers. ... but it is not safe, because the function can modify the caller's arguments. When I first learned Python, four years ago, I found the discussion in Martelli's book on call-by-value to be confusing, so much so that it impeded my understanding of the simple mechanism that it really is. This confusion was not resolved until last week when I started researching this question, in response to a student's question in class. I believe that telling students of C that Python is "call by value" will generate the same confusion that I suffered. No amount of explanation, or re-assurance "this is what some experts say" will help. The examples and diagrams in your section 6.5.2 are excellent. Just for fun, I re-wrote that section keeping everything the same, but changing only the few paragraphs where you talk about call-by-value. In my humble opinion, that section is shorter and much more clear from a "call-by-reference" point of view. It avoids having to say that the "values" of variables are actually the pointers, not the data. It avoids introducing more complex definitions (e.g. "call-by-reference" means that assigning a value to a formal parameter changes the value in the calling program. That's a result, not a definition, and the result depends on unrelated details of the language, like re-binding semantics.) It avoids the awkward "Isn't that interesting?" paragraph where you have to explain that in some cases you really can change the caller's object after it has been passed by value. I'm not saying your definitions are wrong, I just don't see the benefits of adopting these more difficult and more specialized definitions. Being consistent with some language theorists is not a benefit if it confuses students. -- Dave >On Mon, 2008-05-19 at 10:41 -0700, David MacQuigg wrote: >> Summarizing our earlier discussion, we now have some simple terminology and a model for what happens when a parameter is passed to a function in Python. A variable in the calling program has a name and a pointer to an object, which has a type, value, and address in memory. >> >> variable:(name, pointer) --> object:(type, value, address) >> >> When this variable is passed to a function, the pointer is copied to a new variable in the function's namespace. The original object stays exactly where it was, and no copy is made. >> >> Now we need to decide whether this process is a "call-by-reference", a "call-by-value", or something else. There seem to be two schools of thought. If we look just at the machinery above, we could say "clearly, it's a call-by-reference." Some Python experts say "Not so fast! It's the result that matters to users, not the underlying machinery." {see section 6.5.2 of John Zelle's Python Programming for a good presentation of the "call-by-value" point-of-view, and section 10.3.1 of Michael Goldwasser's Object-Oriented Programming in Python for a good presentation of the "call-by-reference" point-of-view.} >> >> In the traditional definitions {Kernighan & Ritchie, 2nd ed. p.27} "call-by-value" means copying the original value from the caller to the function. "Call-by-reference" means copying only a reference (pointer) to the original value. The results, which students will remember, are that call-by-value is safe, and call-by-reference is efficient. In a call-by-value, the original object is safe from any modification by the function. In a call-by-reference, passing a pointer takes minimum time and memory, no matter how big the object is. >> >> The problem is that Python doesn't exactly fit our expectations in using either of the traditional definitions. If we look just at the machinery, its a call-by-reference. Then we run into problems if we expect to modify the original object. Unlike C, there is no way to simply stuff a value into a location specified by a pointer. The result is much like call-by-value, at least for immutable objects. >> >> If look just at this result, and say "call-by-value", we run into problems with mutable objects, and have to resort to explanations that students find vague and counter-intuitive, like - "the object itself is passed" or, "the value IS the pointer". >> >> My preference at this point (perhaps my engineer's bias) is to say Python is "like call-by-reference". That keeps the explanation a lot closer to the underlying machinery (which engineering students will remember). It is safer to err on the side of call-by-reference (no nasty surprises with mutable objects). The apparent deviations from the simple model can be explained with concepts that students need to learn anyway (mutability and re-binding). >> >> I said earlier that we shouldn't raise this topic in a class for beginners, but now I think it is quite appropriate for college freshmen. I'm an electrical engineer, not a computer scientist, but I do remember learning about call-by-value/reference decades ago. I think there is value in keeping the definitions simple, even if modern languages don't conform. Let's not muddy the waters with "call by object" or other ill-defined concepts. There really are only two ways to pass an argument to a function - copy the value or copy a reference. >> >> -- Dave >> >> >> At 01:48 PM 5/16/2008 -0700, David MacQuigg wrote: >> >> >If there are no objections to my models and terminology, the next step is to describe exactly what happens when we pass an argument in C and in Python. >> > >> >C is very helpful, since there is nothing hidden in this primitive language, and we can see exactly what is happening. Also, there is no confusion about the definitions of "call-by-value" and "call-by-reference". See Kernighan & Ritchie, 2nd ed. p.27. Let's call these the "traditional" definitions. In C there are only two ways to pass an argument - copy its value or copy a reference (pointer) to that value. >> > >> >Again, the model and terminology for C in this discussion is: >> > >> > variable:(name, type, pointer) --> object:(value, address) >> > >> >The variable name, type, and pointer are kept by the compiler. The compiled module has just the actual data bits representing the value stored at a particular address. >> > >> >Here is a simple program that calls a function with two parameters, one called by value, the other by reference. >> >f(int a, int *b) { >> > a += 1; // modifies a local variable >> > *b += 10; // modifies the caller's variable >> >} >> >main() { >> > int x = 0; >> > f(x, &x); // pass the value and the pointer >> > printf("x = %d\n", x); >> >} >> >// output is x = 10 >> >In the call to function f, the value of the caller's variable x is copied to the function's parameter a. The function then operates on its own copy of this value, and the original data value is safe from any modification by the function. This is "call-by-value" in C. >> > >> >In that same call, the address of the caller's variable x is copied to the function's parameter b. Operations on b then change the value of x, but not its type or address. This is "call-by-reference" in C. >> > >> >In Python, there is only one way to pass an argument. There may be pointers flying around, but we never see them. We will have to infer what is going on by doing some tests. Again, the model and terminology for our discussion is: >> > >> > variable:(name, pointer) --> object:(type, value, address) >> > >> >Here is a simple program that calls a function with one parameter. >> > >> > >>> def f(b): b[:] = range(9) >> > >> > >>> x = ['abc', 'xyz'] >> > >>> f(x) >> > >>> x >> > [0, 1, 2, 3, 4, 5, 6, 7, 8] >> > >> >In the call to function f, we must infer that a reference to the caller's variable x is copied to the function's variable b. Operations on b then change the value of x, but not its type or address. >> > >> >I know there are later complications ( What if x is immutable? What if b gets re-assigned within the function? ), but right now I would like to focus on exactly what happens in the call to function f. >> > >> >I'll pause once more to see if I've made any mistakes, before the third and final step - deciding what to call this thing that Python does in passing an argument. >> > >> >-- Dave >> > >> > >> >At 12:41 PM 5/15/2008 -0700, David MacQuigg wrote: >> >>At 04:30 PM 5/14/2008 -0500, John Zelle wrote: >> >> >> >>>At some point, I have to just let this go, as I think we all on this >> >>>list have a pretty good understanding of the differences between C and >> >>>Python in terms of assignment and parameter passing. But let's _not_ use >> >>>the term "pass by reference" when talking about Python. You CANNOT >> >>>CHANGE THE CONTENTS OF THE VARIABLE THAT IS SUPPLIED AS AN ACTUAL >> >>>PARAMETER. It will still refer to the same object (contain the same >> >>>reference) regardless of what is done to the formal parameter. Hence, >> >>>the variable IS NOT passed by reference. The value of the variable >> >>>(which happens to be a reference) is copied. Pass by value is the >> >>>accepted label for this mechanism. Pass by reference means something >> >>>else (as I've pointed out in previous posts). >> >>> >> >>>Christopher's point on teaching the differences directly is, I think, a >> >>>good one. But we don't need to worry about that for beginners. >> >> >> >>I agree, the topic should not come up in a class for beginners, but the question I got was from a student in a class on C. In that situation, it does help to explain Python's calling mechanism in terms that these students understand. I've posted my answer at http://ece.arizona.edu/~edatools/ece175/Lecture/QnA.txt >> >> >> >>I used the phrase "like pass-by-reference" to avoid the controversy as much as I can. As you can see from the references cited in my answer, the terms call-by-value and call-by-reference do not have universally accepted definitions, even among experts. >> >> >> >>The differences seem to come down to what we mean by the words "value" and "reference". Everyone seems to have unstated assumptions about their meaning, probably depending on what language they are thinking about. Perhaps it will help if we can agree on models for variables in C and Python. Here are my models: >> >> >> >>In C, the type of an "object" (char, int, float, etc.) is associated with >> >>the variable name, not the object. >> >> >> >> variable:(name, type, pointer) --> object:(value, address) >> >> >> >>In Python, type is associated with the object, not the variable name. >> >> >> >> variable:(name, pointer) --> object:(type, value, address) >> >> >> >>As you can see, I've used the word "value" to mean the actual data associated with the object, and the word "pointer" to mean whatever it is that references the object (a real pointer in C, I assume a C-pointer in Python). >> >> >> >>I realize my diagrams may bias the discussion, so perhaps I should stop at this point and ask for alternative models or terminology. >> >> >> >>-- Dave >> > >> > >> >_______________________________________________ >> >Edu-sig mailing list >> >Edu-sig at python.org >> >http://mail.python.org/mailman/listinfo/edu-sig >> >> >> _______________________________________________ >> Edu-sig mailing list >> Edu-sig at python.org >> http://mail.python.org/mailman/listinfo/edu-sig >> >-- >John M. Zelle, Ph.D. Wartburg College >Professor of Computer Science Waverly, IA >john.zelle at wartburg.edu (319) 352-8360 From john.zelle at wartburg.edu Tue May 20 19:49:56 2008 From: john.zelle at wartburg.edu (John Zelle) Date: Tue, 20 May 2008 12:49:56 -0500 Subject: [Edu-sig] Pass by Reference In-Reply-To: <868920.55445.qm@web88104.mail.re2.yahoo.com> References: <868920.55445.qm@web88104.mail.re2.yahoo.com> Message-ID: <1211305796.5845.18.camel@zelle> Hi All, OK, really, this is my last post (on this topic). On Tue, 2008-05-20 at 08:59 -0700, Warren Sande wrote: > Agreed. > > Python "behaves like" call-by-value for immutable types and "behaves > like" call-by-reference for mutable types. Newbies care about how a > thing behaves, not what's going on behind the scenes. This is not really an accurate characterization. As I explained in my previous post, Python never behaves like call-by-reference. Python always and everywhere (not just in parameter passing) behaves like a language where variables store references to objects (and happens to use call-by-value for parameters). I agree that newbies need not even be engaged in the terminology discussion. > Because understanding the behavior lets them write working programs. > This seemingly inconsistent behavior is one thing that makes teaching > with Python a bit more difficult. Here I can't agree at all. The beauty of Python for newbies is that it offers you one consistent memory model for assignment, parameter passing, and everything else. This makes it unlike many other languages that have multiple, often confusingly different mechanisms. I find it much better as a first language. > Beginners want the answer to the question: "If I pass something to > a function, can the function change it or not?" And the answer is, > "It depends." That's not a great answer for a beginner. But again, this has nothing to do with functions AT ALL. The answer to the question of "can I change it?" Is always and everywhere in Python: "You can if it's a changeable (mutable) object." This has very little to do with parameter passing. I'm more and more convinced this is only a confusion for those of us who cut their teeth with languages that employ other memory models. Of course, there's no need to confuse (true) beginners with those other models. They'll only be confused if we present a confusing picture. If you're teaching (or writing for) students who might have already encountered some other languages, then there's some explaining and comparison to do. But the thing that needs to be explained is that all "values" are heap-allocated objects, and variables _always_ contain a reference to one of these. Again, don't confuse this important and cool difference with notions about how parameters are passed. --John > > > ----- Original Message ---- > From: John Posner > To: edu-sig at python.org > Sent: Tuesday, May 20, 2008 10:50:38 AM > Subject: Re: [Edu-sig] Pass by Reference > > > ... and stop trying to invent new names for a parameter passing > mechanism > > that is identical in function to traditional call by value. > > > > Yeah, but ... it will be difficult to stick to a call-by-value > characterization when confronted with this example, which is straight > from > "Call by Reference 101": > > def AddArtist(mylist): > mylist.append('TheOtherTerry') > > >>> troupe > ['Graham', 'John', 'Eric', 'Michael', 'Terry'] > > >>> AddArtist(troupe) > > >>> troupe > ['Graham', 'John', 'Eric', 'Michael', 'Terry', 'TheOtherTerry'] > > > Most students (especially newbies) won't care about what happens under > the > hood -- not at first. If it looks like a duck, walks like a duck, and > quacks > like a duck ... > > -John > > _______________________________________________ > Edu-sig mailing list > Edu-sig at python.org > http://mail.python.org/mailman/listinfo/edu-sig > > > > _______________________________________________ > Edu-sig mailing list > Edu-sig at python.org > http://mail.python.org/mailman/listinfo/edu-sig -- John M. Zelle, Ph.D. Wartburg College Professor of Computer Science Waverly, IA john.zelle at wartburg.edu (319) 352-8360 From kirby.urner at gmail.com Tue May 20 20:39:18 2008 From: kirby.urner at gmail.com (kirby urner) Date: Tue, 20 May 2008 11:39:18 -0700 Subject: [Edu-sig] Pass by Reference In-Reply-To: <1211305796.5845.18.camel@zelle> References: <868920.55445.qm@web88104.mail.re2.yahoo.com> <1211305796.5845.18.camel@zelle> Message-ID: I think this was a fascinating discussion, a high point for edu-sig in many ways, and thank the participants (not saying it's over, just some will move on at this point, I have a feeling). So I finished my 5th of 5 sessions in SA: 8629, feel free to give it a browse if you wanna see how we do it in Portland. All five sessions in forward-time order: { 1 : http://controlroom.blogspot.com/2008/04/sa-classnotes-2008419.html, 2 : http://controlroom.blogspot.com/2008/04/sa-classnotes-2008426.html, 3 : http://controlroom.blogspot.com/2008/05/sa-classnotes-200853.html, 4 : http://controlroom.blogspot.com/2008/05/sa-classnotes-2008510.html, 5 : http://controlroom.blogspot.com/2008/05/sa-classnotes-2008517.html } Kirby Addendum: As an implementation detail, you might have to copy a lot more bytes when you go x = y, if the object you're controlling at runtime is a long way away, but you want to cache more locally for some reason. You might end up with a synchronization scheme, similar to ACID for databases, such that you preserve the "shared reference" experience -- but with a lot of work behind the scenes to effectively preserve that "illusion" (not really an illusion then?). I offer this simply to underscore the point that Michael Goldwasser was making (I learned a lot from his posts), about there being a big difference between modeling *semantics* and modeling *implementation*. In my view, C was / is all about implementation (wall of memory bricks), is about being "close to the metal". The model and implementation are very deliberately coincident. However, as a hallmark of being "high level," Python expects us to forget about the metal and develop alternative "best fit" concepts. A semantic model *need not* point back to the underlying implementation, although when you start saying stuff like 'heap', 'string' and 'hash table' (aka dictionary) then you're starting to enter C territory (a whole family of concepts, owes much to K&R). There's a difference with emphasis on newcomers to programming. For example, are these people headed into electrical engineering and needing to understand computer guts in great detail, or are they biomedical researchers who only care about Python because it helps them understand their molecules. The very same CS department might customize entirely different courses based on these differing career goals. These latter programmers may never read K&R nor even be clear there's a C family of languages. That doesn't mean they're necessarily more clueless about Python's semantic model however, or are "mere beginners" with Python. On the contrary, they understand as well as anyone that adding to a namespace need not involve the unnecessary replication of the underlying objects. Anyway, go ahead and import the copy module if you really know that's a good solution (at least you'll think twice about it). From john.zelle at wartburg.edu Tue May 20 22:59:35 2008 From: john.zelle at wartburg.edu (John Zelle) Date: Tue, 20 May 2008 15:59:35 -0500 Subject: [Edu-sig] Pass by Reference In-Reply-To: <5.2.1.1.0.20080520100855.03e41b20@mail.ece.arizona.edu> References: <5.2.1.1.0.20080519025135.03c54a20@mail.ece.arizona.edu> <5.2.1.1.0.20080515115035.016e3310@mail.ece.arizona.edu> <1210800612.6060.15.camel@zelle> <482A03C2.9090009@cthoday.uklinux.net> <008201c8b192$a9d1ce20$65bda8c0@jposner> <35B96718-4FE5-4E2E-B8D4-756712DE5775@solarsail.hcs.harvard.edu> <482A03C2.9090009@cthoday.uklinux.net> <5.2.1.1.0.20080519025135.03c54a20@mail.ece.arizona.edu> <5.2.1.1.0.20080520100855.03e41b20@mail.ece.arizona.edu> Message-ID: <1211317175.5845.48.camel@zelle> Hi David, It's enough for me at this point that we all agree on what we're talking about. The rest is a matter of "taste," I think. The one real sticking point I still have with your approach is simply that what you "expect" pass-by-value to do in Python (namely make a copy of the object that a variable refers to) is not to my knowledge implemented in any language. Lots of languages have been built around "pass-by-value," and none is doing what you consider your acid-test for pass-by value. On the flip side, any language that claims pass-by-reference as part of the language allows me to do what I consider the acid test for pass-by-reference (namely I can change the referent of the calling argument), which I cannot do in Python. So I prefer to use the terms the way they have been used historically and remain consistent with language design traditions. As I've tried to emphasize, this is not really an issue of how Python passes parameters, but rather how it treats variables. I base my terminology on the traditional view of what a variable is, and that still works quite well as a consistent model for Python. Doing so allows me to use traditional terminology for parameter passing without any imprecision or change of meaning. Your model of a variable is not the traditional model (as you point out). That doesn't make your model better or worse, just different. It does mean that your model will not work for describing languages like Pascal, Fortran, C++, or Java. But your model is exactly the way I encourage my students to think about Python. I guess you are arguing for a clean break with old traditions and I am suggesting that they can co-exist (perhaps not to everyone's satisfaction). I think both of those positions have merit. --John On Tue, 2008-05-20 at 10:29 -0700, David MacQuigg wrote: > Hi John, > > I did some more searching on this question, and I see it has been discussed many times before. I read a few of the threads, and they seem to go on forever with no resolution, just a lack of communication. It comes down to the definition of "value". One camp says a value is only the actual data in an object, the other says the value can be the reference. I've been using it to mean only the data. > > variable:(name, pointer) --> object:(type, value, address) > > Looks like this controversy is not just in the Python community. I found a good discussion in Bruce Eckel's Thinking in Java, 2nd ed, Appendix A: Passing and Returning Objects. On p. 1018, he has a discussion of pass-by-value with a nice summary of the views of "two distinct camps". He concludes with "I will attempt to sidestep the issue. In the end, it isn't that important. What is important is that you understand that passing a reference allows the caller's object to be changed unexpectedly." > > I think that is what we need to focus on. What will students remember in later years? Which explanation will be most beneficial in helping them avoid problems? > > I hope that you will recognize the validity of other views, and not just say they are wrong. I think that is the only way this discussion can move forward. > > I wrote a detailed response to your last post, but decided to delete most of it. I'll just leave a few parts where I need to correct a serious misunderstanding of what I am saying. > > At 06:36 PM 5/19/2008 -0500, John Zelle wrote: > > >You insist on writing/thinking/reasoning as if Python variables > >"contain" the objects they refer to, but that simply is not the case for > >the traditional use of the term "variable." > > That is not at all what I meant. In my model the variable has only a name and a pointer. The variable refers to an object, but it does not "contain" the object, in the sense that a variable in C is like a box containing a value. > > variable:(name, pointer) --> object:(type, value, address) > > > Literally, your model, > >with the traditional definition would require that every assignment > >statement in Python create a new variable. Consider this sequence: > > > >a = 3 # creates the variable "a" > >a = 4 # "a" is now bound to another location > >a = 5 # "a" is now bound to yet another location > > > >Since the address of the value changes with each assignment, the pair > >(name, location) is changing each time, and hence we have here three > >different variables with the same name. That's certainly not the way I > >think about what's happening in Python! > > In my model, the pointer associated with the variable named "a" is moved from one object to the next, leaving the old object for the garbage collector. > > >So, my question is why don't we just stick with the traditional notion > >of a variable being a (name, location) pair. > > I've been calling it a (name, pointer) meaning the same thing. > > > Realize that Python > >dereferences the values for us when we use variables in expressions and > >stop trying to invent new names for a parameter passing mechanism that > >is identical in function to traditional call by value. > > We seem to be coming from different traditions. In my tradition, call-by-value means copying the actual data to the function, and call-by-reference means copying a reference (pointer). These definitions include all possibilities, and lead to simple inferences about safety and efficiency, which is the only benefit I can see for discussing the topic with students who are nowhere near being language theory specialists. The message to my students will be simple - It's like call by reference in C - efficient, but watch out for functions that might modify the objects you send as arguments. > > The alternative - like call by value but ... seems a lot more difficult to explain. > ... but it is efficient, because the "values" being passed are really just pointers. > ... but it is not safe, because the function can modify the caller's arguments. > > When I first learned Python, four years ago, I found the discussion in Martelli's book on call-by-value to be confusing, so much so that it impeded my understanding of the simple mechanism that it really is. This confusion was not resolved until last week when I started researching this question, in response to a student's question in class. I believe that telling students of C that Python is "call by value" will generate the same confusion that I suffered. No amount of explanation, or re-assurance "this is what some experts say" will help. > > The examples and diagrams in your section 6.5.2 are excellent. Just for fun, I re-wrote that section keeping everything the same, but changing only the few paragraphs where you talk about call-by-value. In my humble opinion, that section is shorter and much more clear from a "call-by-reference" point of view. It avoids having to say that the "values" of variables are actually the pointers, not the data. It avoids introducing more complex definitions (e.g. "call-by-reference" means that assigning a value to a formal parameter changes the value in the calling program. That's a result, not a definition, and the result depends on unrelated details of the language, like re-binding semantics.) It avoids the awkward "Isn't that interesting?" paragraph where you have to explain that in some cases you really can change the caller's object after it has been passed by value. > > I'm not saying your definitions are wrong, I just don't see the benefits of adopting these more difficult and more specialized definitions. Being consistent with some language theorists is not a benefit if it confuses students. > > -- Dave > > > >On Mon, 2008-05-19 at 10:41 -0700, David MacQuigg wrote: > >> Summarizing our earlier discussion, we now have some simple terminology and a model for what happens when a parameter is passed to a function in Python. A variable in the calling program has a name and a pointer to an object, which has a type, value, and address in memory. > >> > >> variable:(name, pointer) --> object:(type, value, address) > >> > >> When this variable is passed to a function, the pointer is copied to a new variable in the function's namespace. The original object stays exactly where it was, and no copy is made. > >> > >> Now we need to decide whether this process is a "call-by-reference", a "call-by-value", or something else. There seem to be two schools of thought. If we look just at the machinery above, we could say "clearly, it's a call-by-reference." Some Python experts say "Not so fast! It's the result that matters to users, not the underlying machinery." {see section 6.5.2 of John Zelle's Python Programming for a good presentation of the "call-by-value" point-of-view, and section 10.3.1 of Michael Goldwasser's Object-Oriented Programming in Python for a good presentation of the "call-by-reference" point-of-view.} > >> > >> In the traditional definitions {Kernighan & Ritchie, 2nd ed. p.27} "call-by-value" means copying the original value from the caller to the function. "Call-by-reference" means copying only a reference (pointer) to the original value. The results, which students will remember, are that call-by-value is safe, and call-by-reference is efficient. In a call-by-value, the original object is safe from any modification by the function. In a call-by-reference, passing a pointer takes minimum time and memory, no matter how big the object is. > >> > >> The problem is that Python doesn't exactly fit our expectations in using either of the traditional definitions. If we look just at the machinery, its a call-by-reference. Then we run into problems if we expect to modify the original object. Unlike C, there is no way to simply stuff a value into a location specified by a pointer. The result is much like call-by-value, at least for immutable objects. > >> > >> If look just at this result, and say "call-by-value", we run into problems with mutable objects, and have to resort to explanations that students find vague and counter-intuitive, like - "the object itself is passed" or, "the value IS the pointer". > >> > >> My preference at this point (perhaps my engineer's bias) is to say Python is "like call-by-reference". That keeps the explanation a lot closer to the underlying machinery (which engineering students will remember). It is safer to err on the side of call-by-reference (no nasty surprises with mutable objects). The apparent deviations from the simple model can be explained with concepts that students need to learn anyway (mutability and re-binding). > >> > >> I said earlier that we shouldn't raise this topic in a class for beginners, but now I think it is quite appropriate for college freshmen. I'm an electrical engineer, not a computer scientist, but I do remember learning about call-by-value/reference decades ago. I think there is value in keeping the definitions simple, even if modern languages don't conform. Let's not muddy the waters with "call by object" or other ill-defined concepts. There really are only two ways to pass an argument to a function - copy the value or copy a reference. > >> > >> -- Dave > >> > >> > >> At 01:48 PM 5/16/2008 -0700, David MacQuigg wrote: > >> > >> >If there are no objections to my models and terminology, the next step is to describe exactly what happens when we pass an argument in C and in Python. > >> > > >> >C is very helpful, since there is nothing hidden in this primitive language, and we can see exactly what is happening. Also, there is no confusion about the definitions of "call-by-value" and "call-by-reference". See Kernighan & Ritchie, 2nd ed. p.27. Let's call these the "traditional" definitions. In C there are only two ways to pass an argument - copy its value or copy a reference (pointer) to that value. > >> > > >> >Again, the model and terminology for C in this discussion is: > >> > > >> > variable:(name, type, pointer) --> object:(value, address) > >> > > >> >The variable name, type, and pointer are kept by the compiler. The compiled module has just the actual data bits representing the value stored at a particular address. > >> > > >> >Here is a simple program that calls a function with two parameters, one called by value, the other by reference. > >> >f(int a, int *b) { > >> > a += 1; // modifies a local variable > >> > *b += 10; // modifies the caller's variable > >> >} > >> >main() { > >> > int x = 0; > >> > f(x, &x); // pass the value and the pointer > >> > printf("x = %d\n", x); > >> >} > >> >// output is x = 10 > >> >In the call to function f, the value of the caller's variable x is copied to the function's parameter a. The function then operates on its own copy of this value, and the original data value is safe from any modification by the function. This is "call-by-value" in C. > >> > > >> >In that same call, the address of the caller's variable x is copied to the function's parameter b. Operations on b then change the value of x, but not its type or address. This is "call-by-reference" in C. > >> > > >> >In Python, there is only one way to pass an argument. There may be pointers flying around, but we never see them. We will have to infer what is going on by doing some tests. Again, the model and terminology for our discussion is: > >> > > >> > variable:(name, pointer) --> object:(type, value, address) > >> > > >> >Here is a simple program that calls a function with one parameter. > >> > > >> > >>> def f(b): b[:] = range(9) > >> > > >> > >>> x = ['abc', 'xyz'] > >> > >>> f(x) > >> > >>> x > >> > [0, 1, 2, 3, 4, 5, 6, 7, 8] > >> > > >> >In the call to function f, we must infer that a reference to the caller's variable x is copied to the function's variable b. Operations on b then change the value of x, but not its type or address. > >> > > >> >I know there are later complications ( What if x is immutable? What if b gets re-assigned within the function? ), but right now I would like to focus on exactly what happens in the call to function f. > >> > > >> >I'll pause once more to see if I've made any mistakes, before the third and final step - deciding what to call this thing that Python does in passing an argument. > >> > > >> >-- Dave > >> > > >> > > >> >At 12:41 PM 5/15/2008 -0700, David MacQuigg wrote: > >> >>At 04:30 PM 5/14/2008 -0500, John Zelle wrote: > >> >> > >> >>>At some point, I have to just let this go, as I think we all on this > >> >>>list have a pretty good understanding of the differences between C and > >> >>>Python in terms of assignment and parameter passing. But let's _not_ use > >> >>>the term "pass by reference" when talking about Python. You CANNOT > >> >>>CHANGE THE CONTENTS OF THE VARIABLE THAT IS SUPPLIED AS AN ACTUAL > >> >>>PARAMETER. It will still refer to the same object (contain the same > >> >>>reference) regardless of what is done to the formal parameter. Hence, > >> >>>the variable IS NOT passed by reference. The value of the variable > >> >>>(which happens to be a reference) is copied. Pass by value is the > >> >>>accepted label for this mechanism. Pass by reference means something > >> >>>else (as I've pointed out in previous posts). > >> >>> > >> >>>Christopher's point on teaching the differences directly is, I think, a > >> >>>good one. But we don't need to worry about that for beginners. > >> >> > >> >>I agree, the topic should not come up in a class for beginners, but the question I got was from a student in a class on C. In that situation, it does help to explain Python's calling mechanism in terms that these students understand. I've posted my answer at http://ece.arizona.edu/~edatools/ece175/Lecture/QnA.txt > >> >> > >> >>I used the phrase "like pass-by-reference" to avoid the controversy as much as I can. As you can see from the references cited in my answer, the terms call-by-value and call-by-reference do not have universally accepted definitions, even among experts. > >> >> > >> >>The differences seem to come down to what we mean by the words "value" and "reference". Everyone seems to have unstated assumptions about their meaning, probably depending on what language they are thinking about. Perhaps it will help if we can agree on models for variables in C and Python. Here are my models: > >> >> > >> >>In C, the type of an "object" (char, int, float, etc.) is associated with > >> >>the variable name, not the object. > >> >> > >> >> variable:(name, type, pointer) --> object:(value, address) > >> >> > >> >>In Python, type is associated with the object, not the variable name. > >> >> > >> >> variable:(name, pointer) --> object:(type, value, address) > >> >> > >> >>As you can see, I've used the word "value" to mean the actual data associated with the object, and the word "pointer" to mean whatever it is that references the object (a real pointer in C, I assume a C-pointer in Python). > >> >> > >> >>I realize my diagrams may bias the discussion, so perhaps I should stop at this point and ask for alternative models or terminology. > >> >> > >> >>-- Dave > >> > > >> > > >> >_______________________________________________ > >> >Edu-sig mailing list > >> >Edu-sig at python.org > >> >http://mail.python.org/mailman/listinfo/edu-sig > >> > >> > >> _______________________________________________ > >> Edu-sig mailing list > >> Edu-sig at python.org > >> http://mail.python.org/mailman/listinfo/edu-sig > >> > >-- > >John M. Zelle, Ph.D. Wartburg College > >Professor of Computer Science Waverly, IA > >john.zelle at wartburg.edu (319) 352-8360 > > > _______________________________________________ > Edu-sig mailing list > Edu-sig at python.org > http://mail.python.org/mailman/listinfo/edu-sig > From warren.sande at rogers.com Wed May 21 03:35:54 2008 From: warren.sande at rogers.com (Warren Sande) Date: Tue, 20 May 2008 18:35:54 -0700 (PDT) Subject: [Edu-sig] Pass by Reference Message-ID: <827038.94282.qm@web88102.mail.re2.yahoo.com> I would argue that from a "functional" point of view (black box, the way it behaves), Python does behave like call-by-reference, for mutable types. In another language, if I use call-by-reference, and the function modifies the variable, the caller's variable changes. That's the same behavior I get in Python with mutable types (just as in John Posner's example). I understand that it is not truly call-by-reference. But from the outside, that's what it looks like, for mutable types. For immutable types it looks like call-by-value, since changing it in the function does not change the caller's "copy" I definitely agree that Python is the best choice for a first language. But there is this one inconsistency (or maybe call it a duality) of mutable vs immutable types, that I think can be a bit confusing. Putting aside the "pass-by-X" question, a beginner asks: "If I do A = (something) then B = A then I change A, does B also change?" And the answer, again, is "It depends." For mutable types, yes, for immutable types, no. And that's a sticky thing to get into for a beginner who is just learning what variables (names) are about. >>> a = 5 >>> b = a >>> a 5 >>> b 5 >>> a = 7 >>> a 7 >>> b 5 >>> a = [8] >>> b = a >>> a [8] >>> b [8] >>> a.append(9) >>> a [8, 9] >>> b [8, 9] I know that in the first case, you are not really "changing" a, you are attaching the name 'a' to a new object (7, instead of 5). But that's not what it looks like from the outside. It looks like you are changing a, and b is not changing. In the second case, you are changing a, and b is changing. I'm not saying the memory model is inconsistent, just that it can appear that way to a beginner. And I think that's true whether they have had exposure to another language or not. Respectfully, Warren Sande ----- Original Message ---- From: John Zelle To: Warren Sande Cc: edu-sig at python.org Sent: Tuesday, May 20, 2008 1:49:56 PM Subject: Re: [Edu-sig] Pass by Reference Hi All, OK, really, this is my last post (on this topic). On Tue, 2008-05-20 at 08:59 -0700, Warren Sande wrote: > Agreed. > > Python "behaves like" call-by-value for immutable types and "behaves > like" call-by-reference for mutable types. Newbies care about how a > thing behaves, not what's going on behind the scenes. This is not really an accurate characterization. As I explained in my previous post, Python never behaves like call-by-reference. Python always and everywhere (not just in parameter passing) behaves like a language where variables store references to objects (and happens to use call-by-value for parameters). I agree that newbies need not even be engaged in the terminology discussion. > Because understanding the behavior lets them write working programs. > This seemingly inconsistent behavior is one thing that makes teaching > with Python a bit more difficult. Here I can't agree at all. The beauty of Python for newbies is that it offers you one consistent memory model for assignment, parameter passing, and everything else. This makes it unlike many other languages that have multiple, often confusingly different mechanisms. I find it much better as a first language. > Beginners want the answer to the question: "If I pass something to > a function, can the function change it or not?" And the answer is, > "It depends." That's not a great answer for a beginner. But again, this has nothing to do with functions AT ALL. The answer to the question of "can I change it?" Is always and everywhere in Python: "You can if it's a changeable (mutable) object." This has very little to do with parameter passing. I'm more and more convinced this is only a confusion for those of us who cut their teeth with languages that employ other memory models. Of course, there's no need to confuse (true) beginners with those other models. They'll only be confused if we present a confusing picture. If you're teaching (or writing for) students who might have already encountered some other languages, then there's some explaining and comparison to do. But the thing that needs to be explained is that all "values" are heap-allocated objects, and variables _always_ contain a reference to one of these. Again, don't confuse this important and cool difference with notions about how parameters are passed. --John > > > ----- Original Message ---- > From: John Posner > To: edu-sig at python.org > Sent: Tuesday, May 20, 2008 10:50:38 AM > Subject: Re: [Edu-sig] Pass by Reference > > > ... and stop trying to invent new names for a parameter passing > mechanism > > that is identical in function to traditional call by value. > > > > Yeah, but ... it will be difficult to stick to a call-by-value > characterization when confronted with this example, which is straight > from > "Call by Reference 101": > > def AddArtist(mylist): > mylist.append('TheOtherTerry') > > >>> troupe > ['Graham', 'John', 'Eric', 'Michael', 'Terry'] > > >>> AddArtist(troupe) > > >>> troupe > ['Graham', 'John', 'Eric', 'Michael', 'Terry', 'TheOtherTerry'] > > > Most students (especially newbies) won't care about what happens under > the > hood -- not at first. If it looks like a duck, walks like a duck, and > quacks > like a duck ... > > -John > > _______________________________________________ > Edu-sig mailing list > Edu-sig at python.org > http://mail.python.org/mailman/listinfo/edu-sig > > > > _______________________________________________ > Edu-sig mailing list > Edu-sig at python.org > http://mail.python.org/mailman/listinfo/edu-sig -- John M. Zelle, Ph.D. Wartburg College Professor of Computer Science Waverly, IA john.zelle at wartburg.edu (319) 352-8360 -------------- next part -------------- An HTML attachment was scrubbed... URL: From john.zelle at wartburg.edu Wed May 21 05:55:24 2008 From: john.zelle at wartburg.edu (John Zelle) Date: Tue, 20 May 2008 22:55:24 -0500 Subject: [Edu-sig] Pass by Reference In-Reply-To: <827038.94282.qm@web88102.mail.re2.yahoo.com> References: <827038.94282.qm@web88102.mail.re2.yahoo.com> Message-ID: <1211342124.6078.83.camel@zelle> Hi Warren, Some interesting thoughts. You have given me something of a new insight. (So call this a post on a related topic :-) On Tue, 2008-05-20 at 18:35 -0700, Warren Sande wrote: > I would argue that from a "functional" point of view (black box, the > way it behaves), Python does behave like call-by-reference, for > mutable types. > > In another language, if I use call-by-reference, and the function > modifies the variable, the caller's variable changes. That's the same > behavior I get in Python with mutable types (just as in John Posner's > example). OK. Again, this is not about parameter passing. To demonstrate, let's take a language that has both call-by-reference and call-by-value, Pascal springs to mind. If you send a linked list (most probably a pointer to a header node) by value in Pascal and you change the structure of the linked list, guess what, the change appears back in the caller. The same thing happens if you use Pascal's pass by reference mechanism. This example is not a test of what kind of parameter passing you do. It is a test of whether the variable you pass holds a reference or actually stores the object. Of course all Python variables hold references and are therefore analogous (in this respect) to Pascal pointers. > I understand that it is not truly call-by-reference. But from the > outside, that's what it looks like, for mutable types. For immutable > types it looks like call-by-value, since changing it in the function > does not change the caller's "copy" I simply don't understand this comment. You can't change an immutable object in the caller or the callee. That's what makes the object immutable. What you can do is change what object a variable refers to (by assignment) and that change has no effect in the callee regardless of whether the type of the object (originally) being referred to is mutable or not. > > I definitely agree that Python is the best choice for a first > language. But there is this one inconsistency (or maybe call it a > duality) of mutable vs immutable types, that I think can be a bit > confusing. > > Putting aside the "pass-by-X" question, a beginner asks: > > "If I do A = (something) then B = A then I change A, does B > also change?" The answer to this question is "yes" always and everywhere in Python. If A refers to a mutable object, then any changes through A will be visible to B. If A's object is not mutable, then you can't change it, period. So if you can make a change to A's object, it is mutable and B's object changes as well (since they are the same object). If you mean does reassigning A have any effect on B, then the answer is "no" always and everywhere in Python. Setting A = C will change A's reference and have no effect whatsoever on B, it makes no difference whether A's original object was mutable or not. > And the answer, again, is "It depends." For mutable types, yes, for > immutable types, no. And that's a sticky thing to get into for a > beginner who is just learning what variables (names) are about. No, it does not depend on whether the object is mutable. It depends on whether you are changing the object or reassigning the variable. The question is not whether A refers to a mutable object, but rather, what does the student mean by "change A." Does he/she mean assign A to be a different object or apply an operation that changes the state of A's object. When posed that way, both answers seem fairly obvious. I think you are on to something here, namely that some confusion actually stems from the overloaded meaning of "Change A." That can mean either change what A refers to or change the state of the object that A refers to. Perhaps as teachers we need to be more careful about using phrases like "reassign A" and "change A's object" vs. "change A." No doubt, this is what leads to your (apparent) mutable/immutable dichotomy, since reassignment is the one and only way to "change A" if A is a reference to an immutable object. > >>> a = 5 > >>> b = a > >>> a > 5 > >>> b > 5 > >>> a = 7 > >>> a > 7 > >>> b > 5 > > >>> a = [8] > >>> b = a > >>> a > [8] > >>> b > [8] > >>> a.append(9) > >>> a > [8, 9] > >>> b > [8, 9] > > I know that in the first case, you are not really "changing" a, you > are attaching the name 'a' to a new object (7, instead of 5). But > that's not what it looks like from the outside. It looks like you are > changing a, and b is not changing. In the second case, you are > changing a, and b is changing. I really like your example, because it makes my point that this discussion is not about parameter passing at all, but rather about memory models. But I don't understand what you mean "that is not what it looks like from the outside." In one case you reassign a and in the other case you don't. They _look_ like _very_different_ things (a = 8, vs. a.append(9)). Therefore one should probably expect they have very different effects, which they do. If you just draw the picture of what assignment does (using arrows for references), these examples are crystal clear. I don't think it should be confusing for newbies. It's probably more confusing for us oldbies. Or perhaps, as suggested above we sow confusion ourselves by generically saying both of these "change a". > I'm not saying the memory model is inconsistent, just that it can > appear that way to a beginner. And I think that's true whether they > have had exposure to another language or not. > If you tell your students that assignment causes the variable to be attached to a different object (my sticky note analogy), then it should be pretty obvious that performing an assignment does not affect another variable (you're just removing one label from the object). If you tell them that assignment of one variable to another gives them another name for the same object (puts another note on the same object), then they should expect both names to see the any changes to the object (ala Kirby's leash example). I can see room for confusion if you are already used to a language that routinely makes copies of complex objects via assignment and somehow expect Python to be making copies of those objects. But if Python is a student's first language, why on earth would one expect that? It's not a more intuitive model, just a different one. When I teach C/C++ to my Python-aware students, the first hurdle is to grasp that variables represent locations and that assignment copies values not references. They find that model a bit confusing until they get used to it. But we draw lots of pictures and it doesn't take long for them to come around. Of course the object-slicing of assignment from derived types to basetypes tends to give them headaches (me too). --John > _______________________________________________ > Edu-sig mailing list > Edu-sig at python.org > http://mail.python.org/mailman/listinfo/edu-sig -- John M. Zelle, Ph.D. Wartburg College Professor of Computer Science Waverly, IA john.zelle at wartburg.edu (319) 352-8360 From jjposner at snet.net Wed May 21 06:27:07 2008 From: jjposner at snet.net (John Posner) Date: Wed, 21 May 2008 00:27:07 -0400 Subject: [Edu-sig] Pass by Reference In-Reply-To: References: Message-ID: <00f801c8bafa$edefb880$65bda8c0@jposner> > > OK, really, this is my last post (on this topic). > Shall we let Lewis Carroll have the last word? ... 'You are sad,' the Knight said in an anxious tone: 'let me sing you a song to comfort you.' 'Is it very long?' Alice asked, for she had heard a good deal of poetry that day. 'It's long,' said the Knight, 'but very, VERY beautiful. Everybody that hears me sing it--either it brings the TEARS into their eyes, or else--' 'Or else what?' said Alice, for the Knight had made a sudden pause. 'Or else it doesn't, you know. The name of the song is called "HADDOCKS' EYES."' 'Oh, that's the name of the song, is it?' Alice said, trying to feel interested. 'No, you don't understand,' the Knight said, looking a little vexed. 'That's what the name is CALLED. The name really IS "THE AGED AGED MAN."' 'Then I ought to have said "That's what the SONG is called"?' Alice corrected herself. 'No, you oughtn't: that's quite another thing! The SONG is called "WAYS AND MEANS": but that's only what it's CALLED, you know!' 'Well, what IS the song, then?' said Alice, who was by this time completely bewildered. 'I was coming to that,' the Knight said. 'The song really IS "A-SITTING ON A GATE": and the tune's my own invention.' -John Posner From macquigg at ece.arizona.edu Wed May 21 16:47:09 2008 From: macquigg at ece.arizona.edu (David MacQuigg) Date: Wed, 21 May 2008 07:47:09 -0700 Subject: [Edu-sig] Pass by Reference In-Reply-To: <827038.94282.qm@web88102.mail.re2.yahoo.com> Message-ID: <5.2.1.1.0.20080521072833.016e3310@mail.ece.arizona.edu> At 06:35 PM 5/20/2008 -0700, Warren Sande wrote: >Putting aside the "pass-by-X" question, a beginner asks: > >"If I do A = (something) then B = A then I change A, does B also change?" > >And the answer, again, is "It depends." For mutable types, yes, for immutable types, no. And that's a sticky thing to get into for a beginner who is just learning what variables (names) are about. At this point, I would immediately stop using vague words like "change", and try to find words with a more precise meaning, like "re-bind" and "modify". "Re-assign" would be another possibility, but I see that "re-bind" is commonly used in Python texts. Also, it is a less common word than re-assign, so less likely to have other meanings. "Mutate" might be better than "modify" for the same reason. Long before any discussion of parameter passing, students should have a firm grasp of how variables work in Python, including the concepts of mutability and rebinding. This is the model and terminology I suggest: variable:(name, pointer) --> object:(type, value, address) Other than the word "value", I don't see any confusion with any of these terms. I haven't heard any suggestions for a better simple model. With this model in mind, the simple answer to the student's question is - "It depends on whether you are modifying the object of variable A, or re-binding A to some other object. -- Dave From kirby.urner at gmail.com Wed May 21 17:34:03 2008 From: kirby.urner at gmail.com (kirby urner) Date: Wed, 21 May 2008 08:34:03 -0700 Subject: [Edu-sig] Pass by Reference In-Reply-To: <5.2.1.1.0.20080521072833.016e3310@mail.ece.arizona.edu> References: <827038.94282.qm@web88102.mail.re2.yahoo.com> <5.2.1.1.0.20080521072833.016e3310@mail.ece.arizona.edu> Message-ID: In the meantime, I've been working on that name 'variable' the CS types keep using, spinning it different [sic], so that in Python we think of 'variable' as meaning the user makes up the name out of the blue (that's what's so variable about it, we're not even thinking about "contents" (what's that?)). This is suitable for a day when unicode strings are getting very *not* Latin-1 in some contexts, so seem even more variable than usual, given our humble past of 128 then 256 (extended!) possible characters (punctuation, carriage return, little bell (ding! -- later a beep)). So when a Pythonista comes to C in CS wanting to learn the rope (pointers to pointers etc.), a prof might have to work extra hard to reinstill that old fashioned idea of a "variable" being "a container" of something (weird), a notion somewhat alien to those most competent in Python. Analogy: a kitchen coffee mug with a fun logo, design or slogan on the "outside" (topologically, said mug is a donut, something with one hole and one outside surface (irrelevant aside, but might come in handy)). A Python student looks at the mug and says, "hey, that's a cool variable" (admiring the picture of some wolf-horse or whatever). A C student says "what do you mean, it's still empty?" The C student calls the mug "a variable" because of all the wonderful stuff we might but "inside" the mug (strange huh? -- welcome to the wonderful world of K&R, MMX etc.). Kirby On Wed, May 21, 2008 at 7:47 AM, David MacQuigg wrote: > At 06:35 PM 5/20/2008 -0700, Warren Sande wrote: > >>Putting aside the "pass-by-X" question, a beginner asks: >> >>"If I do A = (something) then B = A then I change A, does B also change?" >> >>And the answer, again, is "It depends." For mutable types, yes, for immutable types, no. And that's a sticky thing to get into for a beginner who is just learning what variables (names) are about. > > At this point, I would immediately stop using vague words like "change", and try to find words with a more precise meaning, like "re-bind" and "modify". "Re-assign" would be another possibility, but I see that "re-bind" is commonly used in Python texts. Also, it is a less common word than re-assign, so less likely to have other meanings. "Mutate" might be better than "modify" for the same reason. > > Long before any discussion of parameter passing, students should have a firm grasp of how variables work in Python, including the concepts of mutability and rebinding. This is the model and terminology I suggest: > > variable:(name, pointer) --> object:(type, value, address) > > Other than the word "value", I don't see any confusion with any of these terms. I haven't heard any suggestions for a better simple model. > > With this model in mind, the simple answer to the student's question is - "It depends on whether you are modifying the object of variable A, or re-binding A to some other object. > > -- Dave > > > > > _______________________________________________ > Edu-sig mailing list > Edu-sig at python.org > http://mail.python.org/mailman/listinfo/edu-sig > From macquigg at ece.arizona.edu Wed May 21 18:34:27 2008 From: macquigg at ece.arizona.edu (David MacQuigg) Date: Wed, 21 May 2008 09:34:27 -0700 Subject: [Edu-sig] Pass by Reference Message-ID: <5.2.1.1.0.20080521093306.03bf6ad8@plus.pop.mail.yahoo.com> Hi John, I think what we all agree on is the details of what is happening in Python. As long as we use unambiguous words to describe that process, there is no problem. The problem is in the definition of "call-by-value". I have offered a simple definition, what I called the "traditional" definition, but perhaps that is claiming too much priority for one tradition. I'll call it the "common" definition, what most programmers will tell you, and what you find at http://en.wikipedia.org/wiki/Call_by_value I know this discussion is getting very old, but I would like to get just one thing resolved. Can you give us clear and concise definitions of call-by-value and call-by-reference? At 03:59 PM 5/20/2008 -0500, John Zelle wrote: >Hi David, > >It's enough for me at this point that we all agree on what we're talking >about. The rest is a matter of "taste," I think. The one real sticking >point I still have with your approach is simply that what you "expect" >pass-by-value to do in Python (namely make a copy of the object that a >variable refers to) is not to my knowledge implemented in any language. C does call-by-value, at least with primitive objects (according to Kernighan and Ritchie). >Lots of languages have been built around "pass-by-value," and none is >doing what you consider your acid-test for pass-by value. On the flip >side, any language that claims pass-by-reference as part of the language >allows me to do what I consider the acid test for pass-by-reference >(namely I can change the referent of the calling argument), which I >cannot do in Python. I assume by "change" you mean "re-bind", and by "referent" you mean "object". It is possible to modify the object of the calling argument. > So I prefer to use the terms the way they have been >used historically and remain consistent with language design >traditions. I'm finding it hard to understand your terms, perhaps because I'm not familiar with the traditions you refer to. It would really help if we could use the same words for simple things we all understand. Here are my suggestions. variable:(name, pointer) --> object:(type, value, address) re-bind a variable modify an object copy a pointer -- Dave >On Tue, 2008-05-20 at 10:29 -0700, David MacQuigg wrote: >> Hi John, >> >> I did some more searching on this question, and I see it has been discussed many times before. I read a few of the threads, and they seem to go on forever with no resolution, just a lack of communication. It comes down to the definition of "value". One camp says a value is only the actual data in an object, the other says the value can be the reference. I've been using it to mean only the data. >> >> variable:(name, pointer) --> object:(type, value, address) >> >> Looks like this controversy is not just in the Python community. I found a good discussion in Bruce Eckel's Thinking in Java, 2nd ed, Appendix A: Passing and Returning Objects. On p. 1018, he has a discussion of pass-by-value with a nice summary of the views of "two distinct camps". He concludes with "I will attempt to sidestep the issue. In the end, it isn't that important. What is important is that you understand that passing a reference allows the caller's object to be changed unexpectedly." >> >> I think that is what we need to focus on. What will students remember in later years? Which explanation will be most beneficial in helping them avoid problems? >> >> I hope that you will recognize the validity of other views, and not just say they are wrong. I think that is the only way this discussion can move forward. >> >> I wrote a detailed response to your last post, but decided to delete most of it. I'll just leave a few parts where I need to correct a serious misunderstanding of what I am saying. >> >> At 06:36 PM 5/19/2008 -0500, John Zelle wrote: >> >> >You insist on writing/thinking/reasoning as if Python variables >> >"contain" the objects they refer to, but that simply is not the case for >> >the traditional use of the term "variable." >> >> That is not at all what I meant. In my model the variable has only a name and a pointer. The variable refers to an object, but it does not "contain" the object, in the sense that a variable in C is like a box containing a value. >> >> variable:(name, pointer) --> object:(type, value, address) >> >> > Literally, your model, >> >with the traditional definition would require that every assignment >> >statement in Python create a new variable. Consider this sequence: >> > >> >a = 3 # creates the variable "a" >> >a = 4 # "a" is now bound to another location >> >a = 5 # "a" is now bound to yet another location >> > >> >Since the address of the value changes with each assignment, the pair >> >(name, location) is changing each time, and hence we have here three >> >different variables with the same name. That's certainly not the way I >> >think about what's happening in Python! >> >> In my model, the pointer associated with the variable named "a" is moved from one object to the next, leaving the old object for the garbage collector. >> >> >So, my question is why don't we just stick with the traditional notion >> >of a variable being a (name, location) pair. >> >> I've been calling it a (name, pointer) meaning the same thing. >> >> > Realize that Python >> >dereferences the values for us when we use variables in expressions and >> >stop trying to invent new names for a parameter passing mechanism that >> >is identical in function to traditional call by value. >> >> We seem to be coming from different traditions. In my tradition, call-by-value means copying the actual data to the function, and call-by-reference means copying a reference (pointer). These definitions include all possibilities, and lead to simple inferences about safety and efficiency, which is the only benefit I can see for discussing the topic with students who are nowhere near being language theory specialists. The message to my students will be simple - It's like call by reference in C - efficient, but watch out for functions that might modify the objects you send as arguments. >> >> The alternative - like call by value but ... seems a lot more difficult to explain. >> ... but it is efficient, because the "values" being passed are really just pointers. >> ... but it is not safe, because the function can modify the caller's arguments. >> >> When I first learned Python, four years ago, I found the discussion in Martelli's book on call-by-value to be confusing, so much so that it impeded my understanding of the simple mechanism that it really is. This confusion was not resolved until last week when I started researching this question, in response to a student's question in class. I believe that telling students of C that Python is "call by value" will generate the same confusion that I suffered. No amount of explanation, or re-assurance "this is what some experts say" will help. >> >> The examples and diagrams in your section 6.5.2 are excellent. Just for fun, I re-wrote that section keeping everything the same, but changing only the few paragraphs where you talk about call-by-value. In my humble opinion, that section is shorter and much more clear from a "call-by-reference" point of view. It avoids having to say that the "values" of variables are actually the pointers, not the data. It avoids introducing more complex definitions (e.g. "call-by-reference" means that assigning a value to a formal parameter changes the value in the calling program. That's a result, not a definition, and the result depends on unrelated details of the language, like re-binding semantics.) It avoids the awkward "Isn't that interesting?" paragraph where you have to explain that in some cases you really can change the caller's object after it has been passed by value. >> >> I'm not saying your definitions are wrong, I just don't see the benefits of adopting these more difficult and more specialized definitions. Being consistent with some language theorists is not a benefit if it confuses students. >> >> -- Dave -------------- next part -------------- An HTML attachment was scrubbed... URL: From john.zelle at wartburg.edu Thu May 22 00:17:40 2008 From: john.zelle at wartburg.edu (John Zelle) Date: Wed, 21 May 2008 17:17:40 -0500 Subject: [Edu-sig] Pass by Reference In-Reply-To: <5.2.1.1.0.20080521075310.03c0c2c8@mail.ece.arizona.edu> References: <5.2.1.1.0.20080520100855.03e41b20@mail.ece.arizona.edu> <5.2.1.1.0.20080519025135.03c54a20@mail.ece.arizona.edu> <5.2.1.1.0.20080515115035.016e3310@mail.ece.arizona.edu> <1210800612.6060.15.camel@zelle> <482A03C2.9090009@cthoday.uklinux.net> <008201c8b192$a9d1ce20$65bda8c0@jposner> <35B96718-4FE5-4E2E-B8D4-756712DE5775@solarsail.hcs.harvard.edu> <482A03C2.9090009@cthoday.uklinux.net> <5.2.1.1.0.20080519025135.03c54a20@mail.ece.arizona.edu> <5.2.1.1.0.20080520100855.03e41b20@mail.ece.arizona.edu> <5.2.1.1.0.20080521075310.03c0c2c8@mail.ece.arizona.edu> Message-ID: <1211408260.6106.100.camel@zelle> Hi David, I gave a detailed description of my definitions in a post a while back. In that, I referred to the traditional view of a variable as a named location. As per your request: In call-by-value the formal parameter is a local variable whose content is initialized with a copy of the value of the actual parameter. Assignment to the formal parameter has no effect on the actual argument. In pass by reference, the formal parameter is a name bound (by reference) to the variable used as the argument of the call. In this case, assignment to the formal parameter actually changes what is stored in the caller variable. On Wed, 2008-05-21 at 08:41 -0700, David MacQuigg wrote: > Hi John, > > I think what we all agree on is the details of what is happening in > Python. As long as we use unambiguous words to describe that process, > there is no problem. The problem is in the definition of > "call-by-value". I have offered a simple definition, what I called > the "traditional" definition, but perhaps that is claiming too much > priority for one tradition. I'll call it the "common" definition, > what most programmers will tell you, and what you find at > http://en.wikipedia.org/wiki/Call_by_value I'm using the exact same definition of call-by-value as you find in this wikipedia entry. The difference between your view and mine does not turn on the definition of call by value, but rather on what constitutes the "value" of the expression. I'm saying it's clean, simple, and correct to say the result of an expression in Python is a reference to some object. And that reference is what is stored into a variable (which is then still just a named location). You're saying the value of the expression _is_ the object. In your view then, variables contain objects. I often speak along those lines with Python, but in terms of defining the semantics of languages, I think it's cleaner to say that Python variables contain references. That way the term "variable" means the same thing for virtually every language (Prolog notwithstanding). And all of the historical terms still work just fine. In addition, if you look at the Python interpreter, I'm sure there are references (addresses) to these heap-allocated objects running around all over the place, for example in the runtime stack-frames. What do you call the locations that contain those references, if not "variables." That's certainly what they've been called in the traditional programming languages literature for decades now. As for the wikipedia entry on call-by-reference, I find it too ambiguous to say much about, but I can certainly make the case that it agrees with me. What is an "implicit reference to the argument?" In the "canonical" call by reference languages such as FORTRAN and Pascal, the argument to the call has to be a variable (C++ lifts this restriction). The formal parameter then becomes an alias for the same memory location as the argument variable. In essence the formal parameter is a variable that still lives in the caller's stack frame. This is achieved by passing the variable's address "behind the scenes," and the language then specially and automatically dereferences the address to manipulate the non-local variable. That, to me, is call by reference. The reference is being sent _implicitly_ and the language does something special to make it all work. In other words, I reserve the term pass-by-reference as a name for this specific language mechanism, not as a generic term for passing references around in programs. You can pass references around in (virtually) any language, regardless of what parameter passing mechanism the designers provide. As I've pointed out before, I can pass references (pointers) around in Pascal without ever using the pass-by-reference mechanism that's built into the language. And I will have the "visible side-effects" that result from aliasing. But that is not pass-by-reference semantics. In the case of Python, the references are _explicit_. The interpreter doesn't do anything special or different behind the scenes at function call time to grab the address of the argument. All Python variables contain references, and expressions evaluate to references. The parameter passing mechanism just copies the value of the reference from the caller's variable into the formal parameter. The formal parameter is still a local variable in every sense. You know this to be true, because reassigning it has no effect in the caller. I notice that the Wikipedia article tries to have it both ways by saying Java is a "call-by-value language" but "frequently displays call by reference semantics." But there are not two different mechanisms in Java. The _mechanism_ is call-by-value. The call always happens in exactly the same way regardless of the argument type. It just so happens that when the argument is a reference to something mutable, then changes to that mutable thing are visible to the caller, just as in Python, Pascal (non VAR params), C, and any other call-by-value language that allows variables to contain references to heap-allocated objects. By the way, the _lack_ of call-by-reference or a way to simulate it in Java is, to my mind, a design flaw, as it leaves no straightforward mechanism for a function to return multiple values. This is not an issue in Python, which has multiple return values (well, packs and unpacks tuples automatically). I don't know if this helps clarify my position or not. But you asked... --John ps. Here's my acid test. A call-by-reference mechanism allows me to define a swap function: >>> a = 3 >>> b = 5 >>> swap(a,b) >>> a 5 >>> b 3 Show me a Python function that does that and I'll gladly say it has pass-by-reference semantics (or copy-restore :-). > -- John M. Zelle, Ph.D. Wartburg College Professor of Computer Science Waverly, IA john.zelle at wartburg.edu (319) 352-8360 From kirby.urner at gmail.com Thu May 22 03:13:00 2008 From: kirby.urner at gmail.com (kirby urner) Date: Wed, 21 May 2008 18:13:00 -0700 Subject: [Edu-sig] Python for Beginners Message-ID: For true beginners, I think we should leverage their experience with The Web, assume that as a given, and seek analogies on that basis. We needn't begin with any model of "computer memory" in the sense of some individual standalone machine with a flash drive and RAM. So how about we teach that names are like aliases for URLs, objects like websites? There's a kind of DNS service in Python where the alias maps to the actual IP number of the host, which'd be like going id(x). When you use dot notation, other syntax, against a name, e.g. dog.eat(dog), you're like "sending a message" (Smalltalk image) to a website (object) at some id number (like an ip number), thereby invoking a method, changing its state maybe. x = y involves "emailing" an URL from y to x, setting up a second alias. Recipient x now has a copy of the same URL as y, but no website got copied. This conforms to how people generally share websites, by passing hyperlinks by email. x, a name, is like "a portal" to the object it names. type(x) will give you some insight into what services are offered. dir(x) or help(x) also come in handy. This fits our model of the web in that web pages don't really know what other pages link to them (a little difference is PyObjects keep track of "how many"). We're also used to websites being "more than just data" these days, i.e. they offer services, which is characteristic of objects more generally. This'll be good prep for xml-rpc etc. We also know that web pages themselves may contain links to other web pages and so on, which reminds us of how collections work (links to links). Some objects, like some websites, are static, like 8 (a simple set of services, read-only, still an object though). Leveraging experience with animals is another way to go (it's not either/or). Because every object has a __rib__ cage (inheriting from object), we might say "everything is a snake" in Python (meaning an object with __ribs__). Some snakes quack like ducks though. Kirby From kirby.urner at gmail.com Thu May 22 19:37:34 2008 From: kirby.urner at gmail.com (kirby urner) Date: Thu, 22 May 2008 10:37:34 -0700 Subject: [Edu-sig] Python for Beginners In-Reply-To: <26A3BCEF-454A-4A09-91DB-E91CD7850F0D@stratolab.com> References: <26A3BCEF-454A-4A09-91DB-E91CD7850F0D@stratolab.com> Message-ID: At one time in my life I played with the prospect of becoming an airport manager, to the point of buying some expensive books (OK one book) on the subject and reading up in Florida (Bradenton, Golf Lakes Estates), between other jobs. I do like the postit metaphor, but have trouble visualizing going around a busy airport putting post-its on ticket counters, security apparatus, flight attendants, and not getting in trouble. On the other hand, with a textbook open, an airport depicted, I'm very used to pointers in the sense of arrows, usually labeled, call them tags or handles. Anatomy books, same thing, pointers to ribosomes, close-ups of DNA or whatever. So just to use our own OO jargon, I'd say sticky post-its are a subclass of the tag or handle concept. Descending the same tree along other branches, we get to my dog leash metaphor (the first ring of which came from a coffee cup (another idea of "a variable") in some "Youtoon" awhile back). Back to the airport, what we want students to realize is that multiple namespaces might be about the same complex institution or knowledge domain, but hey, we *don't* want to import all this complexity willy-nilly, but with an eye towards getting very specific work done. Namespaces are *designed* (more or less intelligently) for a specific *purpose*. They're the antithesis or random inventories of stuff, in most cases. And keep in mind what namespaces map: not just static data. You can fire up a jet engine, switch on the radar, start and stop elevators. A namespace is like some Lawn Mower Man fantasy, except in a more manageable and sustainable form. Yes it's about control, we're not apologetic about that. Engineering is engineering in that respect. So in one namespace it's all about baggage handling, in another all about queuing in ticket lanes, in another all about food services along the concourse, surveillance cameras (who's pigging out) -- haven't even mentioned the airplanes yet, or the runways. So many namespaces! This gets across to the beginner that we're free to tag as we please, going into a situation, and there's nothing illogical or inherently confusing about multiple namespaces using the same objects concurrently. That's how we work in the real world as human beings: as players operating in parallel within a shared environment. OO (an invention, a style of thinking) has always been about letting us think naturally, in ways already familiar to us, independently of any computer or science. We need to think about threads within processes on a given computer, sure, but also about concurrency within our respective knowledge domains, and this idea of many namespaces sharing access to a busy airport, each supporting a point of view, or job description, is going to help with many a future programming challenge. Kirby On Thu, May 22, 2008 at 9:15 AM, Winston Wolff wrote: > Using the post-it note metaphor, it might be better to say: > > x = y is the same as creating a new bookmark called "x" which represents "y" > > -ww > > On May 21, 2008, at 9:13 PM, kirby urner wrote: > >> x = y involves "emailing" an URL from y to x, setting up a second >> alias. Recipient x now has a copy of the same URL as y, but no website >> got copied. > > Winston Wolff > Stratolab - Kids exploring computers, comics, and robots > (646) 827-2242 - http://stratolab.com > > From kirby.urner at gmail.com Fri May 23 19:00:38 2008 From: kirby.urner at gmail.com (kirby urner) Date: Fri, 23 May 2008 10:00:38 -0700 Subject: [Edu-sig] Python for Beginners In-Reply-To: References: <26A3BCEF-454A-4A09-91DB-E91CD7850F0D@stratolab.com> Message-ID: I think in an Intro to Programming course featuring Python or not, it'd make sense to talk a lot about this new use of the equality symbol ( = ) and how language designers have felt about it (suspicious in some cases). In APL, a left pointing arrow was used. PL/1 used := as I recall. What other symbols for "assignment"? Class project, to collect? In math books, they sometimes write out Let x =, which has that imperative flavor, that commanding tone (who is x to fight back anyway, variables so pliable, whereas in CS we have to "allocate memory" meaning the department might give us a budget, at least in the old time share days, getting "an account" i.e. CPU time, was considered a real privilege, so any "x =" is ultimately gonna cost ya, in adding to a namespace (a finite resource)). In any case, there's that big gulf between asserting these two are equal, versus the one on the right giving new information to the one on the left, passing something on, in a specific direction. So what gets passed on? A beginner seeing x = y = z = 8 won't know if that's in Python or what (nor will an expert for that matter, until a context is provided). In Python, x = y = z = 8 says the information on the whereabouts of 8 is trickling through this pipe and collecting in pools z, y, and x respectively. After this transaction, z, y and x have no ongoing relationship with one another. This is true regardless of whether 8 is an integer, or some mutable object *disguised* as an integer (pretty clever disguise, not legal in Python). The model I've been using is: I'm walking the dog, then hand you a leash. Now we both have a leash to the same dog. A problem with this imagery is it keeps you and I in proximity, as "walking the dog" is a "crowding together", something that moves us along the sidewalk, tethered to a four-legged. Post-its also have this problem of needing to be physically connected to things (that's the hallmark of post-its, they stick to stuff). In the shoptalk of mathematicians, both the leash and the post-it analogy imply a "metric" i.e. give us a strong sense of the physical distances involved. The idea of an astronaut floating in space, connected by a long cord to the space station, shuttle, other craft, is a step closer to the imagery we're seeking. Where I ended up earlier is with this idea of a website address, a pointer through the Internet to something with an IP number, similar to a Python memory id number, as in id( x ). We think more clearly only about the topology then, realize right off the bat we have no way of knowing what physical distances might be involved, so best to not imagine them. When I go y = x in Python, it's like x emailing a web address to y. x doesn't lose any information in sending that URL and y may later rebind to something else, but so long as x and y share the same URL, they both look at the same website. They *do not* look at each other however. The assignment operator ( = ) triggers a fleeting ocurrance, an event, a hand-off (except the provider hands off a duplicate -- this is "copy" not "move" (what true beginners are likely familiar with, given at least minimal GUI-based file management experience)). Given we're mostly seasoned programmers in this group, write code for a living, for school, for industry, we might not remember how odd this new use of = might have seemed at first. To a chemistry major, = looks a lot like a double bond. To a mathematician, = might look like an assertion of some eternal relationship. Either way x = y might come across as "static through time" in some way, whereas in many computer languages (I'm not saying all), we're talking about a quick happening, a few nanoseconds or clock cycles, then it's all over. More like mitosis than anything, in that one variable became two. And so on. All that being said, after x = y, x and y *do* have a sameness we can check, in that both now fit the category of "pointing to object X". That's what the "is" operator is for in Python as in x is y (returns True). "==" is for something else again, and triggers the __eq__ rib. We know what == means in the case of integers, string objects, but it's up to the programmer to apply spin for programmer-defined objects, by writing code for that special name (or not -- nothing much is mandatory in Python, which we like). Kirby From pgries at cs.toronto.edu Sat May 24 00:00:36 2008 From: pgries at cs.toronto.edu (Paul Gries) Date: Fri, 23 May 2008 18:00:36 -0400 Subject: [Edu-sig] Python for Beginners In-Reply-To: References: <26A3BCEF-454A-4A09-91DB-E91CD7850F0D@stratolab.com> Message-ID: I give a lecture early on in my CS1 course on assignment and objects and computer memory and so on. I think I enjoy it way more than my students, but it's a fun model to draw on the board and trace a small program with. I start by telling them that writing a program is, ultimately, giving the computer a script to follow, telling it how to manipulate memory and interact with the user. But the computer is pedantic, so you have to be careful what you tell it to do. In order to be careful, you have to have a mental model that corresponds with how the computer actually works. Here's one model that's pretty close; I tell my students that there are lots of other analogies, but that all of them have to match the computer's behavior. Computer memory is like a really long street, with tons and tons of houses, each with its own unique number. A variable is a little piece of paper with a name and an address written on it. A house is a place for storing some data, along with written descriptions of how to do a small set of very specific tasks. In an assignment statement x = y, we copy y's address onto x's sheet of paper. To relate this to Kirby's URL example, you don't even need to know what's in the house at that address in order to do this, or how far away it is. There are lots of different kinds of things you can put into a house: an int value and descriptions of tasks related to that int value; a string value and descriptions of tasks that related to string-related tasks. You can also put variables (pieces of paper each with a name and an address) in a house. You need worker robots to follow the task descriptions. These represent functions that are currently executing. Workers carry around a set of local variables (again, pieces of paper). Workers can summon other workers whenever they need to. Workers can go to a house (on the bus?) and fetch a piece of information, or summon another robot worker to a house to do a task. The worker waits patiently for the task to be finished---they know which worker they're waiting for, which gives us a call stack---and then brings back the result to wherever they came from. Does it work? I think it helps some people. It certainly helps demystify the concept of memory addresses, which lots of new programmers find surprisingly intimidating. Later in the course, I draw the call stack and the heap and talk about real memory addresses; help(id) says "Return the identity of an object. ... (Hint: it's the object's memory address.)". Now we can quiz a variable about which house it points to, which can help them understand the debugger. I also go back to the street analogy when I talk about recursion, and they don't seem to have any trouble with the idea that a robot with a set of instructions can summon another robot to follow the same set of instructions, and the behavior might be different if the second robot's variable values are different from the first. -Paul On 23-May-08, at 13:00 , kirby urner wrote: > I think in an Intro to Programming course featuring Python or not, > it'd make sense to talk a lot about this new use of the equality > symbol ( = ) and how language designers have felt about it (suspicious > in some cases). > > In APL, a left pointing arrow was used. PL/1 used := as I recall. > What other symbols for "assignment"? Class project, to collect? > > In math books, they sometimes write out Let x =, which has that > imperative flavor, that commanding tone (who is x to fight back > anyway, variables so pliable, whereas in CS we have to "allocate > memory" meaning the department might give us a budget, at least in the > old time share days, getting "an account" i.e. CPU time, was > considered a real privilege, so any "x =" is ultimately gonna cost ya, > in adding to a namespace (a finite resource)). > > In any case, there's that big gulf between asserting these two are > equal, versus the one on the right giving new information to the one > on the left, passing something on, in a specific direction. > > So what gets passed on? > > A beginner seeing x = y = z = 8 won't know if that's in Python or what > (nor will an expert for that matter, until a context is provided). > > In Python, x = y = z = 8 says the information on the whereabouts of 8 > is trickling through this pipe and collecting in pools z, y, and x > respectively. > > After this transaction, z, y and x have no ongoing relationship with > one another. This is true regardless of whether 8 is an integer, or > some mutable object *disguised* as an integer (pretty clever disguise, > not legal in Python). > > The model I've been using is: I'm walking the dog, then hand you a > leash. Now we both have a leash to the same dog. > > A problem with this imagery is it keeps you and I in proximity, as > "walking the dog" is a "crowding together", something that moves us > along the sidewalk, tethered to a four-legged. > > Post-its also have this problem of needing to be physically connected > to things (that's the hallmark of post-its, they stick to stuff). > > In the shoptalk of mathematicians, both the leash and the post-it > analogy imply a "metric" i.e. give us a strong sense of the physical > distances involved. > > The idea of an astronaut floating in space, connected by a long cord > to the space station, shuttle, other craft, is a step closer to the > imagery we're seeking. > > Where I ended up earlier is with this idea of a website address, a > pointer through the Internet to something with an IP number, similar > to a Python memory id number, as in id( x ). > > We think more clearly only about the topology then, realize right off > the bat we have no way of knowing what physical distances might be > involved, so best to not imagine them. > > When I go y = x in Python, it's like x emailing a web address to y. x > doesn't lose any information in sending that URL and y may later > rebind to something else, but so long as x and y share the same URL, > they both look at the same website. > > They *do not* look at each other however. The assignment operator ( = > ) triggers a fleeting ocurrance, an event, a hand-off (except the > provider hands off a duplicate -- this is "copy" not "move" (what true > beginners are likely familiar with, given at least minimal GUI-based > file management experience)). > > Given we're mostly seasoned programmers in this group, write code for > a living, for school, for industry, we might not remember how odd this > new use of = might have seemed at first. > > To a chemistry major, = looks a lot like a double bond. > > To a mathematician, = might look like an assertion of some eternal > relationship. > > Either way x = y might come across as "static through time" in some > way, whereas in many computer languages (I'm not saying all), we're > talking about a quick happening, a few nanoseconds or clock cycles, > then it's all over. > > More like mitosis than anything, in that one variable became two. > And so on. > > All that being said, after x = y, x and y *do* have a sameness we can > check, in that both now fit the category of "pointing to object X". > > That's what the "is" operator is for in Python as in x is y (returns > True). > > "==" is for something else again, and triggers the __eq__ rib. > > We know what == means in the case of integers, string objects, but > it's up to the programmer to apply spin for programmer-defined > objects, by writing code for that special name (or not -- nothing much > is mandatory in Python, which we like). > > Kirby > _______________________________________________ > Edu-sig mailing list > Edu-sig at python.org > http://mail.python.org/mailman/listinfo/edu-sig From jjposner at snet.net Sat May 24 19:29:13 2008 From: jjposner at snet.net (John Posner) Date: Sat, 24 May 2008 13:29:13 -0400 Subject: [Edu-sig] Python for Beginners In-Reply-To: References: Message-ID: <001001c8bdc3$af2614c0$65bda8c0@jposner> > > I think in an Intro to Programming course featuring Python or > not, it'd make sense to talk a lot ... I suggest talking a little, not a lot. Your note about "Let" is good. How about just a short explanation that in algebra (the context in which most students are likely to have encountered the concept of a variable), we make *declarations of truth*: x = 12 + y the value of x IS EQUAL TO the value of the expression "12 + y" ... whereas in computer programming, we *give instructions* to the computer: x = 12 + y LET the value of x BE EQUAL TO the value of the expression "12 + y" > ... about this new use of the > equality symbol ( = ) and how language designers have felt > about it (suspicious in some cases). I suspect that students in an Intro to Programming course couldn't care less about what the language designers thought. Language comparison in an intro course is more likely to be confusing than enlightening. How many high schools teach French and Spanish in the same course? > Post-its also have this problem of needing to be physically > connected to things (that's the hallmark of post-its, they > stick to stuff). You can't convince me that John Zelle's sticky note metaphor is anything other than *fabulous*: they're different from objects, but are attached to objects; they can be easily removed from one object and attached to another; they can be destroyed without affecting the objects to which they were attached. My only complaint is that John doesn't use the metaphor *more* in his textbook! :-) > When I go y = x in Python, it's like x emailing a web address > to y. Um, it's *way* more like attaching a sticky note to a physical object. > (what true beginners are likely familiar with, given > at least minimal GUI-based file management experience) That's a "true beginner"? > Either way x = y might come across as "static through time" > in some way, whereas in many computer languages (I'm not > saying all), we're talking about a quick happening, a few > nanoseconds or clock cycles, then it's all over. Nope, the sticky note remains attached to the object for a considerable period -- until it's removed from that object and placed on another one. [ ... or until the naming scope disappears. John Zelle, do you include this situation in your sticky-note metaphor? Could sticky notes *of a particular color* or "with a particular shape* indicate the names in a particular scope? ] -John Posner From kirby.urner at gmail.com Sun May 25 00:11:07 2008 From: kirby.urner at gmail.com (kirby urner) Date: Sat, 24 May 2008 15:11:07 -0700 Subject: [Edu-sig] Python for Beginners In-Reply-To: <001001c8bdc3$af2614c0$65bda8c0@jposner> References: <001001c8bdc3$af2614c0$65bda8c0@jposner> Message-ID: On Sat, May 24, 2008 at 10:29 AM, John Posner wrote: >> >> I think in an Intro to Programming course featuring Python or >> not, it'd make sense to talk a lot ... > > I suggest talking a little, not a lot. Your note about "Let" is good. How > about just a short explanation that in algebra (the context in which most > students are likely to have encountered the concept of a variable), we make > *declarations of truth*: My style drives some students crazy so I hope my reputation precedes me, such that those wanting less "flitting about" feel forewarned and pre-filtered. Sometimes I believe in YouTubes doing the talking, or something similar, i.e. I like those "soothing voice" animations that just take you through it, "assignment through the ages" or something like that. 10 minutes should about cover it, except we might want to sample alternatives (film majors). 'Warriors of the Net' a good example, for teaching about TCP/IP to newcomers. Of course I think everyone should know about TCP/IP, so make sure to include that if I think students might need it (OK, at Intel they mostly don't, but I'm a Saturday Academy instructor these days, only see Intel people at PORPIG meetups and like that, hi Dylan). > x = 12 + y > the value of x IS EQUAL TO the value of the expression "12 + y" Yes, more like x == (12 + y) in Python (with parens for clarity). > > ... whereas in computer programming, we *give instructions* to the computer: > > x = 12 + y > LET the value of x BE EQUAL TO the value of the expression "12 + y" Except we also have "x == y" and "x is y" in Python, with "x == y" mapping to a __rib__ in x (optionally absent in the more general case), i.e. x == y calls x.__eq__(y) http://docs.python.org/ref/customization.html This is worth mentioning as that leaves the door open to "==" meaning something quite alien, in the hands of a perverse programmer, whereas "=" (assignment) and "is" (memory id comparison) are much more hard-wired. > >> ... about this new use of the >> equality symbol ( = ) and how language designers have felt >> about it (suspicious in some cases). > > I suspect that students in an Intro to Programming course couldn't care less > about what the language designers thought. Language comparison in an intro Well, if this were Princeton, the profs couldn't care less what students thought, as the profs were the experts and thought we all needed Assembler, FORTRAN, PL/1, SNOBOL, APL and a little LISP, all in the same intro course. I liked APL best, and continue to like J (a next incarnation), given my druthers would mix a little J teaching with my Python teaching, just to remind students of the big playing field they're playing in. [ I need more time learning from J teachers though -- not an O'Reilly langauge, so nothing in Safari ] The LEX Institute in Japan an influence here, in persuading me to not get too mono-lingual. > course is more likely to be confusing than enlightening. How many high > schools teach French and Spanish in the same course? Cite LEX again. Not saying everyone should do it my way, or that your way is wrong. We each cultivate a style -- like circus acts. Very boring if everyone is a clown. I'm sure a few Intro to Programming teachers besides me still take a multi-language approach. In that case, it's not a course goal to be blackbelt in any one language when finished. It's just a survey course. Lots of eye-candy up front, a best foot forward kind of thing. Physics uses the same techniques, the Intro course featuring lots of demos, falling stuffed monkeys shot by projectiles with parabolic trajectories, woo hoo. At Princeton a lot of us were liberal arts majors, making a pilgrimage to the far Equad out of curiosity, not out of obeisance. The profs knew this might be our one and only exposure and didn't want us to leave without overview. That's what Intro courses tend to be good for: recruit a lot of non-majors and don't disappoint them, plus find the few who want to go deeper (I stuck around for more, shifted more to computers later, via McGraw-Hill, home of Byte Magazine). >> Post-its also have this problem of needing to be physically >> connected to things (that's the hallmark of post-its, they >> stick to stuff). > > You can't convince me that John Zelle's sticky note metaphor is anything > other than *fabulous*: they're different from objects, but are attached to > objects; they can be easily removed from one object and attached to another; > they can be destroyed without affecting the objects to which they were > attached. I'm fine with *fabulous*. I think in a textbook you don't want too many metaphors flying around. I'm more oral tradition / cartoonist and apply many metaphors thick and fast, with an eye toward building up that more generic impression, of names on the one hand (organized namespaces), memory and/or math objects on the other, with name : object relationships the glue, like key : value pairs in a Python dictionary. > My only complaint is that John doesn't use the metaphor *more* in his > textbook! :-) > Yes, sometimes one wishes more graphical content in general, and metaphors like post-its are valuable in that way. But the trade off between graphics and words is a fine tuning, depends on what kind of book. O'Reilly's 'Head First' series is a different style, the 'Dragonology'... 'Wizardology' series yet different again. My style of teaching CS concepts is more Narnia than Bourbaki, with post-its somewhere on the spectrum. >> When I go y = x in Python, it's like x emailing a web address >> to y. > > Um, it's *way* more like attaching a sticky note to a physical object. Per your point with the post-its, I think we agree that a main thing to get is "del y" removes the *name* y from the namespace. Deallocation of memory objects is more rightly the job of the garbage collector. "del y" impacts the referenced PyObject in that the latter's name counter goes down. >> (what true beginners are likely familiar with, given >> at least minimal GUI-based file management experience) > > That's a "true beginner"? Yes, in this day and age, a beginner has probably used a computer since early childhood, likely has dragged and dropped files with the mouse for years prior to any programming class. The move and copy options are probably as engrained from the menus, as salt and pepper or chocolate and vanilla in a goodly portion of today's student body. When we go x = y, x and y dock for a sec, and a payload goes from y to x, like an URL, or a remote, a controller. The copy is likewise disposable, and y will not ask for it back, or shouldn't have to, because y keeps its own copy, it's own relationship with that snake-like thing with __ribs__ (the number 8 for example). > >> Either way x = y might come across as "static through time" >> in some way, whereas in many computer languages (I'm not >> saying all), we're talking about a quick happening, a few >> nanoseconds or clock cycles, then it's all over. > > Nope, the sticky note remains attached to the object for a considerable > period -- until it's removed from that object and placed on another one. But x and y have no lasting relationship. For a split second, they're coupled, in that x needs a copy of y's URL, the pointer to the object. Then they go their separate ways *immediately*. Going "del x" doesn't create any ripples for "y" or vice versa, except insofar as the shared object registers the change. I think it's second nature to think this way in programming, because we're thinking "instructions in sequence". But in a math book it's not always so clear what the time scope might be, or even if there is one. Mathematicians get more slack, don't have to garbage collect so assiduously. > [ ... or until the naming scope disappears. John Zelle, do you include this > situation in your sticky-note metaphor? Could sticky notes *of a particular > color* or "with a particular shape* indicate the names in a particular > scope? ] > > -John Posner > > Kirby From jjposner at snet.net Sun May 25 19:58:24 2008 From: jjposner at snet.net (John Posner) Date: Sun, 25 May 2008 13:58:24 -0400 Subject: [Edu-sig] Python for Beginners In-Reply-To: References: Message-ID: <001801c8be90$ed84ca90$65bda8c0@jposner> Comments on Kirby's comments ... > Except we also have "x == y" and "x is y" in Python, with "x > == y" mapping to a __rib__ in x (optionally absent in the > more general case), i.e. > x == y calls x.__eq__(y) > http://docs.python.org/ref/customization.html > > This is worth mentioning as that leaves the door open to "==" > meaning something quite alien, in the hands of a perverse > programmer, whereas "=" (assignment) and "is" (memory id > comparison) are much more hard-wired. I wouldn't mention the fact that the "==" operator can be "corrupted" by an incorrect/mischievous definition of the __eq__ method, any more than I'd mention that "*" can get similar treatment with a definition of __mul__. This is *way* beyond Python for Beginners, IMHO. > Deallocation of memory objects is more rightly the job of the > garbage collector. "del y" impacts the referenced PyObject > in that the latter's name counter goes down. Yup, "del y" operates on the name (remove the sticky note from the object, then throw away the sticky note). The important thing for beginners to know is that if an object has zero names (sticky notes), there's no way to refer to it. It's as good as gone. The fact that some background process might delete the no-name object from memory is not something beginners would, or should, care about. > When we go x = y, x and y dock for a sec, and a payload goes > from y to x, like an URL, or a remote, a controller. > > The copy is likewise disposable, and y will not ask for it > back, or shouldn't have to, because y keeps its own copy, > it's own relationship with that snake-like thing with > __ribs__ (the number 8 for example). Hmmm ... "x and y dock for a sec" could lead a beginner to believe that "y" refers to "x", rather than "y" refers to the same object that "x" refers to. I have nothing against Internet-oriented metaphors, as long as they help the beginner to learn the way in which the language *actually* works. How about this: On the Web, you can buy a product directly from the manufacturer, using the manufacturer's product code. Or you can buy it from Amazon, which has its own product code. There's only one product, but it can have two (or more) identifiers that enable you to access it. > But x and y have no lasting relationship. For a split > second, they're coupled, in that x needs a copy of y's URL, > the pointer to the object. Then they go their separate ways > *immediately*. I'd rather say that the names "x" and "y" have no relationship at all. Each of them happens to have a relationship with the same object. -John Posner From kirby.urner at gmail.com Sun May 25 21:17:00 2008 From: kirby.urner at gmail.com (kirby urner) Date: Sun, 25 May 2008 12:17:00 -0700 Subject: [Edu-sig] Python for Beginners In-Reply-To: <001801c8be90$ed84ca90$65bda8c0@jposner> References: <001801c8be90$ed84ca90$65bda8c0@jposner> Message-ID: On Sun, May 25, 2008 at 10:58 AM, John Posner wrote: > I wouldn't mention the fact that the "==" operator can be "corrupted" by an > incorrect/mischievous definition of the __eq__ method, any more than I'd > mention that "*" can get similar treatment with a definition of __mul__. > This is *way* beyond Python for Beginners, IMHO. Right, got it. But my beginning math teachers get to operator overloading within the first 20 minutes, because we're using Python to motivate some insights in elementary group theory, what we're using to replace overbuilt sections of calculus in some flagship charter high schools. I spell it all out in my Chicago talk (Pycon 2008 channel on YouTube). Just last Saturday we were overloading __add__ in my Dog class, having some "Dog %s loves %s" % (self, other) syntax going. These were beginners of another type (not my gnu math teachers), but there's really nothing mysterious about __ribs__ if you've gone dir(8) since day one (which we obviously have, given my interactive, projected approach). So yes, it took a lot more than 20 minutes in this case (wrote up each session in my blog, in case others want to steal my ideas). > >> Deallocation of memory objects is more rightly the job of the >> garbage collector. "del y" impacts the referenced PyObject >> in that the latter's name counter goes down. > > Yup, "del y" operates on the name (remove the sticky note from the object, > then throw away the sticky note). The important thing for beginners to know > is that if an object has zero names (sticky notes), there's no way to refer > to it. It's as good as gone. The fact that some background process might > delete the no-name object from memory is not something beginners would, or > should, care about. Right, as long as by "zero names" you're ruling out any pointers to pointers through a data structure, which are anonymous from another angle (the structure itself has a name, but the objects may be like Rod(color="Red"), with color choosing the length behind the scenes. d = {"red":Rod()} is then a string literal mapped to an object, *like* a top-level name, but not. d is the top-level name in this namespace. Rod( ) in a sense has no name, is a call to a constructor that returned on object captured within a dictionary. So it won't be garbage collected, as it knows there's this pointer for some reason (for what reason the object will have no clue). >> When we go x = y, x and y dock for a sec, and a payload goes >> from y to x, like an URL, or a remote, a controller. >> >> The copy is likewise disposable, and y will not ask for it >> back, or shouldn't have to, because y keeps its own copy, >> it's own relationship with that snake-like thing with >> __ribs__ (the number 8 for example). > > Hmmm ... "x and y dock for a sec" could lead a beginner to believe that "y" > refers to "x", rather than "y" refers to the same object that "x" refers to. > > I have nothing against Internet-oriented metaphors, as long as they help the > beginner to learn the way in which the language *actually* works. Not sure if you're confusing semantic model with implementation model (the latter frequently uninteresting to practicing biologists). > How about > this: > > On the Web, you can buy a product directly from the manufacturer, using > the manufacturer's product code. Or you can buy it from Amazon, which > has its own product code. There's only one product, but it can have two > (or more) identifiers that enable you to access it. > >> But x and y have no lasting relationship. For a split >> second, they're coupled, in that x needs a copy of y's URL, >> the pointer to the object. Then they go their separate ways >> *immediately*. > > I'd rather say that the names "x" and "y" have no relationship at all. Each > of them happens to have a relationship with the same object. > > -John Posner I'd agree, except before x learns y's secret, only y knows it. x = y is not a symmetric situation. y on the right "knows something" that x is "now learning", after which point in the program "x now knows". So I think it's OK to have this idea of y whispering something to x, then a parting of ways. Kirby From jjposner at snet.net Mon May 26 15:28:18 2008 From: jjposner at snet.net (John Posner) Date: Mon, 26 May 2008 09:28:18 -0400 Subject: [Edu-sig] Python for Beginners In-Reply-To: References: Message-ID: <001801c8bf34$5c51abc0$65bda8c0@jposner> > > Right, as long as by "zero names" you're ruling out any > pointers to pointers through a data structure, ... Are you referring to this situation: IDLE 1.2.1 >>> import sys >>> a = 'this is a really unique value' >>> sys.getrefcount(a) 2 >>> dict01 = { 'first' : a, 'second' : 2 } >>> sys.getrefcount(a) 3 >>> dict02 = { 'uno' : a, 'dos' : 222 } >>> sys.getrefcount(a) 4 > ... which are > anonymous from another angle (the structure itself has a > name, but the objects may be like Rod(color="Red"), with > color choosing the length behind the scenes. d = > {"red":Rod()} is then a string literal mapped to an object, > *like* a top-level name, but not. d is the top-level name in > this namespace. Rod( ) in a sense has no name, is a call to > a constructor that returned on object captured within a > dictionary. So it won't be garbage collected, as it knows > there's this pointer for some reason (for what reason the > object will have no clue). "Rod() in a sense has no name" ?? Doesn't the Rod object get the name "red" in *almost exactly* the same way in these two cases? Case #1: >>> red = Rod() Case #2: >>> d = { "red" : Rod() } In Case #1, the name "red" is created in the local (or maybe global) namespace. In Case #2, the name "red" is created in the namespace of a dictionary object. In the sticky-note metaphor: a dictionary object is just a collection of sticky-notes -John Posner From kirby.urner at gmail.com Mon May 26 18:14:37 2008 From: kirby.urner at gmail.com (kirby urner) Date: Mon, 26 May 2008 09:14:37 -0700 Subject: [Edu-sig] Python for Beginners In-Reply-To: <001801c8bf34$5c51abc0$65bda8c0@jposner> References: <001801c8bf34$5c51abc0$65bda8c0@jposner> Message-ID: << SNIP >> > a dictionary object is just a collection of sticky-notes > > > -John Posner > > One program I've been meaning to write, but haven't gotten to yet, creates arbitrarily deep, legal data structures, with "easter egg" or "treasure" randomly buried. The output would be such as: puzzle = {1:[{},([],'a')],(0,):["X"]} -- except it might go on for several pages of nesting. In this case, the object is to name 'X' and the solution is easy: >>> puzzle[(0,)][0] 'X' One point of this exercise is to help students construct a mental model of pointers to pointers, much as C students do (in their different semantic model of what "pointer" means). Kirby