6
votes

Stocker une référence à une référence à Python?

Utiliser Python, existe-t-il un moyen de stocker une référence à une référence, de sorte que je puisse changer ce que cette référence fait référence dans un autre contexte? Par exemple, supposons que j'ai la classe suivante:

f = Foo()
rStandalone = Reassigner(f.standalone) # presumably this syntax might change
rIndex = Reassigner(f.lst[1])
rStandalone.reassign(7)
rIndex.reassign(9)


6 commentaires

Je pense que l'ensemble des références est que vous ne devriez pas être capable de le faire.


Comment avez-vous l'intention d'utiliser cela?


Si vous voulez C ++, vous savez où le trouver ...


@FogleBird Le plan était dans une affectation différée de références nommées. Un tas d'objets est chargé à partir de fichiers XML, ce qui peut faire référence à d'autres objets par nom. Si vous faites référence à un nom qui n'existe pas encore, vous obtenez un objet d'espace réservé et soyez coincé dans une table de choses avec des références dangereuses. Si vous rencontrez plus tard la définition de ce nom, vous suivriez toutes les entrées appropriées du tableau des références en suspens et réaffectait les valeurs d'espace réservé aux objets nouvellement créés. Il existe des solutions avec des couches d'indirection, mais j'espérais quelque chose de direct.


@professional_yet_not_trackable qui est exactement (modulo xml) Ce que je faisais quand j'ai rencontré ce problème et j'ai trouvé la solution qui est maintenant ma réponse. Soutient ma théorie selon laquelle il existe extrêmement peu d'utilisations pour cela.


Je fais habituellement une charge à deux passes pour ce scénario. Tout d'abord, chargez tous les objets (et utilisez un dict pour mapper ID => Objet), puis effectuez une autre passe pour établir les liens entre les objets.


4 Réponses :


6
votes

En bref, ce n'est pas possible. Du tout. L'équivalent le plus proche consiste à enregistrer une référence à l'objet dont le membre / élément que vous souhaitez réaffecter, plus le nom d'attribut / index / clé, puis utilisez setattr code> / SETITEM code>. Cependant, cela donne une syntaxe assez différente, et vous devez différencier entre les deux:

class AttributeReassigner:
    def __init__(self, obj, attr):
        # use your imagination
    def reassign(self, val):
        setattr(self.obj, self.attr, val)

class ItemReassigner:
    def __init__(self, obj, key):
        # use your imagination
    def reassign(self, val):
        self.obj[self.key] = val

f = Foo()
rStandalone = AttributeReassigner(f, 'standalone')
rIndex = ItemReassigner(f.lst, 1)
rStandalone.reassign(7)
rIndex.reassign(9)


0 commentaires

2
votes

réponse simple: vous ne pouvez pas. Réponse compliquée: vous pouvez utiliser Lambdas. Sorte de. xxx


3 commentaires

Pourquoi __ settitem __ et pas seulement l'accès direct de l'article avec [] ?


Duh, parce que ça ne serait pas une lambda


Comme Eric semble avoir réalisé :), f.lst [1] = la valeur n'est pas une expression, mais f.lst .__ Settitem __ (1, valeur) est.



0
votes

Cela fonctionnerait pour le contenu des objets de conteneur. Si cela ne vous dérange pas d'ajouter un niveau d'indirection à vos variables (que vous auriez besoin dans le boîtier du pointeur à pointer-to-Pointer), vous pouvez:

Class Reassigner(object):

    def __init__(self, target):
        self.target = target
    def reassign(self, value):
        self.target.val = value


0 commentaires

1
votes

Si vous devez différer des tâches; Vous pouvez utiliser functools.partial (ou juste lambda ): xxx

si réaffectation est la seule opération ; Vous n'avez pas besoin d'une nouvelle classe. Les fonctions sont des citoyens de première classe à Python: vous pouvez les affecter à une variable, stocker dans une liste, passer comme arguments, etc.


2 commentaires

Opérateur.Setitem rend le cas de l'élément symétrique à l'affaire Attribut, et semble mieux.


@Delnan: J'y ai pensé, mais je voulais démontrer que partiel fonctionne également sur des méthodes (non seulement des fonctions) et il existe également des méthodes spéciales en Python. Sinon opérateur.Setitem peut être préférable car il reporte le fichier __ settitem __ recherche (exceptions sont sur le site de l'appelant).