How to create a reference to a variable in python?
No, you cannot. As other answer point out, you can (ab?)use aliasing of mutable objects to achieve a similar effect. However, that's not the same thing as C++ references, and I want to explain what actually happens to avoid any misconceptions.
You see, in C++ (and other languages), a variable (and object fields, and entries in collections, etc.) is a storage location and you write a value (for instance, an integer, an object, or a pointer) to that location. In this model, references are an alias for a storage location (of any kind) - when you assign to a non-reference variable, you copy a value (even if it's just a pointer, it's still a value) to the storage location; when you assign to a reference, you copy to a storage location somewhere else. Note that you cannot change a reference itself - once it is bound (and it has to as soon as you create one) all assignments to it alter not the reference but whatever is referred to.
In Python (and other languages), a variable (and object fields, and entries in collections, etc.) is a just a name. Values are somewhere else (e.g. sprinkled all over the heap), and a variable refers (not in the sense of C++ references, more like a pointer minus the pointer arithmetic) to a value. Multiple names can refer to the same value (which is generally a good thing). Python (and other languages) calls whatever is needed to refer to a value a reference, despite being pretty unrelated to things like C++ references and pass-by-reference. Assigning to a variable (or object field, or ...) simply makes it refer to another value. The whole model of storage locations does not apply to Python, the programmer never handles storage locations for values. All he stores and shuffles around are Python references, and those are not values in Python, so they cannot be target of other Python references.
All of this is independent of mutability of the value - it's the same for ints and lists, for instance. You cannot take a variable that refers to either, and overwrite the object it points to. You can only tell the object to modify parts of itself - say, change some reference it contains.
Is this a more restrictive model? Perhaps, but it's powerful enough most of the time. And when it isn't you can work around it, either with a custom class like the one given below, or (equivalent, but less obvious) a single-element collection.
class Reference:
def __init__(self, val):
self._value = val # just refers to val, no copy
def get(self):
return self._value
def set(self, val):
self._value = val
That still won't allow you to alias a "regular" variable or object field, but you can have multiple variables referring to the same Reference
object (ditto for the mutable-singleton-collection alternative). You just have to be careful to always use .get()
/.set()
(or [0]
).
How do I pass a variable by reference?
Arguments are passed by assignment. The rationale behind this is twofold:
- the parameter passed in is actually a reference to an object (but the reference is passed by value)
- some data types are mutable, but others aren't
So:
If you pass a mutable object into a method, the method gets a reference to that same object and you can mutate it to your heart's delight, but if you rebind the reference in the method, the outer scope will know nothing about it, and after you're done, the outer reference will still point at the original object.
If you pass an immutable object to a method, you still can't rebind the outer reference, and you can't even mutate the object.
To make it even more clear, let's have some examples.
List - a mutable type
Let's try to modify the list that was passed to a method:
def try_to_change_list_contents(the_list):
print('got', the_list)
the_list.append('four')
print('changed to', the_list)
outer_list = ['one', 'two', 'three']
print('before, outer_list =', outer_list)
try_to_change_list_contents(outer_list)
print('after, outer_list =', outer_list)
Output:
before, outer_list = ['one', 'two', 'three']
got ['one', 'two', 'three']
changed to ['one', 'two', 'three', 'four']
after, outer_list = ['one', 'two', 'three', 'four']
Since the parameter passed in is a reference to outer_list
, not a copy of it, we can use the mutating list methods to change it and have the changes reflected in the outer scope.
Now let's see what happens when we try to change the reference that was passed in as a parameter:
def try_to_change_list_reference(the_list):
print('got', the_list)
the_list = ['and', 'we', 'can', 'not', 'lie']
print('set to', the_list)
outer_list = ['we', 'like', 'proper', 'English']
print('before, outer_list =', outer_list)
try_to_change_list_reference(outer_list)
print('after, outer_list =', outer_list)
Output:
before, outer_list = ['we', 'like', 'proper', 'English']
got ['we', 'like', 'proper', 'English']
set to ['and', 'we', 'can', 'not', 'lie']
after, outer_list = ['we', 'like', 'proper', 'English']
Since the the_list
parameter was passed by value, assigning a new list to it had no effect that the code outside the method could see. The the_list
was a copy of the outer_list
reference, and we had the_list
point to a new list, but there was no way to change where outer_list
pointed.
String - an immutable type
It's immutable, so there's nothing we can do to change the contents of the string
Now, let's try to change the reference
def try_to_change_string_reference(the_string):
print('got', the_string)
the_string = 'In a kingdom by the sea'
print('set to', the_string)
outer_string = 'It was many and many a year ago'
print('before, outer_string =', outer_string)
try_to_change_string_reference(outer_string)
print('after, outer_string =', outer_string)
Output:
before, outer_string = It was many and many a year ago
got It was many and many a year ago
set to In a kingdom by the sea
after, outer_string = It was many and many a year ago
Again, since the the_string
parameter was passed by value, assigning a new string to it had no effect that the code outside the method could see. The the_string
was a copy of the outer_string
reference, and we had the_string
point to a new string, but there was no way to change where outer_string
pointed.
I hope this clears things up a little.
EDIT: It's been noted that this doesn't answer the question that @David originally asked, "Is there something I can do to pass the variable by actual reference?". Let's work on that.
How do we get around this?
As @Andrea's answer shows, you could return the new value. This doesn't change the way things are passed in, but does let you get the information you want back out:
def return_a_whole_new_string(the_string):
new_string = something_to_do_with_the_old_string(the_string)
return new_string
# then you could call it like
my_string = return_a_whole_new_string(my_string)
If you really wanted to avoid using a return value, you could create a class to hold your value and pass it into the function or use an existing class, like a list:
def use_a_wrapper_to_simulate_pass_by_reference(stuff_to_change):
new_string = something_to_do_with_the_old_string(stuff_to_change[0])
stuff_to_change[0] = new_string
# then you could call it like
wrapper = [my_string]
use_a_wrapper_to_simulate_pass_by_reference(wrapper)
do_something_with(wrapper[0])
Although this seems a little cumbersome.
how to assign variable by reference in python?
The simple answer is that all variables in python are references. Some references are to immutable objects (such as strings, integers etc), and some references are to mutable objects (lists, sets). There is a subtle difference between changing a referenced object's value (such as adding to an existing list), and changing the reference (changing a variable to reference a completely different list).
In your example, you are initially x = o.a
making the variable x
a reference to whatever o.a
is (a reference to 1
). When you then do x = 2
, you are changing what x references (it now references 2
, but o.a
still references 1
.
A short note on memory management:
Python handles the memory management of all this for you, so if you do something like:
x = "Really_long_string" * 99999
x = "Short string"
When the second statement executes, Python will notice that there are no more references to the "really long string" string object, and it will be destroyed/deallocated.
How do I reference a variable inside a function in a class in python from another external file in python?
If you want var1 then just do
obj = A()
obj.doSomething()
val = obj.var1
How to make all the reference variables None in Python?
I really like your question. Probably this is not exactly what you are looking for, but I have found weakref
library. With it you could try to modify your code:
class ListNode:
def __init__(self, val, next_=None):
self.val = val
self.next_ = next_
def get_next(self):
try:
self.next_.check()
except AttributeError: # if self.next_ exists then it does not have 'check' method.
return self.next_
except ReferenceError: # if it does not exists it will raise this exception
return None
Then instead of assigning node.next_ = next_node
, you can create weakref:
node = ListNode(1)
next_node = ListNode(2)
node.next_ = weakref.proxy(next_node)
print( next_node == node.next_) # prints True
next_node = None
print(node.get_next()) # prints None
Hope this will help solve your problem!
Edit:
I have also changed the name next
to next_
because next
is a builtin function
Create a reference to a variable (similar to PHP's =&)?
There is some more magic that can be done in Python (not that I would recommend it and it will require digging on your part ;-), but using a closure may be sufficient for your needs:
get_x = lambda: foo_instance.bar
get_x() # yahoo!
Edit, for those wanting "update support", it's all about the closures:
def wrap_prop (obj, pname):
def _access(*v):
if not len(v):
return getattr(obj, pname)
else
setattr(obj, pname, v[0])
return _access
class z (object):
pass
access = wrap_prop(z(), "bar")
access(20)
access() # yahoo! \o/
Without stepping outside the bounds of normally (for me :-) accepted Python, this could also be written to return an object with forwarding/proxy property, imagine:
access = wrap_prop(z(), "bar")
access.val = 20
access.val # yahoo \o/
Some interesting links:
- http://adam.gomaa.us/blog/2008/aug/11/the-python-property-builtin/
- http://code.activestate.com/recipes/576787-alias-class-attributes/
- http://www.faqs.org/docs/diveintopython/dialect_locals.html
- http://docs.python.org/library/functions.html (see "property")
How to reference variable dynamically in Python?
you can use the eval() function to turn strings into variable:
read on eval
PROJECT_ID = 'test'
BQ_TABLE_NAME_CATEGORIES = 'categories'
BQ_TABLE_NAME_MANUFACTURERS = 'manufacturers'
mylist = [BQ_TABLE_NAME_CATEGORIES, BQ_TABLE_NAME_MANUFACTURERS]
table_categories = PROJECT_ID + '.' + BQ_TABLE_NAME_CATEGORIES
table_manufacturers = PROJECT_ID + '.' + BQ_TABLE_NAME_MANUFACTURERS
for table in mylist:
source_objects=eval('table_{0}'.format(table)) #reference to the correct var
print source_objects
output:
test.categories
test.manufacturers
also as noted in comments, you really shouldn't override list, and use mylist or whatever instead
Python functions call by reference
You can not change an immutable object, like str
or tuple
, inside a function in Python, but you can do things like:
def foo(y):
y[0] = y[0]**2
x = [5]
foo(x)
print x[0] # prints 25
That is a weird way to go about it, however, unless you need to always square certain elements in an array.
Note that in Python, you can also return more than one value, making some of the use cases for pass by reference less important:
def foo(x, y):
return x**2, y**2
a = 2
b = 3
a, b = foo(a, b) # a == 4; b == 9
When you return values like that, they are being returned as a Tuple which is in turn unpacked.
edit:
Another way to think about this is that, while you can't explicitly pass variables by reference in Python, you can modify the properties of objects that were passed in. In my example (and others) you can modify members of the list that was passed in. You would not, however, be able to reassign the passed in variable entirely. For instance, see the following two pieces of code look like they might do something similar, but end up with different results:
def clear_a(x):
x = []
def clear_b(x):
while x: x.pop()
z = [1,2,3]
clear_a(z) # z will not be changed
clear_b(z) # z will be emptied
Related Topics
Rendering Text with Multiple Lines in Pygame
Truth Value of a String in Python
Keras Not Training on Entire Dataset
Lag When Win.Blit() Background Pygame
Extending Setuptools Extension to Use Cmake in Setup.Py
How to Get Href Links from HTML Using Python
Beautifulsoup Webscraping Find_All( ): Finding Exact Match
How to Take a Screenshot/Image of a Website Using Python
How to Load All Entries in an Infinite Scroll at Once to Parse the HTML in Python
What Is the Fastest Way to Flatten Arbitrarily Nested Lists in Python
Convert Pandas.Series from Dtype Object to Float, and Errors to Nans
Why Is Tkinter Entry's Get Function Returning Nothing
Unnest (Explode) a Pandas Series
Pandas Add Column to Groupby Dataframe
Negative Integer Division Surprising Result
Parsing Date/Time String with Timezone Abbreviated Name in Python