function-arguments by reference

E

EsC

Hy!

is it possible to pass function-arguments by reference?
(for example in PHP you can use the "&" operator ... )

thx
iolo
 
P

Paul Rubin

EsC said:
is it possible to pass function-arguments by reference?
(for example in PHP you can use the "&" operator ... )

No. If there's a specific situation you want to handle, say what it
is and someone will say how to deal with it in Python. For example if
you want a function that returns multiple values, just return a list:

def get_three_nums ():
return (2, 3, 5)

a, b, c = get_three_nums ()

sets a=2, b=3, and c=5. You don't have to do anything kludgy like
"get_three_nums (&a, &b, &c)" or whatever. If you want to swap two
variables, you can just use a list assignment like in perl:

(x, y) = (y, x)
 
C

Christos TZOTZIOY Georgiou

Hy!

is it possible to pass function-arguments by reference?
(for example in PHP you can use the "&" operator ... )

thx
iolo

There is no such concept as "pass by value" in python. Only references
are passed around, and therefore there is no special syntax for that.

What you need to understand is that objects can be mutable (changeable)
or immutable. Search for these terms in the python documentation.

In other languages, variables are a container: they contain a "value".
In python, "variables" are only "names" referring to "objects" and they
have no "value". If you assign anything to a name, you just change the
object it is pointing to.

Presumably you ask this question because you want your function to pass
back some more data than its return value. Python handles fine multiple
values, check for "tuple" in the docs.

An example: (I am not familiar with php, therefore I will write program
A in pseudocode, but you will get the point I hope)

function f(&a):
if (a > 10) then a = 10
return (a*2)

var = 20
result = f(var)

This function makes sure that the "var" variable stays less than or
equal to 10, and then returns the double of the corrected argument.

In python you would do this:

def f(a):
if a > 10:
a = 10
return a, a*2

var = 20
var, result = f(var)

If not covered, please write back.

PS reading this could be helpful too:
http://www.effbot.org/zone/python-objects.htm
 
E

EsC

hy!

thanks for your explanations!

i want to avoid performance-problems by repeated (very often)
function-calls with very long strings.
in some languages (C, PHP, Powerbuilder, ...) i have the opportunity,
to pass "by value" or "by reference/pointer)".

"by value": the CPU must perform a complete copy of the string
"by reference/pointer": only a long value (address) is passed ...
the performance difference is in most cases unimportant, but sometimes ...

Unfortunately i made an error by testing the behavior of Phyton, and
so i thougt, LISTs are also passed "by value".
But this isn't true, and so i can solve my problem by putting the string-
argument in the first place of a list.

greetings
iolo
 
J

JCM

EsC said:
thanks for your explanations!
i want to avoid performance-problems by repeated (very often)
function-calls with very long strings.
in some languages (C, PHP, Powerbuilder, ...) i have the opportunity,
to pass "by value" or "by reference/pointer)".

The text of the string is not copied; a reference to the string/object
is passed into the function. You can modify objects passed into
functions (but only if they're mutable--strings and integers are
examples of immutable objects), but you cannot rebind the variable
holding the value in the caller's scope.

There have been some discussions in this newsgroup about whether
Python is call-by-value or not. I'm not sure if I want to recommend
looking for them; there was no good consensus about the terminology.
 
E

EsC

hy JCM!

damned - you are right!
i didn't know the way Python is handling arguments
up to now! It's a little bit different to other languages
i know - and somtimes even a little bit easier.

i made some (useless) performance-tests to proof your exclamations ...
if somebody is interested: i enclosed the code and results ...

- String 1 & String2: only read-access within the called function
the runtime is almost identical; therefore the text of the string can't
be copied
- String 3: the argument string is modified but NOT passed back to
the caller;
- String 4: the argument string is passed "by reference" within a
list object and modified.

i think this informations are very interesting
thanks!

greetings
iolo


------------ CODE -------------
import sys
from string import *
from time import *

def ls(str):
return len(str)

def ll(str):
return len(str[0])

def as(str):
str += "x"
return len( str )

def al(str):
str[0] += "x"
return len( str[0] )

loop = 2000
strlen = 30000
strl = []
strl.append("")
strs = ""

for a in range(strlen):
strs += 'x'
strl[0] += 'y'

print "Loop: ", loop
print "Stringlength: " , strlen

print
print 'String 1'
l = 0
start = time()
for x in range(loop):
l += ls(strs)
end = time()
print "duration in seconds: ", end - start
print "result: ", l
if strlen == l / loop:
print 'OK'
else:
print 'ERROR'

print
print 'String 2'
l = 0
start = time()
for x in range(loop):
l += ll(strl)
end = time()
print "duration in seconds: ", end - start
print "result: ", l
if strlen == l / loop:
print 'OK'
else:
print 'ERROR'

print
print 'String 3'
l = 0
start = time()
for x in range(loop):
l += as(strs)
end = time()
print "duration in seconds: ", end - start
print "result: ", l
if l == loop * strlen + loop:
print 'OK'
else:
print 'ERROR'

print
print 'String 4'
l = 0
start = time()
for x in range(loop):
l += al(strl)
end = time()
print "duration in seconds: ", end - start
print "result: ", l
if l == (loop / 2 ) * ((strlen + 1) + (strlen + loop)):
print 'OK'
else:
print 'ERROR'

---------------- RESULT ----------------
Loop: 50000
Stringlength: 200000

String 1
duration in seconds: 0.0620000362396
result: 10000000000
OK

String 2
duration in seconds: 0.0779999494553
result: 10000000000
OK

String 3
duration in seconds: 3.2349998951
result: 10000050000
OK

String 4
duration in seconds: 5.93700003624
result: 11250025000
OK
--------------------------------------------------
 
M

Matt Goodall

EsC said:
hy JCM!

damned - you are right!
i didn't know the way Python is handling arguments
up to now! It's a little bit different to other languages
i know - and somtimes even a little bit easier.

i made some (useless) performance-tests to proof your exclamations ...
if somebody is interested: i enclosed the code and results ...

- String 1 & String2: only read-access within the called function
the runtime is almost identical; therefore the text of the string can't
be copied
I don't think your test code proves that the string is not copied, only
that passing a reference to a string takes approximately the same amount
of time as passing a reference to a list and accessing the 1st item.

A better "proof" that the string is not copied is:
... print s1 is s2
...
The "True" result indicates that both s1 and s2 are bound to the same
string object.
- String 3: the argument string is modified but NOT passed back to
the caller;
- String 4: the argument string is passed "by reference" within a
list object and modified.

i think this informations are very interesting
thanks!

greetings
iolo


------------ CODE -------------
import sys
from string import *
from time import *

def ls(str):
return len(str)

def ll(str):
return len(str[0])

def as(str):
str += "x"
return len( str )

def al(str):
str[0] += "x"
return len( str[0] )

loop = 2000
strlen = 30000
strl = []
strl.append("")
strs = ""

for a in range(strlen):
strs += 'x'
strl[0] += 'y'

print "Loop: ", loop
print "Stringlength: " , strlen

print
print 'String 1'
l = 0
start = time()
for x in range(loop):
l += ls(strs)
end = time()
print "duration in seconds: ", end - start
print "result: ", l
if strlen == l / loop:
print 'OK'
else:
print 'ERROR'

print
print 'String 2'
l = 0
start = time()
for x in range(loop):
l += ll(strl)
end = time()
print "duration in seconds: ", end - start
print "result: ", l
if strlen == l / loop:
print 'OK'
else:
print 'ERROR'

print
print 'String 3'
l = 0
start = time()
for x in range(loop):
l += as(strs)
end = time()
print "duration in seconds: ", end - start
print "result: ", l
if l == loop * strlen + loop:
print 'OK'
else:
print 'ERROR'

print
print 'String 4'
l = 0
start = time()
for x in range(loop):
l += al(strl)
end = time()
print "duration in seconds: ", end - start
print "result: ", l
if l == (loop / 2 ) * ((strlen + 1) + (strlen + loop)):
print 'OK'
else:
print 'ERROR'

---------------- RESULT ----------------
Loop: 50000
Stringlength: 200000

String 1
duration in seconds: 0.0620000362396
result: 10000000000
OK

String 2
duration in seconds: 0.0779999494553
result: 10000000000
OK

String 3
duration in seconds: 3.2349998951
result: 10000050000
OK

String 4
duration in seconds: 5.93700003624
result: 11250025000
OK
--------------------------------------------------


The text of the string is not copied; a reference to the string/object
is passed into the function. You can modify objects passed into
functions (but only if they're mutable--strings and integers are
examples of immutable objects), but you cannot rebind the variable
holding the value in the caller's scope.

There have been some discussions in this newsgroup about whether
Python is call-by-value or not. I'm not sure if I want to recommend
looking for them; there was no good consensus about the terminology.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,173
Messages
2,570,939
Members
47,484
Latest member
JackRichard

Latest Threads

Top