Public Group

# Python question: Default Pass by reference, or value?

This topic is 4484 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I have been working on programming a game entirely in python, using pygame, in an attempt to learn python (I already know c++). I have run into a problem with a recursive function I wrote (pathfinding). Basically, it seems to me that the variables are passing by reference, instead of by value (as is the default in c++). As you can imagine, this is causing problems since I wrote the function assuming that pass by value was the default. Is the default indeed pass by reference? And if so, is there any way to pass by value? Otherwise, I'm going to need a messy work-around for the function (as if my code isn't messy enough) Thanks in advance

##### Share on other sites
It's a little more complicated - see the fairly involved discussion on the Python mailing list. It's similar to pass-by-reference semantics, but more involved that that. The discussion linked has a decent explanation.

Personally, I haven't used the language enough to know if there's a way to force copy semantics when passing arguments to a function; I'm sure someone else can answer that half, though [smile]

##### Share on other sites
Quote:
 Original post by PimpWillyIs the default indeed pass by reference? And if so, is there any way to pass by value?

It's pass by reference, but assignment is not overwriting but is rebinding. So although you get a reference in the called function, if you assign to that object, it won't affect the original object. However, if you modify that object, it does affect the original.

Basically, if you want a copy, make a copy. This might involve the copy module, or whatever it's called. Generally, it's actually very rare that you actually do need to make that copy. I've never used that module myself. You can probably express the problem in a different way that doesn't require a copy.

##### Share on other sites
As far as argument passing goes, the only available Python way is pass-by-value. All Python variables are references to objects of course, but they themselves are not passed by reference. It's clearly references that are passed by value. Don't confuse passing by reference and passing a reference.

##### Share on other sites
You're blurring the 2 concepts beyond the point of usefulness however. It's exactly the same in C or C++, or Java - the called function ends up with a copy of the reference or the pointer. At the low level it's copying a value which represents a memory location, but in language terms it's still "pass by reference" because changes made to an argument in the called function are reflected in the corresponding object in the calling function.

##### Share on other sites
Quote:
 Original post by KylotanYou're blurring the 2 concepts beyond the point of usefulness however. It's exactly the same in C or C++, or Java - the called function ends up with a copy of the reference or the pointer. At the low level it's copying a value which represents a memory location, but in language terms it's still "pass by reference" because changes made to an argument in the called function are reflected in the corresponding object in the calling function.

Not at all. Consider this simple Python function that gets an angle and returns both the sine and the cosine, ie it needs to return 2 values:

import mathdef sin_cos(angle,sin,cos):  sin=math.sin(angle);  cos=math.cos(angle);angle=45.0;sin=None;cos=None;sin_cos(angle,sin,cos);print "The sine of ",angle,"is: ",sinprint "The sine of ",angle,"is: ",cos

Claiming that Python uses pass-by-reference would be a big mistake, as the programmer would naturally expect the above code to work just as it works with C++(where references are regularly used to for multiple return values). He must realize the difference between pass-by-reference and pass-by-value of a reference and use the correct way to do this, that is return a tuple that contains both results.

See this for a couple of more ways to emulate pass-by-reference in Python, although most of them are overcomplicating things and most probably can be avoided.

[Edited by - mikeman on July 3, 2006 2:12:37 PM]

##### Share on other sites
It's passing references by value, in the same way that Java does, except that Python doesn't have any "primitives" - everything is an object, including "ints".

If you need to copy (clone) things, then do so, with the copy module. However, you normally should be trying to write things in such a way that you don't need to do this.

I don't suppose you could show the code in question? :s

##### Share on other sites
I'll go ahead and post the path function. Might be a bit convuluted, but eh, here it goes:

Note: I tried changing leftData to self.leftData, to see if that would help the problem, but it didn't seem to do the trick. so thats why it's referenced different right now
        def findPath(self, currentData, currentSquare, destinationSquare, movementLeft):        #subtract current tile movement cost from movement spaces left        #         check if movement cost < 0.	#	 If so, I cant get here, so append with a -1 and return it        #print "Updating Data for debug:", currentData        tileInfo = self.getTile(currentSquare[0], currentSquare[1])        currentTileMovementCosts = self.mapKey.getMovementCost(tileInfo)        print "         TileCosts:", currentTileMovementCosts        if movementLeft < 0:            currentData[0] = -1            return currentData        #Check if I am on the destination square        if currentSquare == destinationSquare:            print "Found the dest square, returning data ->", currentData            return currentData        else:            currentData[0] += currentTileMovementCosts            movementLeft -= currentTileMovementCosts        self.leftData = currentData	self.leftData.append('L')	tempSquare = currentSquare	tempSquare[0] -= 1	self.leftData = self.findPath(self.leftData, tempSquare, destinationSquare, movementLeft)	upData = currentData	upData.append('U')	tempSquare = currentSquare	tempSquare[1] -= 1	upData = self.findPath(upData, tempSquare, destinationSquare, movementLeft)	rightData = currentData	rightData.append('R')	tempSquare = currentSquare	tempSquare[0] += 1	rightData = self.findPath(rightData, tempSquare, destinationSquare, movementLeft)	downData = currentData	downData.append('D')	tempSquare = currentSquare	tempSquare[1] += 1	downData = self.findPath(downData, tempSquare, destinationSquare, movementLeft)	 	#Find which path is >0 and which has the lowest movement costs        #print "all data:", self.leftData	if upData[0] >= 0:		lowestData = upData	elif rightData[0] >= 0:		lowestData = rightData	elif self.leftData[0] >= 0:                print "@@@@@@@@@@@@@Left Data", self.leftData		lowestData = rightData	elif downData[0] >= 0:		lowestData = downData	else:		#no paths found		# set currentData[0] to -1 and return		currentData[0] = -1		#print "Path not found"		return currentData        print "!!!!!!!!!!!!!!!!!!!!!!!!!!Left Data,", self.leftData        if upData[0] > 0 and upData[0] < lowestData[0]:		lowestData = upData	if rightData[0] > 0 and rightData[0] < lowestData[0]:		lowestData = rightData	if self.leftData[0] > 0 and self.leftData[0] < lowestData[0]:                print "#####################Left Data", self.leftData		lowestData = leftData	if downtData[0] > 0 and downData[0] < lowestData[0]:		lowestData = downData	#now return our shortest path	print " Path found, heres data ->", lowestData	return lowestData

As the algorithm runs, it ends up just adding a whole lot of data to leftData, rightData,upData,downData, and currentData, so that when it finally returns with what I hoped would be the shortest path, it ends up just being a path with like 60+ moves (even for just one square over)

##### Share on other sites
Just an update, but I haven't had any luck so far. Looks like I am going to have to go ahead and just create a temp variable before each recursion call, then re-assign it after it returns, unless anybody has any better alternatives?

Thanks,

--Steve

##### Share on other sites
I'm having a hard time parsing your code. Could you post your algorithm alone?

Also, take a look at shortest path implementations in Python (Dijkstra, A*).

1. 1
2. 2
3. 3
Rutin
22
4. 4
5. 5

• 13
• 19
• 14
• 9
• 9
• ### Forum Statistics

• Total Topics
632930
• Total Posts
3009290
• ### Who's Online (See full list)

There are no registered users currently online

×