102 votes

Convertir le nom de la variable en chaîne ?

J'aimerais convertir un nom de variable python en son équivalent en chaîne de caractères, comme indiqué. Comment faire ?

var = {}
print ???  # Would like to see 'var'
something_else = 3
print ???  # Would print 'something_else'

1 votes

Pourriez-vous préciser ce que vous essayez de faire ? Il semble que vous demandiez comment résoudre un problème de la mauvaise manière. Il y a aussi une question similaire, mais à propos de Ruby stackoverflow.com/questions/58482/ruby-get-a-variables-name

1 votes

J'ai vérifié cette question car, en utilisant RPy2, je veux passer une variable Python avec un nom R éponyme. Un exemple inutile (mais proche de mon application) : def to_R( py_var ): r.assign( 'py_var', py_var ) pour assigner les données de (Py) py_var à l'environnement R et avoir le même nom. Ce serait utile pour moi de le faire à la place, r.assign( py_var.stringof, py_var ) a la D puisque le nom de la variable passée à ma fn to_r n'est pas nécessairement py_var .

4 votes

L'une des façons de l'utiliser est lorsqu'une déclaration Assert échoue. Vous pouvez fournir à l'utilisateur le nom exact de la variable en question tout en conservant votre code générique, par exemple AssertionError : 'something_else' must be a number greater than 5 (erreur d'affirmation : 'quelque chose_autre' doit être un nombre supérieur à 5). Vous pouvez alors tester chaque variable qui doit être supérieure à 5 et obtenir le nom de la variable dans le message AssertionError.

2voto

ZevGriner Points 359

Voici une variante succincte qui vous permet de spécifier n'importe quel répertoire. Le problème avec l'utilisation de répertoires pour trouver quelque chose est que plusieurs variables peuvent avoir la même valeur. Ce code renvoie donc une liste de variables possibles.

def varname( var, dir=locals()):
  return [ key for key, val in dir.items() if id( val) == id( var)]

2voto

restrepo Points 370

En utilisant le opérateur de déballage :

>>> def tostr(**kwargs):
    return kwargs

>>> var = {}
>>> something_else = 3
>>> tostr(var = var,something_else=something_else)
{'var' = {},'something_else'=3}

2voto

Hàm Nghi Points 67

Je ne sais pas si c'est correct ou non, mais cela a fonctionné pour moi.

def varname(variable):
    for name in list(globals().keys()):
        expression = f'id({name})'
        if id(variable) == eval(expression):
            return name

2voto

Nomesis Points 21

C'est possible dans une certaine mesure. la réponse est similaire à la solution de @tamtam . L'exemple donné suppose les hypothèses suivantes -

  • Vous recherchez une variable par sa valeur
  • La variable a une valeur distincte
  • La valeur est dans l'espace de noms global

Exemple :

testVar         = "unique value"
varNameAsString = [k for k,v in globals().items() if v == "unique value"]
#
# the variable "varNameAsString" will contain all the variable name that matches
# the value "unique value"
# for this example, it will be a list of a single entry "testVar"
#
print(varNameAsString)

Sortie : ['testVar']

Vous pouvez étendre cet exemple à tout autre type de variable ou de données

1voto

Erik Aronesty Points 2223

J'aimerais souligner un cas d'utilisation qui n'est pas un anti-modèle, et il n'y a pas de meilleure façon de le faire.

Il semble qu'il s'agisse d'une manquant en python.

Il existe un certain nombre de fonctions, telles que patch.object qui prennent le nom d'une méthode ou d'une propriété à patcher ou à laquelle il faut accéder.

Considérez ceci :

patch.object(obj, "method_name", new_reg)

Cela peut potentiellement déclencher des "fausses réussites" lorsque vous changez le nom d'une méthode. IE : vous pouvez envoyer un bogue, vous pensiez que vous étiez testing.... simplement à cause d'un mauvais refactoring du nom de la méthode.

Réfléchissez maintenant : varname . Il pourrait s'agir d'une fonction intégrée efficace. Mais pour l'instant, elle peut fonctionner en itérant un objet ou le cadre de l'appelant :

Maintenant, votre appel peut être :

patch.member(obj, obj.method_name, new_reg)

Et la fonction patch peut être appelée :

varname(var, obj=obj)

Cela permettrait d'affirmer que la var est liée à l'obj et de renvoyer le nom du membre. Ou si l'obj n'est pas spécifié, utiliser le stack frame de l'appelant pour le dériver, etc.

Il pourrait être intégré de manière efficace à un moment donné, mais voici une définition qui fonctionne. C'est délibérément que je n'ai pas soutenu composants Il est donc facile de l'ajouter :

N'hésitez pas à placer ceci dans un paquet appelé varname.py et l'utiliser dans vos appels à patch.object :

patch.object(obj, varname(obj, obj.method_name), new_reg)

Note : ceci a été écrit pour python 3.

import inspect

def _varname_dict(var, dct):
    key_name = None
    for key, val in dct.items():
        if val is var:
            if key_name is not None:
                raise NotImplementedError("Duplicate names not supported %s, %s" % (key_name, key))
            key_name = key
    return key_name

def _varname_obj(var, obj):
    key_name = None
    for key in dir(obj):
        val = getattr(obj, key)
        equal = val is var
        if equal:
            if key_name is not None:
                raise NotImplementedError("Duplicate names not supported %s, %s" % (key_name, key))
            key_name = key
    return key_name

def varname(var, obj=None):
    if obj is None:
        if hasattr(var, "__self__"):
            return var.__name__
        caller_frame = inspect.currentframe().f_back
        try:
            ret = _varname_dict(var, caller_frame.f_locals)
        except NameError:
            ret = _varname_dict(var, caller_frame.f_globals)
    else:
        ret = _varname_obj(var, obj)
    if ret is None:
        raise NameError("Name not found. (Note: builtins not supported)")
    return ret

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