0

Possible Duplicate:
Python: How do I pass a variable by reference?

I have the following case:

class A:
    def __init__(self):
        self.test = ''
        self.func(self.test)
        print(self.test)
    def func(self,var):
        var = 'foo'

I want func to modify self.var and I'd like to be able to pass a self. to this method.

A bit like:

class A()
{
  public:
    char test[256];
    A() { func(test);}
  private:
    void func(char * var) { var = "foo"; }
};

I haven't written C++ in a while but that's sort of what I'm going for.

Community
  • 1
  • 1
s5s
  • 11,159
  • 21
  • 74
  • 121
  • 2
    Your C++ code does nothing (more specifically, `func` changes what its local pointer points to and then throws that away). –  Nov 14 '12 at 20:00
  • It's exactly the same question, yes. – s5s Nov 14 '12 at 20:14
  • In your C++ version, are you trying to do `void func(char *&var) { var = "foo"; }` (take any `var` by reference and change it to point at a different string), or `void func(char *var) { strcpy(var, "foo"); }` (take a string pointer and mutate the string it points to into a different string)? (As @delnan pointed out, as written it does absolutely nothing—it takes a string pointer and ignores it, making its local copy of the pointer point at a different string.) – abarnert Nov 14 '12 at 22:30
  • PS, is there a reason `func` has to modify its variable? The usual Python idiom is to return a new value, and then just do `self.test = self.func(self.test)`. 99% of the time, when people pass variables by reference in C++, it's either an attempt at avoiding the "inefficiency" of copying (which is almost always misguided in C++, especially C++11, and even moreso in Python), or because they need to return two values (or one value plus an error code), which is trivial to do in Python. – abarnert Nov 14 '12 at 22:37

1 Answers1

0

Unfortunately, I don't know C++ very well, but I'm guessing you want something like this:

class A:
    def __init__(self):
        self.test = ''
        self.func("test")
        print(self.test)
    def func(self,var):
        setattr(self,var,'foo')

We have to do it this way because we can change (mutate) self.test inside a function (if it's mutable), but we can't change which object it references (which is what you're attempting to do with assignment). consider:

def func1(x):
   x.append('foo')
def func2(x):
   x = 'foo'

a = []
func1(a)
print a #['foo']  #mutated a in func1
func2(a)
print a #['foo']  #didn't change a in func2, only created a new local variable named `x` and assigned it to the string 'foo'

The only way around this is to pass some sort of proxy-like object which you can change. In this case, we pass the instance as the proxy object (self) and the attribute's name (var) so we know what to change on self. Given those two pieces of information, we can make the desired changes -- Of course, at this point, you're probably best off getting rid of func all together and just using setattr directly.


It's probably also worth asking why you actually want to do this. In general, you can just do:

self.test = "foo"

why would you want to write:

self.func(self.test)

instead? I can understand if you're trying to do that since you're used to having private methods and attributes. But this is python. "We're all consenting adults here." Just rely on the conventions (prefix a variable with _ if you want to warn users against modifying it and prefix with __ to invoke name mangling to avoid collisions in superclasses).

mgilson
  • 300,191
  • 65
  • 633
  • 696
  • That's not exactly the same because you have to have to associate a string with each variable. On the other hand if you could pass a reference to a variable you wouldn't need the string :). – s5s Nov 14 '12 at 19:57
  • @s5s - I realize it's not exactly the same. The "problem" is that assignment rebinds a local name to the object on the RHS. As such, you **can't change an immutable object by reference** -- But that begs the question -- Why would you need to? See my edit. – mgilson Nov 14 '12 at 20:03
  • @mgilson You're confusing names and the mutability objects. Nobody can change an immutable object in any way (that's the very definition of immutability). Everyone (who has access to that name) can change what object a name refers to (regardless of what object it refers to or is made to refer to; especially regardless of mutability of those objects). –  Nov 14 '12 at 20:05
  • @delnan -- the semantics here are quite muddy. I don't have the issue confused, but I may not have explained it the best. The point is that assignment creates a new reference to the object that results from the right hand side. So you can't change what a variable points to in a function because as soon as you make an assignment, you've only created a new local variable and you haven't changed what you passed in at all. Mutable objects can be *changed* (mutated) in functions: `lambda x: x.append(y)`, but again you can't change what object `x` points to. – mgilson Nov 14 '12 at 20:10
  • @mgilson Yes, that's more accurate. I trust you understand the semantics (though in my understanding, it's quite simple and non-muddy -- and I am yet to encounter anything challenging my mental model, despite frequenting questions on this topic). I merely objected to your phrasing. –  Nov 14 '12 at 20:12
  • @s5s -- As pointed out by delnan, perhaps my comment was ambiguous. You can't change an immutable object. **ever**. And you can't change the object that a variable references in a function. You can mutate an object within a function if it is a mutable object. – mgilson Nov 14 '12 at 20:14
  • @delnan -- I suppose the tricky part (the muddy semantics) is what do you mean by "change an object". Do you mean change the object that your reference is referencing? Or do you mean mutate the object. The former is impossible, the latter is trivial. I've not found anything to challenge my mental model of this either. But explaning the mental model is challenging due to the ambiguity in the word "change". (IMHO) – mgilson Nov 14 '12 at 20:15
  • @mgilson I take "changing an object" as "mutating the object", or (to use the term from the Python documentation) "changing the object's value". I don't recall discussing this with anyone who insists it means "changing what object a name references", but yeah, I see your point. It could be interpreted as either if one's not careful to differentiate between objects and names (I intentionally avoid "variable") which refer to objects. –  Nov 14 '12 at 20:26