There's no concept of pointers on python (at least that I'm aware of).
In case you are saving objects inside your list, you can simply keep a reference to that object.
In the case you are saving primitive values into your list, the approach I would take is to make a wrapper object around the value/values and keep a reference of that object to use it later without having to access the list. This way your wrapper is working as a mutable object and can be modified no matter from where you are accesing it.
An example:
class FooWrapper(object):
def __init__(self, value):
self.value = value
# save an object into a list
l = []
obj = FooWrapper(5)
l.append(obj)
# add another object, so the initial object is shifted
l.insert(0, FooWrapper(1))
# change the value of the initial object
obj.value = 3
print l[1].value # prints 3 since it's still the same reference
Answer from asermax on Stack OverflowThere's no concept of pointers on python (at least that I'm aware of).
In case you are saving objects inside your list, you can simply keep a reference to that object.
In the case you are saving primitive values into your list, the approach I would take is to make a wrapper object around the value/values and keep a reference of that object to use it later without having to access the list. This way your wrapper is working as a mutable object and can be modified no matter from where you are accesing it.
An example:
class FooWrapper(object):
def __init__(self, value):
self.value = value
# save an object into a list
l = []
obj = FooWrapper(5)
l.append(obj)
# add another object, so the initial object is shifted
l.insert(0, FooWrapper(1))
# change the value of the initial object
obj.value = 3
print l[1].value # prints 3 since it's still the same reference
element = mylist[0] already works if you don't need to change the element or if element is a mutable object.
Immutable objects such as int objects in Python you can not change. Moreover, you can refer to the same object using multiple names in Python e.g., sys.getrefcount(1) is ~2000 in a fresh REPL on my system. Naturally, you don't want 1 to mean 2 all of a sudden in all these places.
If you want to change an object later then it should be mutable e.g., if mylist[0] == [1] then to change the value, you could set element[0] = 2. A custom object instead of the
[1] list could be more appropriate for a specific application.
As an alternative, you could use a dictionary (or other namespace objects such as types.SimpleNamespace) instead of the mylist list. Then to change the item, reference it by its name: mydict["a"] = 2.
I was just thinking about it... like, sometimes I want to work with something like a pointer, so I just put whatever I need in a list and when I need to reference another thing, I just do list[0] = new_thing
... goofy question, but I'm really curious how you guys work when the situation calls for a pointer
No, really. I've just started practicing problems on Leetcode and today I tried to do a bunch of things with Linked lists in python. I always second guess myself when I'm writing assignment statements like node = next_node because I'm worried that using shallow copies might screw things up for me.
Wouldn't it have been way easier to directly reference objects by their memory location?
I'm not going to use C for coding interviews so I'd also appreciate any ways I can idiot proof my code when I'm dealing with moving and assigning objects in Python.
One idea I had was to include a deepcopy method in the List node class definition but I can't make any changes to the leetcode question setup.
I recommend reading Semantics of Python variable names from a C++ perspective:
All variables are references
This is oversimplification of the entire article, but this (and the understanding that a list is a mutable type) should help you understand how the following example works.
In [5]: def update_list(lst, data):
...: for datum in data:
...: lst.append(datum)
...:
In [6]: l = [1, 2, 3]
In [7]: update_list(l, [4, 5, 6])
In [8]: l
Out[8]: [1, 2, 3, 4, 5, 6]
You can even shorten this by using the extend() method:
In [9]: def update_list(lst, data):
...: lst.extend(data)
...:
Which actually probably removes the need of your function.
N.B: list is a built-in and therefore a bad choice for a variable name.
You don't pass pointers in Python. Just assign to the slice that is the whole list
def update_list(list, data):
list[:] = newlist
Just to demonstrate, I wrote the following C code:
#include <stdio.h>
int absolute(int num, int* state)
{
if(num >= 0)
{
*state = 1;
return num;
}
else
{
*state = -1;
return num * (-1);
}
}
int main() {
int a, b;
printf("Enter the number to find its absolute: ");
scanf("%d", &a);
int result = absolute(a, &b);
if(b == -1)
{
printf("You entered a negative number");
}
else
{
printf("You did enter positive number");
}
printf("The absoluted value is %d", result);
return 0;
}In the above C program, I have passed in the value that I want absolute of. As well as a pointer to the variable. In the function, even though I can return the absolute value, I also want to know if the number was infact negative so I have to smuggle that out with the b variable.
Now, I know there are many ways to do it in a better way. But I just made a quick example to demonstrate what I mean.
I know that one can bundle all the stuff to return in a dict or a list and return that out of the function but in my case what if I have to use pointer smuggling?
I'm not sure exactly what you are trying to do, but you could do something like:
class FooWrapper(object):
def __init__(self, value):
self.value = value
def __repr__(self):
return 'FooWrapper(' + repr(self.value) + ')'
def __str__(self):
return str(self.value)
def __call__(self,value):
self.value = value
Here I got rid of your idea of using __repr__ to hide FooWrapper since I think it a bad idea to hide from the programmer what is happening at the REPL. Instead -- I used __str__ so that when you print the object you will print the wrapped value. The __call__ functions as a default method, which doesn't change the meaning of = but is sort of what you want:
>>> vals = [1,2,3]
>>> vals[1] = FooWrapper("Bob")
>>> vals
[1, FooWrapper('Bob'), 3]
>>> for x in vals: print(x)
1
Bob
3
>>> this = vals[1]
>>> this(10)
>>> vals
[1, FooWrapper(10), 3]
However, I think it misleading to refer to this as a pointer. It is just a wrapper object, and is almost certain to make dealing with the wrapped object inconvenient.
On Edit: The following is more of a pointer to a list. It allows you to create something like a pointer object with __call__ used to dereference the pointer (when no argument is passed to it) or to mutate the list (when a value is passed to __call__). It also implements a form of p++ called (pp) with wrap-around (though the wrap-around part could of course be dropped):
class ListPointer(object):
def __init__(self, myList,i=0):
self.myList = myList
self.i = i % len(self.myList)
def __repr__(self):
return 'ListPointer(' + repr(self.myList) + ',' + str(self.i) + ')'
def __str__(self):
return str(self.myList[self.i])
def __call__(self,*value):
if len(value) == 0:
return self.myList[self.i]
else:
self.myList[self.i] = value[0]
def pp(self):
self.i = (self.i + 1) % len(self.myList)
Used like this:
>>> vals = ['a','b','c']
>>> this = ListPointer(vals)
>>> this()
'a'
>>> this('d')
>>> vals
['d', 'b', 'c']
>>> this.pp()
>>> this()
'b'
>>> print(this)
b
I think that this is a more transparent way of getting something which acts like a list pointer. It doesn't require the thing pointed to to be wrapped in anything.
The __repr__ method can get a string however it wants to. Let's say it says return repr(self.value) + 'here'. If you say this = '4here', what should be affected? Should self.value be assigned to 4 or 4here? What if this had another attribute called key and __repr__ did return repr(self.key) + repr(self.value)? When you did this = '4here', would it assign self.key to the whole string, assign self.value to the whole string, or assign self.key to 4 and self.value to here? What if the string is completely made up by the method? If it says return 'here', what should this = '4here' do?
In short, you can't.
No, that's not possible. You can't store a reference to a location in a list and try to update it later through assignment.
If you want to implement a work-around, then you might want to use a closure to capture a reference to the desired index in your list. Here's an example:
# Here's my list
mylist = [1, 2, 3, 4]
# Save a reference to the list using a function to close over it
def myref(x): mylist[1] = x
# Update the referenced value to 7
myref(7)
# mylist is now [1, 7, 3, 4]
print mylist
You're stuck using the myref(7) syntax rather than myref = 7 syntax since there's no way to overload the assignment operator in Python, but I think that will work for you.
In your comment on one of the other answers you mentioned that you're actually dealing with an n-dimensional list, and you want to save a reference so that you can update it later when the indices aren't in scope. This works nicely for that case as well. Here's an example:
# My 3D list
list3D = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]
# Find
def findEntry(data, x):
for i, page in enumerate(data):
for j, row in enumerate(page):
for k, col in enumerate(row):
if col == x:
def myref(y): data[i][j][k] = y
return myref
# Get a reference to the first cell containing 4
updater = findEntry(list3D, 4)
# Update that cell to be 44 instead
updater(44)
# list3D is now [[[1, 2], [3, 44]], [[5, 6], [7, 8]]]
print list3D
It is better style to use a ref cell, than to use a pointer. Pointers are a distant concept from the point-of-view of python. You can make a cheap ref cell from a list.
pointer = [3]
pointer[0] = 5 #change value of ref cell
pointer[0] #get value of ref cell