web-dev-qa-db-fra.com

Comment imprimer un nom de variable en python?

Disons que j'ai une variable nommée choice elle est égale à 2. Comment pourrais-je accéder au nom de la variable? Quelque chose d'équivalent à

In [53]: namestr(choice)
Out[53]: 'choice'

à utiliser pour créer un dictionnaire. Il y a un bon moyen de le faire et ça me manque juste.

MODIFIER:

La raison en est ainsi. J'exécute des trucs d'analyse de données où j'appelle le programme avec plusieurs paramètres que je voudrais Tweak, ou pas Tweak, au moment de l'exécution. J'ai lu les paramètres que j'ai utilisés lors de la dernière exécution à partir d'un fichier .config formaté comme

filename
no_sig_resonance.dat

mass_peak
700

choice
1,2,3

Lorsque vous êtes invité à entrer des valeurs, la valeur précédemment utilisée s'affiche et une entrée de chaîne vide utilise la valeur précédemment utilisée.

Ma question vient du fait que lorsqu'il s'agit d'écrire le dictionnaire, ces valeurs ont été numérisées. Si un paramètre est nécessaire, je lance get_param qui accède au fichier et trouve le paramètre.

Je pense que j'éviterai le problème tous ensemble en lisant une fois le fichier .config et en produisant un dictionnaire à partir de cela. J'ai évité cela à l'origine pour ... des raisons dont je ne me souviens plus. Situation parfaite pour mettre à jour mon code!

61
physicsmichael

Si vous insistez, voici une horrible solution basée sur l'inspection.

import inspect, re

def varname(p):
  for line in inspect.getframeinfo(inspect.currentframe().f_back)[3]:
    m = re.search(r'\bvarname\s*\(\s*([A-Za-z_][A-Za-z0-9_]*)\s*\)', line)
    if m:
      return m.group(1)

if __== '__main__':
  spam = 42
  print varname(spam)

J'espère que cela vous inspirera à réévaluer le problème que vous avez et à chercher une autre approche.

90
Constantin

Pour répondre à votre question d'origine:

def namestr(obj, namespace):
    return [name for name in namespace if namespace[name] is obj]

Exemple:

>>> a = 'some var'
>>> namestr(a, globals())
['a']

Comme @ rbright l'a déjà souligné quoi que vous fassiez, il y a probablement de meilleures façons de le faire.

59
jfs

Vous ne pouvez pas, car il n'y a pas de variables dans Python mais seulement des noms.

Par exemple:

> a = [1,2,3]
> b = a
> a is b
True

Laquelle de ces deux est maintenant la bonne variable? Il n'y a pas de différence entre a et b.

Il y a eu une question similaire avant.

13
Georg Schölly

Si vous essayez de faire cela, cela signifie que vous faites quelque chose de mal. Pensez à utiliser un dict à la place.

def show_val(vals, name):
    print "Name:", name, "val:", vals[name]

vals = {'a': 1, 'b': 2}
show_val(vals, 'b')

Sortie:

Name: b val: 2
10
recursive

Plutôt que de demander des détails sur une solution spécifique, je recommande de décrire le problème auquel vous êtes confronté; Je pense que vous obtiendrez de meilleures réponses. Je dis cela car il y a presque certainement une meilleure façon de faire tout ce que vous essayez de faire. L'accès aux noms de variables de cette manière n'est généralement pas nécessaire pour résoudre des problèmes dans n'importe quelle langue.

Cela dit, tous vos noms de variables sont déjà dans des dictionnaires accessibles via les fonctions intégrées locals et globals . Utilisez la bonne pour la portée que vous inspectez.

L'un des rares idiomes courants pour inspecter ces dictionnaires est l'interpolation de chaînes facile:

>>> first = 'John'
>>> last = 'Doe'
>>> print '%(first)s %(last)s' % globals()
John Doe

Ce genre de chose a tendance à être un peu plus lisible que les alternatives même si cela nécessite d'inspecter les variables par leur nom.

7
Ryan Bright

Pour la question révisée de la lecture des paramètres de configuration, je vous recommande fortement de vous épargner du temps et des efforts et d'utiliser ConfigParser ou (mon outil préféré) ConfigObj .

Ils peuvent faire tout ce dont vous avez besoin, ils sont faciles à utiliser et quelqu'un d'autre s'est déjà demandé comment les faire fonctionner correctement!

2
James Brady

Est-ce que quelque chose comme ça fonctionnera pour vous?

>>> def namestr(**kwargs):
...     for k,v in kwargs.items():
...       print "%s = %s" % (k, repr(v))
...
>>> namestr(a=1, b=2)
a = 1
b = 2

Et dans votre exemple:

>>> choice = {'key': 24; 'data': None}
>>> namestr(choice=choice)
choice = {'data': None, 'key': 24}
>>> printvars(**globals())
__builtins__ = <module '__builtin__' (built-in)>
__= '__main__'
__doc__ = None
namestr = <function namestr at 0xb7d8ec34>
choice = {'data': None, 'key': 24}
2
myroslav

Avec une évaluation enthousiaste, les variables deviennent essentiellement leurs valeurs à chaque fois que vous les regardez (pour paraphraser). Cela dit, Python a intégré espaces de noms . Par exemple, locals () retournera un dictionnaire mappant les noms des variables d'une fonction à leurs valeurs et globals ( ) fait de même pour un module. Ainsi:

for name, value in globals().items():
    if value is unknown_variable:
        ... do something with name

Notez que vous n'avez pas besoin d'importer quoi que ce soit pour pouvoir accéder aux sections locales () et globales ().

En outre, s'il existe plusieurs alias pour une valeur, l'itération dans un espace de noms ne trouve que le premier.

1
Nikhil Chelliah