2

i need help-i try to send value to method like in c++ by ref/by ptr how can i do it?

to exmple:

 def test(x):
    x=3    

 x=2
 test(x)
 print(x)

In this case x a local variable in test method and will not change the "original" X so how can i change the "original" X? thanks

Evyatar Elmaliah
  • 634
  • 1
  • 8
  • 23
  • http://stackoverflow.com/questions/1145722/simulating-pointers-in-python – solusipse Oct 16 '13 at 16:47
  • 2
    Don't try to write other languages in Python (or, indeed, Python in other languages). – Daniel Roseman Oct 16 '13 at 16:51
  • 3
    @BurhanKhalid There is no distinction between mutable and immutable objects either (as far as argument passing is concerned). Everything is passed the same way -- for example, immutable objects are *not* copied -- the only difference is that it's slightly harder to observe this with immutable objects. –  Oct 16 '13 at 16:52

2 Answers2

4

In some ways, all calls in Python are called with references. In fact, all variables are references in a sense. But some types, like int from your example, cannot be changed.

In the case of, say, a list, the functionality you're looking for is trivial:

def change_it(some_list):
    some_list.append("world")

foo = ["hello"]
change_it(foo)
print(foo)  # prints ['hello', 'world']

Note, however, that reassigning the parameter variable some_list does not change the value in the calling context.

If you're asking this question, though, you're probably looking to do something like set two or three variables using one function. In that case, you're looking for something like this:

def foo_bar(x, y, z):
    return 2*x, 3*y, 4*z

x = 3
y = 4
z = 5
x, y, z = foo_bar(x, y, z)
print(y)  # prints 12

Of course, you can do anything in Python, but that doesn't mean you should. In the fashion of the TV show Mythbusters, here's something that does what you're looking for

import inspect

def foo(bar):
    frame = inspect.currentframe()
    outer = inspect.getouterframes(frame)[1][0]
    outer.f_locals[bar] = 2 * outer.f_locals[bar]

a = 15
foo("a")
print(a) # prints 30

or even worse:

import inspect
import re

def foo(bar):
    # get the current call stack
    my_stack = inspect.stack()
    # get the outer frame object off of the stack
    outer = my_stack[1][0]
    # get the calling line of code; see the inspect module documentation
    #   only works if the call is not split across multiple lines of code
    calling_line = my_stack[1][4][0]
    # get this function's name
    my_name = my_stack[0][3]
    # do a regular expression search for the function call in traditional form
    #   and extract the name of the first parameter
    m = re.search(my_name + "\s*\(\s*(\w+)\s*\)", calling_line)
    if m:
        # finally, set the variable in the outer context
        outer.f_locals[m.group(1)] = 2 * outer.f_locals[m.group(1)]
    else:
        raise TypeError("Non-traditional function call.  Why don't you just"
                        " give up on pass-by-reference already?")

# now this works like you would expect
a = 15
foo(a)
print(a)

# but then this doesn't work:
baz = foo_bar
baz(a)  #  raises TypeError

# and this *really*, disastrously doesn't work
a, b = 15, 20
foo_bar, baz = str, foo_bar
baz(b) and foo_bar(a)
print(a, b)  # prints 30, 20

Please, please, please, don't do this. I only put it in here to inspire the reader to look into some of the more obscure parts of Python.

Daisy Sophia Hollman
  • 6,046
  • 6
  • 24
  • 35
  • 2
    Not call by reference, call be reference objects. All parameters are passed by reference by default. – Games Brainiac Oct 16 '13 at 17:49
  • Good point. Fixing it now – Daisy Sophia Hollman Oct 16 '13 at 17:56
  • 1
    Your examples using `f_locals` doesn't work in the general case. whenever the given name is a fast local (as it is for variables in local scope of most functions), then the `f_locals` dict won't contain the value, it's in `f_localsplus`, which is not accessible from normal python. There's no reasonable way to push data from `f_locals` into `f_localsplus` (except with ctypes). – SingleNegationElimination Oct 16 '13 at 18:07
  • @dequestarmappartialsetattr good to know. I didn't intend it to be an actual usable method, but more a way to show off the `inspect` module. Thanks, though. I learned something – Daisy Sophia Hollman Oct 16 '13 at 20:45
1

As far as I am aware, this doesn't exist in Python (although a similar thing occurs if you pass mutable objects to a function). You would do either

def test():
    global x
    x = 3

test()

or

def test(x):
    return 3

x = test(x)

The second of these is much preferred.

rlms
  • 10,650
  • 8
  • 44
  • 61