Simulating Pointers in Python

Viewed 95928

I'm trying to cross compile an in house language(ihl) to Python.

One of the ihl features is pointers and references that behave like you would expect from C or C++.

For instance you can do this:

a = [1,2];  // a has an array 
b = &a;     // b points to a
*b = 2;     // derefernce b to store 2 in a
print(a);   // outputs 2
print(*b);   // outputs 2

Is there a way to duplicate this functionality in Python.

I should point out that I think I've confused a few people. I don't want pointers in Python. I just wanted to get a sense from the Python experts out there, what Python I should generate to simulate the case I've shown above

My Python isn't the greatest but so far my exploration hasn't yielded anything promising:(

I should point out that we are looking to move from our ihl to a more common language so we aren't really tied to Python if someone can suggest another language that may be more suitable.

10 Answers

This can be done explicitly.

class ref:
    def __init__(self, obj): self.obj = obj
    def get(self):    return self.obj
    def set(self, obj):      self.obj = obj

a = ref([1, 2])
b = a
print(a.get())  # => [1, 2]
print(b.get())  # => [1, 2]

b.set(2)
print(a.get())  # => 2
print(b.get())  # => 2

If you're compiling a C-like language, say:

func()
{
    var a = 1;
    var *b = &a;
    *b = 2;
    assert(a == 2);
}

into Python, then all of the "everything in Python is a reference" stuff is a misnomer.

It's true that everything in Python is a reference, but the fact that many core types (ints, strings) are immutable effectively undoes this for many cases. There's no direct way to implement the above in Python.

Now, you can do it indirectly: for any immutable type, wrap it in a mutable type. Ephemient's solution works, but I often just do this:

a = [1]
b = a
b[0] = 2
assert a[0] == 2

(I've done this to work around Python's lack of "nonlocal" in 2.x a few times.)

This implies a lot more overhead: every immutable type (or every type, if you don't try to distinguish) suddenly creates a list (or another container object), so you're increasing the overhead for variables significantly. Individually, it's not a lot, but it'll add up when applied to a whole codebase.

You could reduce this by only wrapping immutable types, but then you'll need to keep track of which variables in the output are wrapped and which aren't, so you can access the value with "a" or "a[0]" appropriately. It'll probably get hairy.

As to whether this is a good idea or not--that depends on why you're doing it. If you just want something to run a VM, I'd tend to say no. If you want to be able to call to your existing language from Python, I'd suggest taking your existing VM and creating Python bindings for it, so you can access and call into it from Python.

Everything in Python is pointers already, but it's called "references" in Python. This is the translation of your code to Python:

a = [1,2]  // a has an array 
b = a     // b points to a
a = 2      // store 2 in a.
print(a)   // outputs 2
print(b)  // outputs [1,2]

"Dereferencing" makes no sense, as it's all references. There isn't anything else, so nothing to dereference to.

As others here have said, all Python variables are essentially pointers.

The key to understanding this from a C perspective is to use the unknown by many id() function. It tells you what address the variable points to.

>>> a = [1,2]
>>> id(a)
28354600

>>> b = a
>>> id(a)
28354600

>>> id(b)
28354600

This is goofy, but a thought...

# Change operations like:
b = &a

# To:
b = "a"

# And change operations like:
*b = 2

# To:
locals()[b] = 2


>>> a = [1,2]
>>> b = "a"
>>> locals()[b] = 2
>>> print(a)
2
>>> print(locals()[b])
2

But there would be no pointer arithmetic or such, and no telling what other problems you might run into...

Negative, no pointers. You should not need them with the way the language is designed. However, I heard a nasty rumor that you could use the: ctypes module to use them. I haven't used it, but it smells messy to me.

Related