473,326 Members | 2,125 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,326 software developers and data experts.

Mutability of function arguments?

I'm trying to create a function that can take arguments, say, foo and
bar, and modify the original copies of foo and bar as well as its local
versions -- the equivalent of C++ funct(&foo, &bar).

I've looked around on this newsgroup and elsewhere, and I gather that
this is a very common concern in Python, but one which is ordinarily
answered with "No, you can't. Neat, huh?" A few websites, newsgroup
posts, etc. have recommended that one ask for a more "Pythonic" way of
doing things; so, is there one, or at least one that doesn't involve
using objects as wrappers for mutable arguments?

And, indeed, would that approach work? Would declaring:

class FooWrapper :
__init__(fooToLoad) :
self.foo = fooToLoad

mean that I could now declare a FooWrapper holding a foo, pass the
FooWrapper to a function, and have the function conclude with the foo
within the FooWrapper now modified?

Thanks in advance for everyone's time; I hope I'm comprehensible.

Dec 8 '05 #1
17 2016
(Re. mutability question:)

Update, never mind. I found that the FooWrapper solution isn't so bad
after all -- and even better is putting the variable in question in a
different module entirely.

However, anyone who wants to answer the question is still welcome to.
Sorry to be a bother, and to have posted before I thought... :)

Dec 8 '05 #2
"ex_ottoyuhr" <ex*********@hotmail.com> writes:
I'm trying to create a function that can take arguments, say, foo and
bar, and modify the original copies of foo and bar as well as its local
versions -- the equivalent of C++ funct(&foo, &bar).
C++'s '&' causes an argument to be passed by reference. Python does
that with all arguments. Any changes you make to the argument in the
function will be seen in the caller unless you explicitly make a copy
to pass.
I've looked around on this newsgroup and elsewhere, and I gather that
this is a very common concern in Python, but one which is ordinarily
answered with "No, you can't. Neat, huh?" A few websites, newsgroup
posts, etc. have recommended that one ask for a more "Pythonic" way of
doing things; so, is there one, or at least one that doesn't involve
using objects as wrappers for mutable arguments?
If your arguments are mutable, you don't need to do anything to be
able to change them - just call the mutator methods. If your arguments
aren't mutable, then you can't change them, either in the function or
in the original namespace.

If what you really want to do is rebind a variable in the calling
namespace - well, you can't do that. The standard way to deal with the
usual uses for passing references in C is to return the value (or
values - Python handles multi-valued return and assignment much
cleaner than C++) and rebind the variables at the point of the call.

If you insist on writing C/C++ in Python, you can wrap an immutable
object in an instance of class with a method to let you change it, as
you suggest:
And, indeed, would that approach work? Would declaring:
class FooWrapper :
__init__(fooToLoad) :
self.foo = fooToLoad mean that I could now declare a FooWrapper holding a foo, pass the
FooWrapper to a function, and have the function conclude with the foo
within the FooWrapper now modified?


If you like an extended lambda calculus syntax, you can use my Ref
class: http://aspn.activestate.com/ASPN/Coo.../Recipe/456150.

<mike
--
Mike Meyer <mw*@mired.org> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
Dec 8 '05 #3
"ex_ottoyuhr" <ex*********@hotmail.com> wrote in message
news:11*********************@z14g2000cwz.googlegro ups.com...
I'm trying to create a function that can take arguments, say, foo and
bar, and modify the original copies of foo and bar as well as its local
versions -- the equivalent of C++ funct(&foo, &bar).

I've looked around on this newsgroup and elsewhere, and I gather that
this is a very common concern in Python, but one which is ordinarily
answered with "No, you can't. Neat, huh?" A few websites, newsgroup
posts, etc. have recommended that one ask for a more "Pythonic" way of
doing things; so, is there one, or at least one that doesn't involve
using objects as wrappers for mutable arguments?

And, indeed, would that approach work? Would declaring:

class FooWrapper :
__init__(fooToLoad) :
self.foo = fooToLoad

mean that I could now declare a FooWrapper holding a foo, pass the
FooWrapper to a function, and have the function conclude with the foo
within the FooWrapper now modified?

Thanks in advance for everyone's time; I hope I'm comprehensible.


Python isn't C++ and there is no need to return multiple values by modifying
function parameters:
def funct(a,b): .... return a+1,b+1
.... foo,bar=1,2
print foo,bar 2 3 foo,bar=funct(foo,bar)
print foo,bar 3 4


-Mark
Dec 8 '05 #4

Mike Meyer wrote:
"ex_ottoyuhr" <ex*********@hotmail.com> writes:
I'm trying to create a function that can take arguments, say, foo and
bar, and modify the original copies of foo and bar as well as its local
versions -- the equivalent of C++ funct(&foo, &bar).


C++'s '&' causes an argument to be passed by reference. Python does
that with all arguments. Any changes you make to the argument in the
function will be seen in the caller unless you explicitly make a copy
to pass.

except when foo and bar are bound to immutable objects.

In C:

int foo=1;
int bar=2;

void update(int *a, int *b) { *a=3; *b=4}

update(&foo, &bar);

In Python:

foo=1
bar=2

def update(a,b): a=3; b=4

update(foo,bar)

Many people from C/C++ background would be tricked for this situation.

Dec 8 '05 #5
"ex_ottoyuhr" wrote:
I've looked around on this newsgroup and elsewhere, and I gather that
this is a very common concern in Python, but one which is ordinarily
answered with "No, you can't. Neat, huh?" A few websites, newsgroup
posts, etc. have recommended that one ask for a more "Pythonic" way of
doing things; so, is there one, or at least one that doesn't involve
using objects as wrappers for mutable arguments?
anyone that holds a reference to a mutable object can modify it, and
everyone that has the same reference will see the changes. assignment
copies references, not values:
foo = []
value = foo
foo.append("hello")
foo.append("world")
value ['hello', 'world']
And, indeed, would that approach work? Would declaring:

class FooWrapper :
__init__(fooToLoad) :
self.foo = fooToLoad

mean that I could now declare a FooWrapper holding a foo, pass the
FooWrapper to a function, and have the function conclude with the foo
within the FooWrapper now modified?


if self.foo is a mutable object, and your function is modifying it in
place, yes:
class FooWrapper: ... def __init__(self, fooToLoad):
... self.foo = fooToLoad
... value = []
foo = FooWrapper(value)

foo.foo [] value [] def mutator(x): ... x.foo.append("hello")
... mutator(foo)
mutator(foo)

foo.foo ['hello', 'hello'] value ['hello', 'hello']

however, if the mutator replaces the wrapped object, the original object
will not see the changes. you can still see them via the wrapper, of course:
def mutator(x): ... x.foo = ["goodbye"]
... mutator(foo)
foo.foo ['goodbye'] value

['hello', 'hello']

this might help:

http://effbot.org/zone/python-objects.htm

</F>

Dec 8 '05 #6
ex_ottoyuhr wrote:
I'm trying to create a function that can take arguments, say, foo and
bar, and modify the original copies of foo and bar as well as its local
versions -- the equivalent of C++ funct(&foo, &bar).

I've looked around on this newsgroup and elsewhere, and I gather that
this is a very common concern in Python, but one which is ordinarily
answered with "No, you can't. Neat, huh?" A few websites, newsgroup
posts, etc. have recommended that one ask for a more "Pythonic" way of
doing things; so, is there one, or at least one that doesn't involve
using objects as wrappers for mutable arguments?

And, indeed, would that approach work? Would declaring:

class FooWrapper :
__init__(fooToLoad) :
self.foo = fooToLoad

mean that I could now declare a FooWrapper holding a foo, pass the
FooWrapper to a function, and have the function conclude with the foo
within the FooWrapper now modified?
Well, you can test it yourself:
class wrapper(object): .... def __init__(self, val):
.... self.val = val
.... w = wrapper(42)
w.val 42 def foo(w): .... w.val = 11
.... foo(w)
w.val 11
Thanks in advance for everyone's time; I hope I'm comprehensible.


You're comprehensible, but I think that you're also thinking in C++.
The object model that Python follows is very different -- instead of
thinking of assignment meaning
"Stick this value into this named location", you need to switch to
thinking of assignment as meaning "stick this name onto that object
until I tell you otherwise".

If you're trying to return multiple values from a function, Python lets
you do that
def multiFoo(x, y, z): .... return x*2, y*2, z*2
.... x = 1
y = 2
z = 3
x, y, z = multiFoo(x, y, z)
x 2 y 4 z 6

--
// Today's Oblique Strategy (© Brian Eno/Peter Schmidt):
// Repetition is a form of change
// Brett g Porter * Bg******@acm.org

Dec 8 '05 #7
bo****@gmail.com writes:
Mike Meyer wrote:
"ex_ottoyuhr" <ex*********@hotmail.com> writes:
> I'm trying to create a function that can take arguments, say, foo and
> bar, and modify the original copies of foo and bar as well as its local
> versions -- the equivalent of C++ funct(&foo, &bar).
C++'s '&' causes an argument to be passed by reference. Python does
that with all arguments. Any changes you make to the argument in the
function will be seen in the caller unless you explicitly make a copy
to pass.

except when foo and bar are bound to immutable objects.


Wrong.
In C:

int foo=1;
int bar=2;

void update(int *a, int *b) { *a=3; *b=4}

update(&foo, &bar);
Note that this update is using an assignment statement, and thus
changing the arguments.
In Python:

foo=1
bar=2

def update(a,b): a=3; b=4

update(foo,bar)
This update isn't changing the objects, it's rebinding the names in
the local name space. Since you didn't change the objects, there's no
change to see in the calling environment.
Many people from C/C++ background would be tricked for this situation.


That's because they don't understand binding. Any language that has
bindings instead of has assignments will "trick" them this way.

<mike
--
Mike Meyer <mw*@mired.org> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
Dec 8 '05 #8
Mike Meyer <mw*@mired.org> wrote:
Many people from C/C++ background would be tricked for this situation.


That's because they don't understand binding. Any language that has
bindings instead of has assignments will "trick" them this way.


....Java being probably the most popular example...
Alex
Dec 8 '05 #9


And, indeed, would that approach work? Would declaring:

class FooWrapper :
__init__(fooToLoad) :
self.foo = fooToLoad

mean that I could now declare a FooWrapper holding a foo, pass the
FooWrapper to a function, and have the function conclude with the foo
within the FooWrapper now modified?

Yes, passing FooWrapper will pass by reference to a python function
thereby allowing you to edit the fooToLoad

HTH,

carl
--

Carl J. Van Arsdall
cv*********@mvista.com
Build and Release
MontaVista Software

Dec 8 '05 #10

Mike Meyer wrote:
bo****@gmail.com writes:
Mike Meyer wrote:
"ex_ottoyuhr" <ex*********@hotmail.com> writes:
> I'm trying to create a function that can take arguments, say, foo and
> bar, and modify the original copies of foo and bar as well as its local
> versions -- the equivalent of C++ funct(&foo, &bar).

C++'s '&' causes an argument to be passed by reference. Python does
that with all arguments. Any changes you make to the argument in the
function will be seen in the caller unless you explicitly make a copy
to pass.
except when foo and bar are bound to immutable objects.


Wrong.
In C:

int foo=1;
int bar=2;

void update(int *a, int *b) { *a=3; *b=4}

update(&foo, &bar);


Note that this update is using an assignment statement, and thus
changing the arguments.


void update(int a, int b) { a=3; b=4}

Is this also an assignment statement ?
In Python:

foo=1
bar=2

def update(a,b): a=3; b=4

update(foo,bar)


This update isn't changing the objects, it's rebinding the names in
the local name space. Since you didn't change the objects, there's no
change to see in the calling environment.
Many people from C/C++ background would be tricked for this situation.


That's because they don't understand binding. Any language that has
bindings instead of has assignments will "trick" them this way.

Sure, any language that behave like this would trick them, I am not
saying python is the only one or that there is anything wrong with this
behaviour. I was just saying that it is a situation that they get
tricked, because of their "perception" about "=", especially when they
are told that any change to the arguments are seen by the caller.

Dec 8 '05 #11
bo****@gmail.com writes:
Mike Meyer wrote:
bo****@gmail.com writes:
> Mike Meyer wrote:
>> "ex_ottoyuhr" <ex*********@hotmail.com> writes:
>> > I'm trying to create a function that can take arguments, say, foo and
>> > bar, and modify the original copies of foo and bar as well as its local
>> > versions -- the equivalent of C++ funct(&foo, &bar).
>> C++'s '&' causes an argument to be passed by reference. Python does
>> that with all arguments. Any changes you make to the argument in the
>> function will be seen in the caller unless you explicitly make a copy
>> to pass.
> except when foo and bar are bound to immutable objects.

Wrong.
> In C:
>
> int foo=1;
> int bar=2;
>
> void update(int *a, int *b) { *a=3; *b=4}
>
> update(&foo, &bar);


Note that this update is using an assignment statement, and thus
changing the arguments.

void update(int a, int b) { a=3; b=4}
Is this also an assignment statement ?


Yes. But C calls by value, and passes copies of the original a and b
in. So in this case, you change the copies.
> In Python:
>
> foo=1
> bar=2
>
> def update(a,b): a=3; b=4
>
> update(foo,bar)

This update isn't changing the objects, it's rebinding the names in
the local name space. Since you didn't change the objects, there's no
change to see in the calling environment.
> Many people from C/C++ background would be tricked for this situation.

That's because they don't understand binding. Any language that has
bindings instead of has assignments will "trick" them this way.

Sure, any language that behave like this would trick them, I am not
saying python is the only one or that there is anything wrong with this
behaviour. I was just saying that it is a situation that they get
tricked, because of their "perception" about "=", especially when they
are told that any change to the arguments are seen by the caller.


Except "trick" is a poor word choice. Nobody is playing a trick on
them - they just don't understand what is going on.

<mike
--
Mike Meyer <mw*@mired.org> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
Dec 8 '05 #12

Mike Meyer wrote:
Except "trick" is a poor word choice. Nobody is playing a trick on
them - they just don't understand what is going on.

oops, never thought about the negative meaning of it, it is just meant
as "not behave as expected", what would be the word you use then ?

Dec 8 '05 #13
bo****@gmail.com writes:
Except "trick" is a poor word choice. Nobody is playing a trick on
them - they just don't understand what is going on.

oops, never thought about the negative meaning of it, it is just meant
as "not behave as expected", what would be the word you use then ?


Surprise?

<mike
--
Mike Meyer <mw*@mired.org> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
Dec 8 '05 #14
ex_ottoyuhr wrote:
I'm trying to create a function that can take arguments, say, foo and
bar, and modify the original copies of foo and bar as well as its local
versions -- the equivalent of C++ funct(&foo, &bar).
This is already what you have. In Python, all you have are references to
objects, there is no "local version".
I've looked around on this newsgroup and elsewhere, and I gather that
this is a very common concern in Python, but one which is ordinarily
answered with "No, you can't. Neat, huh?"


Pardon ???
def appendToList(aList, aValue): .... aList.append(aValue)
.... mylist = range(10)
mylist [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] appendToList(mylist, 42)
mylist [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 42]


Now the usual considerations apply :
- rebinding an arg has of course only local effect
- immutable objects are still immutables

Also note that since
1/ Python as a good support for exception handling
2/ a function can return multiple values [1],
there is less need for such constructs than in C or C++.

[1] the truth is that the function can return a unique tuple, that can
be unpacked as any other.

--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Dec 8 '05 #15
Mike Meyer wrote:
"ex_ottoyuhr" <ex*********@hotmail.com> writes:
I'm trying to create a function that can take arguments, say, foo and
bar, and modify the original copies of foo and bar as well as its local
versions -- the equivalent of C++ funct(&foo, &bar).

C++'s '&' causes an argument to be passed by reference. Python does
that with all arguments. Any changes you make to the argument in the
function will be seen in the caller unless you explicitly make a copy
to pass.


I would say, from the point of view of a C++ programmer, Python passes
references by value. In other words if you think of variables as
pointers (references) to values, and function call as passing the
reference by value, the behaviour of Python makes sense.

Kent
Dec 8 '05 #16
Kent Johnson <ke**@kentsjohnson.com> writes:
Mike Meyer wrote:
"ex_ottoyuhr" <ex*********@hotmail.com> writes:
I'm trying to create a function that can take arguments, say, foo and
bar, and modify the original copies of foo and bar as well as its local
versions -- the equivalent of C++ funct(&foo, &bar).

C++'s '&' causes an argument to be passed by reference. Python does
that with all arguments. Any changes you make to the argument in the
function will be seen in the caller unless you explicitly make a copy
to pass.

I would say, from the point of view of a C++ programmer, Python passes
references by value. In other words if you think of variables as
pointers (references) to values, and function call as passing the
reference by value, the behaviour of Python makes sense.


While the description is right, the terminology is wrong, and places
the emphasis in the wrong place.

Your description of "passes references by value" is a description of
call by reference. C passes all arguments by value, to pass a
reference, the C programmer creates the reference to the value "by
hand", then dereferences it by hand at the other end. So C's
"call-by-reference" passes the reference by value. There's no
difference between C's call-by-reference and Python's
call-by-reference, and using different words to try and imply there is
will just cause problems further on.

The real difference is in the way names behave in the two
languages. As you put it, "variables are references to values", except
Python names don't have most of the things associated with variables
in other programming languages, so it's better to call them names. We
use "bound" to show that we're not copying a value over a fixed memory
location, hence "names are bound to values." This is the crucial
point, and the one that need to be emphasized.

<mike
--
Mike Meyer <mw*@mired.org> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
Dec 8 '05 #17
Mike Meyer wrote:
Your description of "passes references by value" is a description of
call by reference. C passes all arguments by value, to pass a
reference, the C programmer creates the reference to the value "by
hand", then dereferences it by hand at the other end. So C's
"call-by-reference" passes the reference by value. There's no
difference between C's call-by-reference and Python's
call-by-reference, and using different words to try and imply there is
will just cause problems further on.


can you guys please stop using "call by value" and "call by reference"
when you discuss Python. both terms have established meanings, and
Python's argument passing model doesn't match any of them.

this was known some 30 years ago; here's a quote from a CLU reference
manaual from 1979:

"We call the argument passing technique _call by sharing_,
because the argument objects are shared between the
caller and the called routine. This technique does not
correspond to most traditional argument passing techniques
(it is similar to argument passing in LISP). In particular IT
IS NOT call by value because mutations of arguments per-
formed 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."

(CLU was one of the first languages to use objects in the Python sense,
as well as the same argument passing model as today's Python)

established terms for Python's argument passing model are

call by object

or

call by sharing

for more on this, see the comp.lang.python archives.

</F>

Dec 8 '05 #18

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: domeceo | last post by:
can anyone tell me why I cannot pass values in a setTimeout function whenever I use this function it says "menu is undefined" after th alert. function imgOff(menu, num) { if (document.images) {...
2
by: laredotornado | last post by:
Hello, I am looking for a cross-browser way (Firefox 1+, IE 5.5+) to have my Javascript function execute from the BODY's "onload" method, but if there is already an onload method defined, I would...
4
by: anonymous | last post by:
Thanks your reply. The article I read is from www.hakin9.org/en/attachments/stackoverflow_en.pdf. And you're right. I don't know it very clearly. And that's why I want to understand it; for it's...
10
by: Robert Skidmore | last post by:
Take a look at this new JS function I made. It is really simple but very powerful. You can animate any stylesheet numeric value (top left width height have been tested), and works for both % and px...
3
by: Beta What | last post by:
Hello, I have a question about casting a function pointer. Say I want to make a generic module (say some ADT implementation) that requires a function pointer from the 'actual/other modules'...
7
by: sfeher | last post by:
Hi All, Is there a way to preserve the arguments across functions? I have: <script> function myFirstFunction() { // arguments = 'param1'
7
by: VK | last post by:
I was getting this effect N times but each time I was in rush to just make it work, and later I coudn't recall anymore what was the original state I was working around. This time I nailed the...
9
by: CryptiqueGuy | last post by:
Consider the variadic function with the following prototype: int foo(int num,...); Here 'num' specifies the number of arguments, and assume that all the arguments that should be passed to this...
1
by: cnb | last post by:
Is it not possible to have mutability without this? I know I can use sorted and list(reversed) instead of .sort and .reverse but if I want to copy a list and then change that list without changing...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.