55 votes

Simuler des pointeurs en Python

Je suis en train de faire de la compilation croisée dans la maison de la langue(dih) de Python.

L'un des dih caractéristiques est les pointeurs et les références qui se comportent comme vous vous attendez de C ou de C++.

Par exemple, vous pouvez faire ceci:

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

Est-il possible de reproduire cette fonctionnalité en Python.

Je tiens à souligner que je crois que j'ai confondu un peu de gens. Je ne veux pas de pointeurs en Python. Je voulais juste avoir une idée de l'Python experts, ce Python je devrait générer pour simuler le cas, je l'ai montré ci-dessus

Mon Python n'est pas la plus grande, mais jusqu'à présent, mon exploration n'a pas abouti à quelque chose de prometteur:(

Je tiens à souligner que nous sommes à la recherche à passer de nos dih plus courante de la langue, donc nous ne sommes pas vraiment lié à Python si quelqu'un peut suggérer une autre langue qui peut être plus approprié.

83voto

ephemient Points 87003

Cela peut être fait explicitement.

 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
 

24voto

Stephan202 Points 27707

Vous voudrez peut-être lire les noms de variables sémantiques de Python à partir d'une perspective C ++ . La ligne du bas: Toutes les variables sont des références .

Plus précisément, ne pensez pas en termes de variables, mais en termes d'objets qui peuvent être nommés .

14voto

Glenn Maynard Points 24451

Si vous êtes à la compilation d'un C-comme la langue, de dire:

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

en Python, puis tous les "tout en Python est une référence" choses " est un abus de langage.

C'est vrai que tout en Python est une référence, mais le fait que de nombreux types de base (entiers, chaînes de caractères) sont immuables efficacement annule cette pour de nombreux cas. Il n'y a pas de direct façon de mettre en œuvre le ci-dessus en Python.

Maintenant, vous pouvez le faire indirectement: pour toute immuable du type, de l'envelopper dans un mutable type. Ephemient la solution fonctionne, mais souvent, je viens de le faire:

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

(Je l'ai fait ce travail autour de Python est le manque de "non" dans le 2.x quelques fois.)

Cela implique beaucoup plus généraux: chaque immuable type (ou de chaque type, si vous n'essayez pas de les distinguer) soudain crée une liste (ou un autre objet conteneur), de sorte que vous êtes à l'augmentation de la surcharge pour les variables de manière significative. Individuellement, il n'est pas beaucoup, mais il va ajouter jusqu'à quand appliqué à l'ensemble de la base de code.

Vous pouvez réduire ce en seulement emballage immuable types, mais alors vous aurez besoin de garder une trace des variables de sortie sont enveloppés et qui ne le sont pas, de sorte que vous pouvez accéder à la valeur de "a" ou "a[0]" de manière appropriée. Il va probablement s'arracher les cheveux.

Quant à savoir si c'est une bonne idée ou pas-qui dépend de pourquoi vous le faites. Si vous voulez juste quelque chose pour exécuter une machine virtuelle, j'aurais tendance à dire non. Si vous voulez être en mesure d'appeler à votre langue à partir de Python, je vous suggère de prendre votre VM existantes et la création de liaisons Python pour elle, de sorte que vous pouvez accéder et de les appeler à partir de Python.

10voto

Mark Mikofski Points 2503

Presque exactement comme ephemient réponse, qui j'ai voté, vous pouvez utiliser Python builtin propriété de la fonction. Il va faire quelque chose près semblable à l' ref de la classe dans ephemient réponse, sauf que maintenant, au lieu d'être obligé d'utiliser get et set méthodes pour accéder à un ref de l'instance, il vous suffit d'appeler les attributs de votre instance à laquelle vous avez assigné comme des propriétés dans la définition de classe. À partir de Python docs (sauf que j'ai changé de C à ptr):

class ptr(object):
    def __init__(self):
        self._x = None
    def getx(self):
        return self._x
    def setx(self, value):
        self._x = value
    def delx(self):
        del self._x
    x = property(getx, setx, delx, "I'm the 'x' property.")

Les deux méthodes fonctionnent comme un C pointeur, sans avoir recours à l' global. Par exemple, si vous avez une fonction qui prend un pointeur:

def do_stuff_with_pointer(pointer, property='x', value):
    setattr(pointer, property, value)

ou à l'aide de ephemient solution:

def do_stuff_with_ref(ref, value):
    ref.set(value)

Les deux vont changer le contenu stocké derrière ref ou ptr des cas.

De l'autre, et totalement fou option serait d'utiliser Python ctypes. Essayez ceci:

from ctypes import *
a = py_object([1,2]) # a has an array 
b = a                # b points to a
b.value = 2          # derefernce b to store 2 in a
print a.value        # outputs 2
print b.value        # outputs 2

ou si vous voulez vraiment faire de la fantaisie

from ctypes import *
a = py_object([1,2])   # a has an array 
b = pointer(a)         # b points to a
b.contents.value = 2   # derefernce b to store 2 in a
print a.value          # outputs 2
print b.contents.value # outputs 2

ce qui est plus proche de l'OP de la demande d'origine. fou!

4voto

Unknown Points 22789

Comme d’autres l’ont dit, toutes les variables Python sont essentiellement des pointeurs.

La clé pour comprendre cela du point de vue du C consiste à utiliser l'inconnu de nombreuses fonctions id (). Il vous indique l'adresse de la variable.

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

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

>>> id(b)
28354600
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X