Je sais que Python n'a pas de pointeurs, mais y a-t-il un moyen d'avoir ce rendement à la 2
place
>>> a = 1
>>> b = a # modify this line somehow so that b "points to" a
>>> a = 2
>>> b
1
?
Voici un exemple: je veux form.data['field']
et form.field.value
avoir toujours la même valeur. Ce n'est pas tout à fait nécessaire, mais je pense que ce serait bien.
En PHP, par exemple, je peux faire ceci:
<?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
Production:
GeorgeGeorgeRalphRalph
Ou comme ça en C ++ (je pense que c'est vrai, mais mon C ++ est rouillé):
#include <iostream>
using namespace std;
int main() {
int* a;
int* b = a;
*a = 1;
cout << *a << endl << *b << endl; # 1 1
return 0;
}
a, b = b, a
.Réponses:
C'est faisable, car cela implique des noms décorés et une indexation - c'est-à-dire des constructions complètement différentes des noms de barres
a
etb
que vous demandez, et pour avec votre demande est totalement impossible. Pourquoi demander quelque chose d'impossible et de totalement différent de la chose (possible) que vous voulez réellement ?!Peut-être que vous ne réalisez pas à quel point les noms de barres et les noms décorés sont radicalement différents. Lorsque vous faites référence à un nom de barre
a
, vous obtenez exactement l'objet auquel aa
été lié la dernière fois dans cette portée (ou une exception s'il n'a pas été lié dans cette portée) - c'est un aspect si profond et fondamental de Python qu'il peut peut-être pas être subverti. Lorsque vous faites référence à un nom décoréx.y
, vous demandez à un objet ( auquel l'objetx
fait référence) de s'il vous plaît fournir "l'y
attribut" - et en réponse à cette demande, l'objet peut effectuer des calculs totalement arbitraires (et l'indexation est assez similaire: il permet également d'effectuer des calculs arbitraires en réponse).Maintenant, votre exemple de "desiderata réel" est mystérieux parce que dans chaque cas, deux niveaux d'indexation ou d'obtention d'attributs sont impliqués, donc la subtilité dont vous rêvez pourrait être introduite de plusieurs manières. Quels autres attributs est
form.field
censé avoir, par exemple, en plusvalue
? Sans ces.value
calculs supplémentaires , les possibilités comprendraient:et
La présence de
.value
suggère de choisir la première forme, plus une sorte de wrapper inutile:Si de telles affectations
form.field.value = 23
sont également censées définir l'entréeform.data
, alors le wrapper doit devenir plus complexe en effet, et pas du tout inutile:Ce dernier exemple est à peu près aussi proche que possible, en Python, du sens de "pointeur" que vous semblez vouloir - mais il est crucial de comprendre que de telles subtilités ne peuvent jamais fonctionner qu'avec des noms indexés et / ou décorés , jamais avec des noms de barres comme vous l'avez demandé!
la source
Il n'y a aucun moyen que vous puissiez faire cela en changeant uniquement cette ligne. Tu peux faire:
Cela crée une liste, attribue la référence à a, puis b également, utilise la référence a pour définir le premier élément sur 2, puis accède à l'aide de la variable de référence b.
la source
a
etb
la liste, pas la valeur dans la liste. Les variables ne changent pas d'affectation, l'objet est le même objet. S'il a changé, comme dans le cas de la modification de l'entier (dont chacun est des objets différents), ila
serait maintenant attribué à un autre objet et rien n'inciteb
à suivre. Ici, cea
n'est pas réaffecté, mais plutôt une valeur à l'intérieur de l'objet auquel il est affecté change. Puisqu'ilb
est toujours lié à cet objet, il reflétera cet objet et les modifications des valeurs qu'il contient.Ce n'est pas un bug, c'est une fonctionnalité :-)
Quand vous regardez l'opérateur '=' en Python, ne pensez pas en termes d'affectation. Vous n'attribuez pas les choses, vous les liez. = est un opérateur de liaison.
Donc, dans votre code, vous donnez un nom à la valeur 1: a. Ensuite, vous donnez la valeur dans «a» un nom: b. Ensuite, vous liez la valeur 2 au nom «a». La valeur liée à b ne change pas dans cette opération.
Venant de langages de type C, cela peut être déroutant, mais une fois que vous vous y êtes habitué, vous constatez que cela vous aide à lire et à raisonner plus clairement sur votre code: la valeur qui porte le nom `` b '' ne changera pas sauf si vous le changer explicitement. Et si vous faites un 'import this', vous constaterez que le Zen de Python déclare qu'Explicit est meilleur qu'implicite.
Notez également que les langages fonctionnels tels que Haskell utilisent également ce paradigme, avec une grande valeur en termes de robustesse.
la source
a = 1; b = a; a = 2;
est exactement le même en Python, C et Java: b vaut 1. Pourquoi ce focus sur "= n'est pas une affectation, c'est une liaison"?a
etb
alors qu'en Python, ils font tous les deux référence au même "1" (je pense). Ainsi, si vous pouviez changer la valeur de 1 (comme pour les objets), ce serait différent. Ce qui conduit à des problèmes de boxe / déballage étranges, j'entends.Oui! il existe un moyen d'utiliser une variable comme pointeur en python!
Je suis désolé de dire que de nombreuses réponses étaient partiellement fausses. En principe, chaque assignation égale (=) partage l'adresse mémoire (vérifiez la fonction id (obj)), mais en pratique ce n'est pas le cas. Il y a des variables dont le comportement égal ("=") fonctionne en dernier terme comme une copie de l'espace mémoire, principalement dans des objets simples (par exemple, un objet "int"), et d'autres dans lesquels non (par exemple des objets "liste", "dict") .
Voici un exemple d'affectation de pointeur
Voici un exemple d'affectation de copie
L'affectation de pointeurs est un outil assez utile pour créer des alias sans gaspiller de mémoire supplémentaire, dans certaines situations pour exécuter du code confortable,
mais il faut être conscient de cette utilisation pour éviter les erreurs de code.
Pour conclure, par défaut, certaines variables sont des noms de barres (objets simples comme int, float, str, ...), et certaines sont des pointeurs lorsqu'elles sont assignées entre elles (par exemple dict1 = dict2). Comment les reconnaître? essayez simplement cette expérience avec eux. Dans les IDE avec le panneau de l'explorateur de variables, il semble généralement être l'adresse mémoire ("@axbbbbbb ...") dans la définition des objets du mécanisme de pointeur.
Je suggère d'enquêter sur le sujet. Il y a beaucoup de gens qui en savent bien plus sur ce sujet. (voir module "ctypes"). J'espère que c'est utile. Profitez de la bonne utilisation des objets! Cordialement, José Crespo
la source
Comme vous pouvez le voir,
a
il neb
s'agit que de deux noms différents qui font référence au même objet immuable (int)1
. Si vous écrivez plus tarda = 2
, vous réaffectez le noma
à un objet différent (int)2
, maisb
continue de faire référence à1
:Que se passerait-il si vous aviez un objet mutable à la place, comme une liste
[1]
?Encore une fois, nous faisons référence au même objet (liste)
[1]
par deux noms différentsa
etb
. Mais maintenant , nous pouvons muter cette liste alors qu'il reste le même objet, eta
,b
sera à la fois continuer le référencement à cela source
D'un point de vue, tout est un pointeur en Python. Votre exemple fonctionne beaucoup comme le code C ++.
(Un équivalent plus proche utiliserait un type de
shared_ptr<Object>
au lieu deint*
.)Vous pouvez le faire en surchargeant
__getitem__
dansform.data
la classe de.la source
form.data
n'est pas une classe. Est-il nécessaire d'en créer un ou puis-je le remplacer à la volée? (C'est juste un dict python) De plus, les données devraient avoir une référenceform
pour accéder aux champs ... ce qui rend l'implémentation moche.Ceci est un pointeur python (différent de c / c ++)
la source
J'ai écrit la classe simple suivante comme, en fait, un moyen d'émuler un pointeur en python:
Voici un exemple d'utilisation (à partir d'une page de notebook jupyter):
Bien sûr, il est également facile de faire ce travail pour les éléments dict ou les attributs d'un objet. Il existe même un moyen de faire ce que l'OP a demandé, en utilisant globals ():
Cela imprimera 2, suivi de 3.
Jouer avec l'espace de noms global de cette manière est une sorte de transparence une idée terrible, mais cela montre qu'il est possible (si cela n'est pas conseillé) de faire ce que l'OP a demandé.
L'exemple est, bien entendu, assez inutile. Mais j'ai trouvé cette classe utile dans l'application pour laquelle je l'ai développée: un modèle mathématique dont le comportement est régi par de nombreux paramètres mathématiques réglables par l'utilisateur, de types divers (qui, parce qu'ils dépendent d'arguments de ligne de commande, ne sont pas connus au moment de la compilation). Et une fois que l'accès à quelque chose a été encapsulé dans un objet Parameter, tous ces objets peuvent être manipulés de manière uniforme.
Bien que cela ne ressemble pas beaucoup à un pointeur C ou C ++, cela résout un problème que j'aurais résolu avec des pointeurs si j'écrivais en C ++.
la source
Le code suivant émule exactement le comportement des pointeurs en C:
Voici des exemples d'utilisation:
Mais il est maintenant temps de donner un code plus professionnel, y compris la possibilité de supprimer des pointeurs, que je viens de trouver dans ma bibliothèque personnelle:
la source