153

I know Python doesn't have pointers, but is there a way to have this yield 2 instead

>>> a = 1
>>> b = a # modify this line somehow so that b "points to" a
>>> a = 2
>>> b
1

?


Here's an example: I want form.data['field'] and form.field.value to always have the same value. It's not completely necessary, but I think it would be nice.


In PHP, for example, I can do this:

<?php

class Form {
    public $data = [];
    public $fields;

    function __construct($fields) {
        $this->fields = $fields;
        foreach($this->fields as &$field) {
            $this->data[$field['id']] = &$field['value'];
        }
    }
}

$f = new Form([
    [
        'id' => 'fname',
        'value' => 'George'
    ],
    [
        'id' => 'lname',
        'value' => 'Lucas'
    ]
]);

echo $f->data['fname'], $f->fields[0]['value']; # George George
$f->data['fname'] = 'Ralph';
echo $f->data['fname'], $f->fields[0]['value']; # Ralph Ralph

Output:

GeorgeGeorgeRalphRalph

ideone


Or like this in C++ (I think this is right, but my C++ is rusty):

#include <iostream>
using namespace std;

int main() {
    int* a;
    int* b = a;
    *a = 1;
    cout << *a << endl << *b << endl; # 1 1

    return 0;
}
mpen
  • 272,448
  • 266
  • 850
  • 1,236
  • 29
    Perhaps I can ask a question similar to S.Lott's (but more productive): can you show us some real code where you wanted to do this? Perhaps even in another language that is more to your taste? It's likely that the problem you are trying to solve will lend itself to a more Pythonic solution, and focusing on "I want pointers" is obscuring the real answer. – Ned Batchelder Jun 24 '10 at 01:45
  • 9
    It doesn't take much imagination; I can think of dozens of reasons to want to do this. It's just not how it's done in pointer-less languages like Python; you need to wrap it in a container that's not invariant, as in Matt's answer. – Glenn Maynard Jun 24 '10 at 02:24
  • @Ned: Updated Q. Another example would be for a function, `swap(a, b)`. Not that I need that right now. – mpen Jun 24 '10 at 03:00
  • 21
    You wouldn't write a swap function in Python. You'd write `a, b = b, a`. – dan04 Jun 24 '10 at 03:10
  • 4
    -1: The construct in the question is (a) senseless, and (b) no one seems to be able to provide an example that makes it sensible. Saying there are "dozens of reasons" is not the same as posting an example. – S.Lott Jun 24 '10 at 10:21
  • @Mark: aliasing a variable absolutely is senseless. I'm asking for an example of how or why an alias could be other than complete and utter confusion. Your example of two names that don't match for the same variable leaves me confused. Why make things *more* complex? Why add the complexity of aliases? Many programmers get pointers wrong in C. Why try to add this error-prone problem to Python? – S.Lott Jun 24 '10 at 23:19
  • @Mark: "Why force them to go through...?" Because that's that the thing **is**. I can't see what the problem is. You can assign `a= form.field.widget` and then do `a.value`. I don't see what the problem is. – S.Lott Jun 25 '10 at 02:13
  • 1
    @Mark: Also, I'm not "disagreeing". I'm confused. I'm asking a question, looking for a way to understand what this is and why you think it's so important. – S.Lott Jun 25 '10 at 11:07
  • @Mark: I'm not understanding the use case. I trying to avoid any comment on the *importance*. I'm looking for an example of an alias that is helpful or makes the code *more* understandable. I'm still looking. Lacking an example, I'm suggesting that the question isn't a good question about Python since it seems to be asking for a feature that has no value. Please update the question with an example of an alias (or "pointer") that doesn't create new forms of confusion. – S.Lott Jun 28 '10 at 14:44
  • @Mark: I'm not "disagreeing". I'm looking for an explanation. And not getting one. It appears that you have agreed to provide no explanation. Therefore, I am left to "agree" to stop asking for an explanation. – S.Lott Jun 29 '10 at 01:26
  • @Mark: I can't follow "one variable that is used in two different places extensively, I don't like that one has to be extremely verbose". It's one variable. How can a variable be verbose? – S.Lott Jun 29 '10 at 10:15
  • @mpen I restored the `form.data['field'] is form.field.value` since multiple answers were referring to that. – Antti Haapala -- Слава Україні Mar 26 '16 at 15:25
  • @AnttiHaapala No problem. Sometimes I like to trim out superfluous info, but if you think it's useful, that's fine. – mpen Mar 27 '16 at 00:41
  • @Mark: I believe you mean [***'weak reference'*** (in the Python sense)](https://docs.python.org/3/library/weakref.html), not 'variable'. – smci Feb 27 '19 at 02:38
  • @smci I think I had in mind something more like a 'hardlink' in linux. Weakrefs die when the referent is no longer alive. – mpen Feb 27 '19 at 20:18

11 Answers11

78

There's no way you can do that changing only that line. You can do:

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

That creates a list, assigns the reference to a, then b also, uses the a reference to set the first element to 2, then accesses using the b reference variable.

Matthew Flaschen
  • 278,309
  • 50
  • 514
  • 539
  • 27
    That's exactly the kind of inconsistency I hate about Python and these dynamic languages. (Yeah yeah, it's not really "inconsistent" because you're changing an attribute rather than the reference but I still don't like it) – mpen Jun 24 '10 at 01:34
  • 14
    @Mark: indeed. I know countless (well, a few) people who spent possibly hours searching for a "bug" in their code and then to find that it was caused by a list not getting hard-copied. – houbysoft Jun 24 '10 at 01:44
  • 24
    There's no inconsistency. And it has nothing to do with the great static v. dynamic debate. If they were two references to the same Java ArrayList, it would be the same, modulo syntax. If you use immutable objects (like tuples), you don't have to worry about the object being changed through another reference. – Matthew Flaschen Jun 24 '10 at 01:44
  • I've used this several times, most commonly to work around 2.x's lack of "nonlocal". It's not the prettiest thing to do, but it works fine in a pinch. – Glenn Maynard Jun 24 '10 at 02:17
  • Yep, I figured this out for my situation. This is the best solution, I think. Ditto on what Mark said about inconsistency, though. It's weird that this is how we do this. – sudo Sep 16 '15 at 03:02
  • 2
    This is not inconsistent at all because the object you are assigning to `a` and `b` is the list, not the value in the list. The variables are not changing assignment, the object is the same object. If it changed, as in the case of changing the integer (each of which are different objects), `a` would now be assigned to another object and there is nothing prompting `b` to follow suit. Here, `a` is not being reassigned, rather a value inside the object to which it is assigned is changing. Since `b` is still bound to that object, it will reflect that object and the changes to the values within it. – arkigos Jan 27 '17 at 22:59
  • So we can say python list `is` C pointer / HLL reference. 233 – recolic Jan 25 '19 at 21:26
54

I want form.data['field'] and form.field.value to always have the same value

This is feasible, because it involves decorated names and indexing -- i.e., completely different constructs from the barenames a and b that you're asking about, and for with your request is utterly impossible. Why ask for something impossible and totally different from the (possible) thing you actually want?!

Maybe you don't realize how drastically different barenames and decorated names are. When you refer to a barename a, you're getting exactly the object a was last bound to in this scope (or an exception if it wasn't bound in this scope) -- this is such a deep and fundamental aspect of Python that it can't possibly be subverted. When you refer to a decorated name x.y, you're asking an object (the object x refers to) to please supply "the y attribute" -- and in response to that request, the object can perform totally arbitrary computations (and indexing is quite similar: it also allows arbitrary computations to be performed in response).

Now, your "actual desiderata" example is mysterious because in each case two levels of indexing or attribute-getting are involved, so the subtlety you crave could be introduced in many ways. What other attributes is form.field suppose to have, for example, besides value? Without that further .value computations, possibilities would include:

class Form(object):
   ...
   def __getattr__(self, name):
       return self.data[name]

and

class Form(object):
   ...
   @property
   def data(self):
       return self.__dict__

The presence of .value suggests picking the first form, plus a kind-of-useless wrapper:

class KouWrap(object):
   def __init__(self, value):
       self.value = value

class Form(object):
   ...
   def __getattr__(self, name):
       return KouWrap(self.data[name])

If assignments such form.field.value = 23 is also supposed to set the entry in form.data, then the wrapper must become more complex indeed, and not all that useless:

class MciWrap(object):
   def __init__(self, data, k):
       self._data = data
       self._k = k
   @property
   def value(self):
       return self._data[self._k]
   @value.setter
   def value(self, v)
       self._data[self._k] = v

class Form(object):
   ...
   def __getattr__(self, name):
       return MciWrap(self.data, name)

The latter example is roughly as close as it gets, in Python, to the sense of "a pointer" as you seem to want -- but it's crucial to understand that such subtleties can ever only work with indexing and/or decorated names, never with barenames as you originally asked!

Alex Martelli
  • 854,459
  • 170
  • 1,222
  • 1,395
  • 29
    I asked it the way I did because I was hoping to get a general solution that would work for everything right down to "barenames" and I didn't have a particular case in mind at the time -- just that I had ran into this problem with the previous iteration of this project and I didn't want to run into again. Anyway, this is a great answer! The incredulity, however, is less appreciated. – mpen Jun 24 '10 at 06:15
  • 2
    @Mark, look at the comments on your Q and you'll see that "incredulity" is a widespread reaction -- and the top-voted A is telling you "don't do it, get over it", followed by one that goes "it's just how it is". While you may not "appreciate" Python-knowledgeable people reacting with astonishment to your original specs, they _are_ quite astonishing in themselves;-). – Alex Martelli Jun 24 '10 at 14:04
  • 32
    Yes, but you seem astonished at my lack of Python knowledge... as if we're a foreign species :P – mpen Jun 24 '10 at 18:25
40

It's not a bug, it's a feature :-)

When you look at the '=' operator in Python, don't think in terms of assignment. You don't assign things, you bind them. = is a binding operator.

So in your code, you are giving the value 1 a name: a. Then, you are giving the value in 'a' a name: b. Then you are binding the value 2 to the name 'a'. The value bound to b doesn't change in this operation.

Coming from C-like languages, this can be confusing, but once you become accustomed to it, you find that it helps you to read and reason about your code more clearly: the value which has the name 'b' will not change unless you explicitly change it. And if you do an 'import this', you'll find that the Zen of Python states that Explicit is better than implicit.

Note as well that functional languages such as Haskell also use this paradigm, with great value in terms of robustness.

David Harks
  • 730
  • 4
  • 5
  • 46
    You know, I've read answers like this dozens of times, and I've never understood it. The behavior of `a = 1; b = a; a = 2;` is exactly the same in Python, C, and Java: b is 1. Why this focus on "= isn't assignment, it's binding"? – Ned Batchelder Jun 24 '10 at 01:59
  • 4
    You do assign things. That's why it's called an [assignment statement](http://docs.python.org/reference/simple_stmts.html). The distinction you're stating doesn't make sense. And this has nothing to do with compiled v. interpreted or static v. dynamic. Java is a compiled language with static type-checking, and it doesn't have pointers either. – Matthew Flaschen Jun 24 '10 at 01:59
  • 5
    What about C++? "b" might be a reference to "a". Understanding the difference between assignment and binding is critical to fully understanding why Mark can't do what he'd like to do, and how languages like Python are designed. Conceptually (not necessarily in implementation), "a = 1" doesn't overwrite the block of memory named "a" with 1; it assigns a name "a" to the already-existing object "1", which is fundamentally different than what happens in C. That's why pointers as a concept can't exist in Python--they'd become stale the next time the original variable was "assigned over". – Glenn Maynard Jun 24 '10 at 02:36
  • 1
    @d.w.: I like this way of thinking about it! "Binding" is a good word. @Ned: The output is the same, yes, but in C the value of "1" is copied to both `a` and `b` whereas in Python, they both *refer* to the *same* "1" (I think). Thus, if you could change the value of 1 (as with objects), it would be different. Which leads to some weird boxing/unboxing issues, I hear. – mpen Jun 24 '10 at 02:56
  • 5
    The difference between Python and C isn't what "assignment" means. It's what "variable" means. – dan04 Jun 24 '10 at 03:04
  • 1
    @Matthew, read the link you referred me to. The first sentence refers to the (re)binding behavior of =. The distinction is in mutability. – David Harks Jun 24 '10 at 03:13
28

Yes! there is a way to use a variable as a pointer in python!

I am sorry to say that many of answers were partially wrong. In principle every equal(=) assignation shares the memory address (check the id(obj) function), but in practice it is not such. There are variables whose equal("=") behaviour works in last term as a copy of memory space, mostly in simple objects (e.g. "int" object), and others in which not (e.g. "list","dict" objects).

Here is an example of pointer assignation

dict1 = {'first':'hello', 'second':'world'}
dict2 = dict1 # pointer assignation mechanism
dict2['first'] = 'bye'
dict1
>>> {'first':'bye', 'second':'world'}

Here is an example of copy assignation

a = 1
b = a # copy of memory mechanism. up to here id(a) == id(b)
b = 2 # new address generation. therefore without pointer behaviour
a
>>> 1

Pointer assignation is a pretty useful tool for aliasing without the waste of extra memory, in certain situations for performing comfy code,

class cls_X():
   ...
   def method_1():
      pd1 = self.obj_clsY.dict_vars_for_clsX['meth1'] # pointer dict 1: aliasing
      pd1['var4'] = self.method2(pd1['var1'], pd1['var2'], pd1['var3'])
   #enddef method_1
   ...
#endclass cls_X

but one have to be aware of this use in order to prevent code mistakes.

To conclude, by default some variables are barenames (simple objects like int, float, str,...), and some are pointers when assigned between them (e.g. dict1 = dict2). How to recognize them? just try this experiment with them. In IDEs with variable explorer panel usually appears to be the memory address ("@axbbbbbb...") in the definition of pointer-mechanism objects.

I suggest investigate in the topic. There are many people who know much more about this topic for sure. (see "ctypes" module). I hope it is helpful. Enjoy the good use of the objects! Regards, José Crespo

  • 2
    So I have to use a dictionary to pass a variable by reference to a function, and I can't pass a variable by reference using an int or a string? – Sam Mar 21 '20 at 15:42
  • 1
    **This is wrong.** There is only a single type of variable assignment in Python. What your example actually demonstrates is that dicts are mutable while ints are immutable. When you do dict2 = dict1, both variables now refer to the same address in memory, which you can confirm with the id() function. And the **exact same is true** for the int example b = a. The difference is, you are **reassigning the identifier** b in the second case, but you are **mutating the object** dict2 (which is the same as dict1) in the first case. The behavior of foo = bar is **exactly the same** for every type. – dain Apr 22 '23 at 10:13
  • (To clarify the above) the difference comes in the part where you do dict2["first"] = "bye"; this is where you mutate the underlying object, which you can't do with the integer. Up until that point, the assignment statement worked the same way. dict2["first"] = "bye" works differently because the thing on the left isn't a variable, it's a more general lvalue. The = invokes the `__setitem__` method on the dictionary. This ends up reassigning what the "first" key of the dictionary object refers to, thereby mutating the dict2 object. See this talk: https://www.youtube.com/watch?v=_AEJHKGk9ns – dain Apr 22 '23 at 10:25
  • 1
    It may seem like I'm being pedantic, but this point is crucial to understand, otherwise Python's semantics will seem more mysterious than it really is. It is **not true** that _"by default some variables are barenames and some are pointers"_. On the contrary: **all variables behave the same** with respect to assignment. The difference comes when the left side of the = is not a variable `foo`, but an attribute `foo.bar` or container item `foo[123]` or `foo["bar"]`. These are governed by a handful of rules, which you can+should learn. It is **not** a matter of trial-and-error experimentation. – dain Apr 22 '23 at 10:53
23
>> id(1)
1923344848  # identity of the location in memory where 1 is stored
>> id(1)
1923344848  # always the same
>> a = 1
>> b = a  # or equivalently b = 1, because 1 is immutable
>> id(a)
1923344848
>> id(b)  # equal to id(a)
1923344848

As you can see a and b are just two different names that reference to the same immutable object (int) 1. If later you write a = 2, you reassign the name a to a different object (int) 2, but the b continues referencing to 1:

>> id(2)
1923344880
>> a = 2
>> id(a)
1923344880  # equal to id(2)
>> b
1           # b hasn't changed
>> id(b)
1923344848  # equal to id(1)

What would happen if you had a mutable object instead, such as a list [1]?

>> id([1])
328817608
>> id([1])
328664968  # different from the previous id, because each time a new list is created
>> a = [1]
>> id(a)
328817800
>> id(a)
328817800 # now same as before
>> b = a
>> id(b)
328817800  # same as id(a)

Again, we are referencing to the same object (list) [1] by two different names a and b. However now we can mutate this list while it remains the same object, and a, b will both continue referencing to it

>> a[0] = 2
>> a
[2]
>> b
[2]
>> id(a)
328817800  # same as before
>> id(b)
328817800  # same as before
Andreas K.
  • 9,282
  • 3
  • 40
  • 45
  • 1
    Thanks for introducing id function. This solve many of my doubt. – haudoing Jan 08 '19 at 03:33
  • Is there any way I can make b always point to whatever a is pointing to? i.e. if I were to say `a = 2`, and then b would automatically stop pointing to 1 and instead point to 2. – Anchith Acharya Nov 06 '20 at 16:57
13

From one point of view, everything is a pointer in Python. Your example works a lot like the C++ code.

int* a = new int(1);
int* b = a;
a = new int(2);
cout << *b << endl;   // prints 1

(A closer equivalent would use some type of shared_ptr<Object> instead of int*.)

Here's an example: I want form.data['field'] and form.field.value to always have the same value. It's not completely necessary, but I think it would be nice.

You can do this by overloading __getitem__ in form.data's class.

dan04
  • 87,747
  • 23
  • 163
  • 198
  • `form.data` isn't a class. Is it necessary to make it one, or can I override it on the fly? (It's just a python dict) Also, data would have to have a reference back to `form` to access the fields... which makes implementing this ugly. – mpen Jun 24 '10 at 03:20
6

This is a python pointer (different of c/c++)

>>> a = lambda : print('Hello')
>>> a
<function <lambda> at 0x0000018D192B9DC0>
>>> id(a) == int(0x0000018D192B9DC0)
True
>>> from ctypes import cast, py_object
>>> cast(id(a), py_object).value == cast(int(0x0000018D192B9DC0), py_object).value
True
>>> cast(id(a), py_object).value
<function <lambda> at 0x0000018D192B9DC0>
>>> cast(id(a), py_object).value()
Hello
Henry
  • 577
  • 4
  • 9
1

I wrote the following simple class as, effectively, a way to emulate a pointer in python:

class Parameter:
    """Syntactic sugar for getter/setter pair
    Usage:

    p = Parameter(getter, setter)

    Set parameter value:
    p(value)
    p.val = value
    p.set(value)

    Retrieve parameter value:
    p()
    p.val
    p.get()
    """
    def __init__(self, getter, setter):
        """Create parameter

        Required positional parameters:
        getter: called with no arguments, retrieves the parameter value.
        setter: called with value, sets the parameter.
        """
        self._get = getter
        self._set = setter

    def __call__(self, val=None):
        if val is not None:
            self._set(val)
        return self._get()

    def get(self):
        return self._get()

    def set(self, val):
        self._set(val)

    @property
    def val(self):
        return self._get()

    @val.setter
    def val(self, val):
        self._set(val)

Here's an example of use (from a jupyter notebook page):

l1 = list(range(10))
def l1_5_getter(lst=l1, number=5):
    return lst[number]

def l1_5_setter(val, lst=l1, number=5):
    lst[number] = val

[
    l1_5_getter(),
    l1_5_setter(12),
    l1,
    l1_5_getter()
]

Out = [5, None, [0, 1, 2, 3, 4, 12, 6, 7, 8, 9], 12]

p = Parameter(l1_5_getter, l1_5_setter)

print([
    p(),
    p.get(),
    p.val,
    p(13),
    p(),
    p.set(14),
    p.get()
])
p.val = 15
print(p.val, l1)

[12, 12, 12, 13, 13, None, 14]
15 [0, 1, 2, 3, 4, 15, 6, 7, 8, 9]

Of course, it is also easy to make this work for dict items or attributes of an object. There is even a way to do what the OP asked for, using globals():

def setter(val, dict=globals(), key='a'):
    dict[key] = val

def getter(dict=globals(), key='a'):
    return dict[key]

pa = Parameter(getter, setter)
pa(2)
print(a)
pa(3)
print(a)

This will print out 2, followed by 3.

Messing with the global namespace in this way is kind of transparently a terrible idea, but it shows that it is possible (if inadvisable) to do what the OP asked for.

The example is, of course, fairly pointless. But I have found this class to be useful in the application for which I developed it: a mathematical model whose behavior is governed by numerous user-settable mathematical parameters, of diverse types (which, because they depend on command line arguments, are not known at compile time). And once access to something has been encapsulated in a Parameter object, all such objects can be manipulated in a uniform way.

Although it doesn't look much like a C or C++ pointer, this is solving a problem that I would have solved with pointers if I were writing in C++.

Leon Avery
  • 856
  • 2
  • 8
  • 20
1

The reason I'm posting another answer is that none of the answers use the locals() function and there are a lot of huge classes out there that don't exactly do what they're supposed to do: directly change the pointed variable itself.

Remember that a pointer is not a variable that is always the same as another variable, but just a variable that links to another variable. This means that a pointer does not change even if the pointed variable is changed, directly or indirectly (for example by a pointer)

Indeed you can't just make a fully working pointer in one line of code, but after some research it turned out not to be that extremely difficult.


If you want to make all edge cases work, there must be at least 2 features:

  1. Any valid variable name in any scope should work
  2. Very logical perhaps, but a pointer must always point!

If you want feature 1 to work you need to figure out a way to create, change or delete a variable through a function. This is possible through the locals() function. this function returns a dict containing all variables in the current scope. If you change this dict, the variables will also be changed. So:

a = 0 # locals()["a"] == 0
lcs = locals() # lcs == {..., "a": 0, ...}
lcs["a"] = 1 # So a == 1 now
print(a) # will print 1

So the way to create, change or delete a variable through a function is:

locals().update({"name": "value"}) # create var 'name' with value 'value'
locals().update({"name": "other value"}) # change value of var 'name' to 'other value'
locals().pop("name") # delete var 'name'

I've been stuck on this point for a long time, because the difficulty is that you always have to call an function to get the value of a variable.

Until I figured out that the pointer itself could be that function! that way the pointer is a function in a variable. I got that idea when I realized that pointers in C have an asterisk, so it's not a big deal if there are a few things different from a normal variable. Then you also don't need to write or import huge scripts.


So I made a function that returns a semi-pointer:

def pointer(name, lcs: dict):
    return lambda *args: (lcs.get(name)) if len(args) == 0 else (lcs.update({name: args[0]}))  # if there are no args, get the value of the pointed variable, else, set the value

Usage of this function:

a = 0 # set a to 0

# create the pointer:
b = pointer("a", locals())  # locals() is to make sure that the function only modifies the current scope

a = 1 # set a to 1

print(b) # will print <function add_pointer.<locals>.<lambda> at 0x000001DC04C39D00>
print(b()) # will print 1

b(2) # set a to 2
print(a) # will print 2

It's just 2 lines of extra code!

0

The following code emulates exactly the behavior of pointers in C:

from collections import deque # more efficient than list for appending things
pointer_storage = deque()
pointer_address = 0

class new:    
    def __init__(self):
        global pointer_storage    
        global pointer_address

        self.address = pointer_address
        self.val = None        
        pointer_storage.append(self)
        pointer_address += 1


def get_pointer(address):
    return pointer_storage[address]

def get_address(p):
    return p.address

null = new() # create a null pointer, whose address is 0    

Here are examples of use:

p = new()
p.val = 'hello'
q = new()
q.val = p
r = new()
r.val = 33

p = get_pointer(3)
print(p.val, flush = True)
p.val = 43
print(get_pointer(3).val, flush = True)

But it's now time to give a more professional code, including the option of deleting pointers, that I've just found in my personal library:

# C pointer emulation:

from collections import deque # more efficient than list for appending things
from sortedcontainers import SortedList #perform add and discard in log(n) times


class new:      
    # C pointer emulation:
    # use as : p = new()
    #          p.val             
    #          p.val = something
    #          p.address
    #          get_address(p) 
    #          del_pointer(p) 
    #          null (a null pointer)

    __pointer_storage__ = SortedList(key = lambda p: p.address)
    __to_delete_pointers__ = deque()
    __pointer_address__ = 0 

    def __init__(self):      

        self.val = None 

        if new.__to_delete_pointers__:
            p = new.__to_delete_pointers__.pop()
            self.address = p.address
            new.__pointer_storage__.discard(p) # performed in log(n) time thanks to sortedcontainers
            new.__pointer_storage__.add(self)  # idem

        else:
            self.address = new.__pointer_address__
            new.__pointer_storage__.add(self)
            new.__pointer_address__ += 1


def get_pointer(address):
    return new.__pointer_storage__[address]


def get_address(p):
    return p.address


def del_pointer(p):
    new.__to_delete_pointers__.append(p)

null = new() # create a null pointer, whose address is 0
MikeTeX
  • 529
  • 4
  • 18
  • I think you've just boxed the values in a strange way. – mpen Aug 26 '19 at 18:00
  • You mean: a "clever way" or a "not clever way" ? – MikeTeX Aug 26 '19 at 18:37
  • Uhhh... I'm struggling to see a valid use-case for a global storage indexed by a random number. – mpen Aug 26 '19 at 18:41
  • Example of use: I am an algorithm engineer and I have to work with programmers. I work with Python and they work with C++. Sometimes, they ask me to write an algorithm for them, and I write it as close to C++ as possible for their convenience. Pointers are useful e.g. for binary trees etc. – MikeTeX Aug 26 '19 at 18:45
  • Note: if the global storage bother, you can include it as a global variable at the level of the class itself, which is probably more elegant. – MikeTeX Aug 26 '19 at 18:47
  • Interesting. I've never heard of such a profession. Why not just write it in C++ for them, instead of writing Python pseudo-c++ and then letting them port it? – mpen Aug 26 '19 at 19:18
  • You never heard about algorithm engineers???? well, Python is much more convenient to work with (interactive debugging, clear syntax etc.), and I am much more used with Python than with C++. – MikeTeX Aug 26 '19 at 19:24
  • No, not one that exclusively writes algorithms for other engineers. Normally writing algorithms is just part of normal software engineering. – mpen Aug 26 '19 at 19:27
  • I think it is quite usual algorithm engineers have their work translated from Matlab or Python to a compiled language by programmers. – MikeTeX Aug 26 '19 at 19:35
  • Oh yeah.. sometimes people prototype in other languages, just never considered it'd be a dedicated job :-) Makes sense. – mpen Aug 26 '19 at 22:01
-1

I don't know if my comment will help or not but if you want to use pointers in python, you can use dictionaries instead of variables

Let's say in your example will be

a = {'value': 1}

b = {'value': 2}

then you changed a to 2

a['value'] = 2

print(a) #{'value': 2}
  • This has nothing to do with pointer or even trying to connect `a` and `b`. Change the second line into b = a makes much more sense but still, not so related to the question. – yuji Jul 19 '22 at 16:21