Un moyen plus simple de créer un dictionnaire de variables distinctes?

220

J'aimerais pouvoir obtenir le nom d'une variable sous forme de chaîne mais je ne sais pas si Python a autant de capacités d'introspection. Quelque chose comme:

>>> print(my_var.__name__)
'my_var'

Je veux le faire parce que j'ai un tas de variables que je voudrais transformer en dictionnaire comme:

bar = True
foo = False
>>> my_dict = dict(bar=bar, foo=foo)
>>> print my_dict 
{'foo': False, 'bar': True}

Mais j'aimerais quelque chose de plus automatique que ça.

Python a locals()et vars(), donc je suppose qu'il y a un moyen.

e-satis
la source
31
Étant donné que les gens semblent confus quant à ce qui est demandé, je le répéterai ici parce que c'est une question intéressante. Étant donné un tableau [foo, bar, baz], vous voulez un dictionnaire comme {'foo': foo, 'bar': bar, 'baz': baz} et vous ne savez pas quelles sont les variables du tableau. le questionneur demande donc comment obtenir le nom d'une variable sous forme de chaîne en python. J'espère maintenant que les gens pourront naviguer à travers les réponses horribles pour trouver les quelques endroits où vous apprendrez pourquoi ce n'est pas vraiment une bonne idée en python.
Jesse Sherlock
3
Duplicata possible: stackoverflow.com/questions/544919/…
Anderson Green
2
Une utilisation de la technique consisterait à rationaliser les appels de formatage de chaînes: '{var} {foo} {bar}'. Format (** named (var, foo, bar)), où "named" est la fonction qui renvoie le dict ( 'var': var) comme décrit.
Gordon Bean
4
Je pense que c'est en fait une mauvaise question parce que les noms sont mappés sur des objets, vous pouvez avoir plusieurs noms pointant vers le même objet, et je n'ai jamais vu le besoin d'atteindre l'objectif d'inverser ce mappage. Donc, le fait que la mauvaise réponse soit acceptée ici n'a aucun sens - si une recherche Google vous a amené ici, vous posez clairement la mauvaise question.
Aaron Hall
1
C'est une excellente idée de débogage!
john ktejik

Réponses:

48

Essayez-vous de faire ça?

dict( (name,eval(name)) for name in ['some','list','of','vars'] )

Exemple

>>> some= 1
>>> list= 2
>>> of= 3
>>> vars= 4
>>> dict( (name,eval(name)) for name in ['some','list','of','vars'] )
{'list': 2, 'some': 1, 'vars': 4, 'of': 3}
S.Lott
la source
1
rlotun est plus proche de "l'esprit" initial car il permet de découvrir le nom. Je pourrais utiliser à la fois votre réponse. Ou peut-être utilisez simplement ma putain de main pour taper. Certaines choses ne sont tout simplement pas faites pour être aussi automatisées ...
e-satis
7
@ e-satis: Pour que @ rlotun fonctionne, vous devez fournir la liste des variables. Si vous avez la liste des variables, quel est l'intérêt de "découvrir" leurs noms?
S.Lott
4
Pourquoi évaluer au lieu d'utiliser explicitement les sections locales et globales?
1
@Roger Pate: Parce que je ne pouvais pas comprendre quel était le but de tout l'exercice.
S.Lott
242
Cette réponse ne répond pas à la question posée. Si vous avez la liste des variables, quel est l'intérêt de "découvrir" leurs noms? Pour éviter la duplication afin qu'au lieu de l' print('x: ' + x)un puisse écrire magic_print(x)et avoir la même sortie sans écrire deux fois le nom de la variable.
Piotr Dobrogost
130

Comme dit le déroulement, ce n'est pas vraiment quelque chose que vous faites en Python - les variables sont en fait des mappages de noms aux objets.

Cependant , voici une façon d'essayer de le faire:

 >>> a = 1
 >>> for k, v in list(locals().iteritems()):
         if v is a:
             a_as_str = k
 >>> a_as_str
 a
 >>> type(a_as_str)
 'str'
rlotun
la source
14
Cette idée a du mérite, mais notez que si deux noms de variable font référence à la même valeur (par exemple True), alors un nom de variable involontaire peut être renvoyé.
unutbu
14
Pourquoi id(v) == id(a)au lieu de v is a? Cela échouera pour les objets liés à plusieurs variables, tels que les entiers, les chaînes et tous les types définis par l'utilisateur de manière similaire.
Oui, ce v is aserait un meilleur choix. Et oui, certainement dangereux compte tenu de tous les pièges potentiels qui pourraient survenir! ;-)
rlotun
16
@ e-satis Je suis surpris que vous n'ayez pas marqué cette réponse comme réponse car je suis d'accord avec votre commentaire disant que rlotun est plus proche de "l'esprit" initial car il permet de découvrir le nom . De plus, la réponse de S.Lott ne répond pas du tout à votre question ...
Piotr Dobrogost
2
"exagéré et dangereux" ... et utiliser eval n'est-ce pas?
bug
63

J'ai beaucoup voulu faire ça. Ce hack est très similaire à la suggestion de rlotun, mais c'est un one-liner, ce qui est important pour moi:

blah = 1
blah_name = [ k for k,v in locals().iteritems() if v is blah][0]

Python 3+

blah = 1
blah_name = [ k for k,v in locals().items() if v is blah][0]
keflavich
la source
3
@keflavich J'ai beaucoup aimé cette approche et je l'utilise de temps en temps. Cependant, je ne peux pas le faire fonctionner à l'intérieur des fonctions. J'imagine qu'il existe de "meilleures" façons de le faire, mais aucune n'est aussi simple que nbubis. Avez-vous pu l'utiliser dans les fonctions keflavich? C'est là que je pose une question à ce sujet.
Leo
10
Notez que dans Python 3, iteritems()est remplacé paritems()
Jonathan Wheeler
Ce n'est pas fiable: spam = 1; blah = 1; blah_name = [ k for k,v in locals().items() if v is blah][0]; print(blah_name)Sortiesspam
andreasdr
1
@andreasdr c'est parce que spam = 1, blah = 1; assert spam is blah. La solution se casse lors de la comparaison des types de données primitifs.
JYun
17

Ceci est un hack. Il ne fonctionnera pas sur toutes les distributions d'implémentations Python (en particulier, celles qui n'en ont pas traceback.extract_stack.)

import traceback

def make_dict(*expr):
    (filename,line_number,function_name,text)=traceback.extract_stack()[-2]
    begin=text.find('make_dict(')+len('make_dict(')
    end=text.find(')',begin)
    text=[name.strip() for name in text[begin:end].split(',')]
    return dict(zip(text,expr))

bar=True
foo=False
print(make_dict(bar,foo))
# {'foo': False, 'bar': True}

Notez que ce hack est fragile:

make_dict(bar,
          foo)

(appeler make_dict sur 2 lignes) ne fonctionnera pas.

Au lieu d'essayer de générer le dict à partir des valeurs foo et bar, il serait beaucoup plus Pythonic de générer le dict à partir des noms de variables de chaîne 'foo'et 'bar':

dict([(name,locals()[name]) for name in ('foo','bar')])
unutbu
la source
1
+1 pour le hack intelligent. Bien sûr, le traçage est très lent, il peut donc être lent de l'utiliser.
e-satis
1
+1111111 !!!! Oui, c'est lent, mais lors de l'utilisation pour remplacer print("a_very_long_name: {}'.format(a_very_long_name))qui s'en soucie!
frnhr
14

Ce n'est pas possible en Python, qui n'a vraiment pas de "variables". Python a des noms et il peut y avoir plusieurs noms pour le même objet.

se détendre
la source
oui, je sais, j'ai rendu la question simple, mais je m'attendais à plus de quelque chose comme "get_var_tags (var) [0]".
e-satis
10

Je pense que mon problème aidera à illustrer pourquoi cette question est utile, et il peut donner un peu plus d'informations sur la façon d'y répondre. J'ai écrit une petite fonction pour faire une vérification rapide de la tête en ligne sur diverses variables de mon code. Fondamentalement, il répertorie le nom de la variable, le type de données, la taille et d'autres attributs, afin que je puisse rapidement détecter les erreurs que j'ai faites. Le code est simple:

def details(val):
  vn = val.__name__                 #  If such a thing existed
  vs = str(val)
  print("The Value of "+ str(vn) + " is " + vs)
  print("The data type of " + vn + " is " + str(type(val)))

Donc, si vous avez une situation de dictionnaire / liste / tuple compliquée, il serait très utile que l'interprète retourne le nom de variable que vous avez attribué. Par exemple, voici un dictionnaire étrange:

m = 'abracadabra'
mm=[]    
for n in m:
  mm.append(n)
mydic = {'first':(0,1,2,3,4,5,6),'second':mm,'third':np.arange(0.,10)}



details(mydic)

The Value of mydic is {'second': ['a', 'b', 'r', 'a', 'c', 'a', 'd', 'a', 'b', 'r', 'a'], 'third': array([ 0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9.]), 'first': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]}
The data type of mydic is <type 'dict'>

details(mydic['first'])
The Value of mydic['first'] is (0, 1, 2, 3, 4, 5, 6)]
The data type of mydic['first'] is <type 'list'>

details(mydic.keys())
The Value of mydic.keys() is ['second', 'third', 'first']
The data type of mydic.keys() is <type 'tuple'>

details(mydic['second'][0])
The Value of mydic['second'][0] is a
The data type of mydic['second'][0] is <type 'str'>

Je ne sais pas si je l'ai mis au bon endroit, mais j'ai pensé que cela pourrait aider. J'espère que oui.

TheProletariat
la source
Donc, avec votre vérification de la tête, cela tient-il compte du fait que les variables / noms peuvent pointer vers différentes choses à différents moments dans le code? Par exemple, il myconnectionpourrait s'agir d'une valeur booléenne à un moment donné, d'un entier à un autre moment et d'une connexion socket à un autre moment de l'exécution du code ??
9

J'ai écrit une petite fonction très utile basée sur la réponse à cette question. Je le mets ici au cas où cela serait utile.

def what(obj, callingLocals=locals()):
    """
    quick function to print name of input and value. 
    If not for the default-Valued callingLocals, the function would always
    get the name as "obj", which is not what I want.    
    """
    for k, v in list(callingLocals.items()):
         if v is obj:
            name = k
    print(name, "=", obj)

usage:

>> a = 4
>> what(a)
a = 4
>>|
aquirdturtle
la source
6

Je trouve que si vous avez déjà une liste spécifique de valeurs, c'est la manière décrite par @S. Lotts est le meilleur; cependant, la manière décrite ci-dessous fonctionne bien pour obtenir toutes les variables et classes ajoutées dans le code SANS la nécessité de fournir le nom de la variable bien que vous puissiez les spécifier si vous le souhaitez. Le code peut être étendu pour exclure les classes.

import types
import math  # mainly showing that you could import what you will before d

# Everything after this counts
d = dict(globals())

def kv_test(k,v):
    return (k not in d and 
            k not in ['d','args'] and
            type(v) is not types.FunctionType)

def magic_print(*args):
    if len(args) == 0: 
        return {k:v for k,v in globals().iteritems() if kv_test(k,v)}
    else:
        return {k:v for k,v in magic_print().iteritems() if k in args}

if __name__ == '__main__':
    foo = 1
    bar = 2
    baz = 3
    print magic_print()
    print magic_print('foo')
    print magic_print('foo','bar')

Production:

{'baz': 3, 'foo': 1, 'bar': 2}
{'foo': 1}
{'foo': 1, 'bar': 2}
cdhagmann
la source
6

En python 3, c'est facile

myVariable = 5
for v in locals():
  if id(v) == id("myVariable"):
    print(v, locals()[v])

cela imprimera:

myVariable 5

officialhopsof
la source
Ceci est similaire à l'approche de rlotun mais un peu plus simple
officialhopsof
10
-1. Ouvrez une nouvelle fenêtre d'interpréteur et essayez for v in locals().
Air
Je ne suis pas totalement sûr de ce que tu veux dire?
officialhopsof
4
Cela donnera une erreur: RuntimeError: la taille du dictionnaire a changé pendant l'itération ...
Nizar B.
2
comme vous pouvez le fairefor v in list(locals()):
Phylliida
5

Python3. Utilisez inspect pour capturer l'espace de noms local appelant, puis utilisez les idées présentées ici. Peut renvoyer plus d'une réponse comme cela a été souligné.

def varname(var):
  import inspect
  frame = inspect.currentframe()
  var_id = id(var)
  for name in frame.f_back.f_locals.keys():
    try:
      if id(eval(name)) == var_id:
        return(name)
    except:
      pass
vvxxii
la source
Bonne réponse, mais pour moi c'est mieux avec: ... id (eval (nom, Aucun, frame.f_back.f_locals)) == ...
Emmanuel DUMAS
5

Voici la fonction que j'ai créée pour lire les noms de variables. Il est plus général et peut être utilisé dans différentes applications:

def get_variable_name(*variable):
    '''gets string of variable name
    inputs
        variable (str)
    returns
        string
    '''
    if len(variable) != 1:
        raise Exception('len of variables inputed must be 1')
    try:
        return [k for k, v in locals().items() if v is variable[0]][0]
    except:
        return [k for k, v in globals().items() if v is variable[0]][0]

Pour l'utiliser dans la question spécifiée:

>>> foo = False
>>> bar = True
>>> my_dict = {get_variable_name(foo):foo, 
               get_variable_name(bar):bar}
>>> my_dict
{'bar': True, 'foo': False}
Anna
la source
4

En lisant le fil, j'ai vu énormément de frictions. Il est assez facile de donner une mauvaise réponse, puis laissez quelqu'un donner la bonne réponse. Bref, voici ce que j'ai trouvé.

De: [effbot.org] ( http://effbot.org/zone/python-objects.htm#names )

Les noms sont un peu différents - ce ne sont pas vraiment des propriétés de l'objet, et l'objet lui-même ne sait pas comment il s'appelle.

Un objet peut avoir n'importe quel nombre de noms, ou aucun nom du tout.

Les noms vivent dans des espaces de noms (comme un espace de noms de module, un espace de noms d'instance, l'espace de noms local d'une fonction).

Remarque: il dit que l'objet lui-même ne sait pas comment il s'appelle , donc c'était l'indice. Les objets Python ne sont pas auto-référentiels. Ensuite, il dit: Les noms vivent dans des espaces de noms . Nous l'avons dans TCL / TK. Alors peut-être que ma réponse vous aidera (mais cela m'a aidé)

    jj = 123
    print eval ("'" + str (id (jj)) + "'")
    print dir ()

166707048
['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'jj']

Il y a donc «jj» à la fin de la liste.

Réécrivez le code comme suit:

    jj = 123
    print eval ("'" + str (id (jj)) + "'")
    pour x en dir ():
        id d'impression (eval (x))

161922920
['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'jj']
3077447796
136515736
3077408320
3077656800
136515736
161922920

Ce méchant identifiant de code est le nom de la variable / objet / quel que soit votre nom de pédant.

Tiens voilà. L'adresse mémoire de 'jj' est la même lorsque nous la recherchons directement, que lorsque nous recherchons le dictionnaire dans l'espace de nom global. Je suis sûr que vous pouvez créer une fonction pour ce faire. N'oubliez pas dans quel espace de noms se trouve votre variable / objet / wypci.

QED.

Jesse Monroy Jr.
la source
6
Vous avez deux utilisations folles d'eval ici. La première est exactement la même que: print id(jj). Le second recherche simplement le nom et peut être fait plus facilement avec vars().
Ned Batchelder
2

Peut-être que j'y pense trop, mais ..

str_l = next((k for k,v in locals().items() if id(l) == id(v)))


>>> bar = True
>>> foo = False
>>> my_dict=dict(bar=bar, foo=foo)
>>> next((k for k,v in locals().items() if id(bar) == id(v)))
'bar'
>>> next((k for k,v in locals().items() if id(foo) == id(v)))
'foo'
>>> next((k for k,v in locals().items() if id(my_dict) == id(v)))
'my_dict'
rh0dium
la source
Génial! C'est ce que je cherchais. Merci @ rh0dium ... \ nvariable = 1 \n [k for k,v in locals().items() if id(variable) == id(v)] \n Out[14]: ['variable']
Majdi
2
import re
import traceback

pattren = re.compile(r'[\W+\w+]*get_variable_name\((\w+)\)')
def get_variable_name(x):
    return pattren.match( traceback.extract_stack(limit=2)[0][3]) .group(1)

a = 1
b = a
c = b
print get_variable_name(a)
print get_variable_name(b)
print get_variable_name(c)
xmduhan
la source
2

J'ai téléchargé une solution sur pypi . C'est un module définissant un équivalent de la fonction de C # nameof.

Il parcourt les instructions de bytecode pour la trame qu'il appelle, obtenant les noms des variables / attributs qui lui sont passés. Les noms se trouvent dans le .argreprdes LOADinstructions ci - dessous le nom de la fonction.


la source
2

J'ai écrit le paquet sorcellerie pour faire ce genre de magie avec robustesse. Tu peux écrire:

from sorcery import dict_of

my_dict = dict_of(foo, bar)
Alex Hall
la source
1

La plupart des objets n'ont pas d' attribut __name__ . (Les classes, les fonctions et les modules le font; d'autres types intégrés en ont-ils un?)

Que voulez - vous attendre à print(my_var.__name__)autre que print("my_var")? Pouvez-vous simplement utiliser la chaîne directement?

Vous pouvez "découper" un dicton:

def dict_slice(D, keys, default=None):
  return dict((k, D.get(k, default)) for k in keys)

print dict_slice(locals(), ["foo", "bar"])
# or use set literal syntax if you have a recent enough version:
print dict_slice(locals(), {"foo", "bar"})

Alternativement:

throw = object()  # sentinel
def dict_slice(D, keys, default=throw):
  def get(k):
    v = D.get(k, throw)
    if v is not throw:
      return v
    if default is throw:
      raise KeyError(k)
    return default
  return dict((k, get(k)) for k in keys)

la source
2
+1 mais je sais que ce nom n'existe pas, pourquoi tout le monde prend ce "quelque chose comme" littéralement? Votre solution ne résout pas le problème car je ne veux pas coder le nom, sinon je ferais la solution dict que j'ai déjà donnée dans la question.
e-satis
3
@ e-satis: Si tout simplement utiliser tout dans les sections locales () résout votre problème, je n'ai aucune idée de ce que vous demandez. Je suppose que vous êtes d'accord avec l'appel some_func(var), j'ai donc essayé de souligner qu'il n'y en a pas très loin some_func("var"), avec dictslice vous permettant d'obtenir le mappage nom-valeur pour plusieurs variables à la fois.
1

Eh bien, j'ai rencontré le même besoin il y a quelques jours et j'ai obtenir le nom d' une variable qui pointait vers le objet lui-même.

Et pourquoi était-ce si nécessaire?

En bref, je construisais un plug-in pour Maya . Le plug-in principal a été construit à l'aide de C ++ mais l'interface graphique est dessinée via Python (car elle n'est pas gourmande en processeur). Comme je ne sais pas encore comment returnmultiplier les valeurs du plug-in, sauf la valeur par défaut MStatus, donc pour mettre à jour un dictionnaire en Python, je devais passer le nom de la variable, pointant vers l'objet implémentant l'interface graphique et qui contenait le dictionnaire lui-même, au plug-in, puis utilisez le MGlobal::executePythonCommand()pour mettre à jour le dictionnaire à partir de la portée globale de Maya .

Pour ce faire, ce que j'ai fait était quelque chose comme:

import time

class foo(bar):

    def __init__(self):
        super(foo, self).__init__()
        self.time = time.time() #almost guaranteed to be unique on a single computer

    def name(self):
        g = globals()
        for x in g:
            if isinstance(g[x], type(self)):
                if g[x].time == self.time:
                    return x
                    #or you could:
                    #return filter(None,[x if g[x].time == self.time else None for x in g if isinstance(g[x], type(self))])
                    #and return all keys pointing to object itself

Je sais que ce n'est pas la solution parfaite dans les globalsnombreuses touches qui pourraient pointer vers le même objet par exemple:

a = foo()
b = a
b.name()
>>>b
or
>>>a

et que l'approche n'est pas thread-safe. Corrigez-moi si je me trompe.

Au moins, cette approche a résolu mon problème en obtenant le nom de toute variable dans la portée globale qui pointait vers l' objet lui-même et le transmettait au plug-in, comme argument, pour qu'il l'utilise en interne.

J'ai essayé cela sur int(la classe entière primitive) mais le problème est que ces classes primitives ne sont pas contournées (veuillez corriger la terminologie technique utilisée si elle est incorrecte). Vous pouvez réimplémenter intpuis faire, int = foomais ne a = 3serez jamais un objet foode la primitive. Pour surmonter cela, vous devez vous a = foo(3)mettre a.name()au travail.

Doigts saignants
la source
1

Avec python 2.7 et plus récent, il existe également une compréhension du dictionnaire qui le rend un peu plus court. Si possible, j'utiliserais getattr à la place eval (eval is evil) comme dans la réponse du haut. Le soi peut être n'importe quel objet qui a le contexte que vous regardez. Il peut s'agir d'un objet ou de locals = locals () etc.

{name: getattr(self, name) for name in ['some', 'vars', 'here]}
yvess
la source
1

Je travaillais sur un problème similaire. @ S.Lott a dit "Si vous avez la liste des variables, quel est l'intérêt de" découvrir "leurs noms?" Et ma réponse est juste de voir si cela pourrait être fait et si pour une raison quelconque vous voulez trier vos variables par type dans des listes. Donc de toute façon, dans mes recherches, je suis tombé sur ce fil et ma solution est un peu développée et est basée sur la solution @rlotun. Une autre chose, @unutbu a déclaré: "Cette idée a du mérite, mais notez que si deux noms de variable font référence à la même valeur (par exemple, True), alors un nom de variable involontaire peut être renvoyé." Dans cet exercice qui était vrai alors je résignées en utilisant une compréhension de liste semblable à cela pour chaque possibilité: isClass = [i for i in isClass if i != 'item']. Sans elle, «item» apparaîtrait dans chaque liste.

__metaclass__ = type

from types import *

class Class_1: pass
class Class_2: pass
list_1 = [1, 2, 3]
list_2 = ['dog', 'cat', 'bird']
tuple_1 = ('one', 'two', 'three')
tuple_2 = (1000, 2000, 3000)
dict_1 = {'one': 1, 'two': 2, 'three': 3}
dict_2 = {'dog': 'collie', 'cat': 'calico', 'bird': 'robin'}
x = 23
y = 29
pie = 3.14159
eee = 2.71828
house = 'single story'
cabin = 'cozy'

isClass = []; isList = []; isTuple = []; isDict = []; isInt = []; isFloat = []; isString = []; other = []

mixedDataTypes = [Class_1, list_1, tuple_1, dict_1, x, pie, house, Class_2, list_2, tuple_2, dict_2, y, eee, cabin]

print '\nMIXED_DATA_TYPES total count:', len(mixedDataTypes)

for item in mixedDataTypes:
    try:
        # if isinstance(item, ClassType): # use this for old class types (before 3.0)
        if isinstance(item, type):
            for k, v in list(locals().iteritems()):
                if v is item:
                    mapping_as_str = k
                    isClass.append(mapping_as_str)
            isClass = [i for i in isClass if i != 'item']

        elif isinstance(item, ListType):
            for k, v in list(locals().iteritems()):
                if v is item:
                    mapping_as_str = k
                    isList.append(mapping_as_str)
            isList = [i for i in isList if i != 'item']

        elif isinstance(item, TupleType):
            for k, v in list(locals().iteritems()):
                if v is item:
                    mapping_as_str = k
                    isTuple.append(mapping_as_str)
            isTuple = [i for i in isTuple if i != 'item']

        elif isinstance(item, DictType):
            for k, v in list(locals().iteritems()):
                if v is item:
                    mapping_as_str = k
                    isDict.append(mapping_as_str)
            isDict = [i for i in isDict if i != 'item']

        elif isinstance(item, IntType):
            for k, v in list(locals().iteritems()):
                if v is item:
                    mapping_as_str = k
                    isInt.append(mapping_as_str)
            isInt = [i for i in isInt if i != 'item']

        elif isinstance(item, FloatType):
            for k, v in list(locals().iteritems()):
                if v is item:
                    mapping_as_str = k
                    isFloat.append(mapping_as_str)
            isFloat = [i for i in isFloat if i != 'item']

        elif isinstance(item, StringType):
            for k, v in list(locals().iteritems()):
                if v is item:
                    mapping_as_str = k
                    isString.append(mapping_as_str)
            isString = [i for i in isString if i != 'item']

        else:
            for k, v in list(locals().iteritems()):
                if v is item:
                    mapping_as_str = k
                    other.append(mapping_as_str)
            other = [i for i in other if i != 'item']

    except (TypeError, AttributeError), e:
        print e

print '\n isClass:', len(isClass), isClass
print '  isList:', len(isList), isList
print ' isTuple:', len(isTuple), isTuple
print '  isDict:', len(isDict), isDict
print '   isInt:', len(isInt), isInt
print ' isFloat:', len(isFloat), isFloat
print 'isString:', len(isString), isString
print '   other:', len(other), other

# my output and the output I wanted
'''
MIXED_DATA_TYPES total count: 14

 isClass: 2 ['Class_1', 'Class_2']
  isList: 2 ['list_1', 'list_2']
 isTuple: 2 ['tuple_1', 'tuple_2']
  isDict: 2 ['dict_1', 'dict_2']
   isInt: 2 ['x', 'y']
 isFloat: 2 ['pie', 'eee']
isString: 2 ['house', 'cabin']
   other: 0 []
'''
Michael Swartz
la source
Le problème que je prendrais avec cela est que les noms ne sont pas des propriétés d'objets. Un même objet peut avoir plusieurs noms, voire aucun nom. Par exemple, vous avez ajouté pi = pieà votre code, vous obtiendrez une entrée supplémentaire dans votre isFloatliste. Si vous avez ajouté tuple_1[0]à votre mixedDataTypesliste, aucun nom ne sera trouvé pour lui malgré le fait que "un" soit dans votre code deux fois (bien que grâce à l'internement de chaînes, ils seront tous les deux des références au même objet).
Blckknght
1
@Blckknght --- Je suis d'accord. C'est juste une autre façon de faire quelque chose qui n'était vraiment pas censé être fait. Je n'ai pas dit que cela donne des résultats uniques ou que c'est infaillible. Ce faisant, j'ai découvert que l'utilisation de piet en etant que variables provoquait une sortie indésirable et c'est parce que les deux font partie de la mathbibliothèque. Pour moi, c'était juste un exercice pour voir si cela pouvait être fait même si le résultat final n'est pas parfait. Dans mon apprentissage de cette langue, passer par les livres ne va que si loin. À mon avis, si vous voulez vraiment apprendre la langue, vous devez jouer "et si" et voir ce que vous proposez.
Michael Swartz
1

vous pouvez utiliser easydict

>>> from easydict import EasyDict as edict
>>> d = edict({'foo':3, 'bar':{'x':1, 'y':2}})
>>> d.foo
3
>>> d.bar.x
1
>>> d = edict(foo=3)
>>> d.foo
3

un autre exemple:

>>> d = EasyDict(log=False)
>>> d.debug = True
>>> d.items()
[('debug', True), ('log', False)]
Eli
la source
1

Sur python3, cette fonction obtiendra le nom le plus externe de la pile:

import inspect


def retrieve_name(var):
        """
        Gets the name of var. Does it from the out most frame inner-wards.
        :param var: variable to get name from.
        :return: string
        """
        for fi in reversed(inspect.stack()):
            names = [var_name for var_name, var_val in fi.frame.f_locals.items() if var_val is var]
            if len(names) > 0:
                return names[0]

Il est utile n'importe où sur le code. Traverse la pile inversée à la recherche du premier match.

Juan Isaza
la source
0

Bien que ce soit probablement une idée horrible, elle va dans le même sens que la réponse de rlotun, mais elle retournera le résultat correct plus souvent.

import inspect
def getVarName(getvar):
  frame = inspect.currentframe()
  callerLocals = frame.f_back.f_locals
  for k, v in list(callerLocals.items()):
    if v is getvar():
      callerLocals.pop(k)
      try:
        getvar()
        callerLocals[k] = v
      except NameError:
        callerLocals[k] = v
        del frame
        return k
  del frame

Vous l'appelez comme ceci:

bar = True
foo = False
bean = False
fooName = getVarName(lambda: foo)
print(fooName) # prints "foo"
Phylliida
la source
0

devrait obtenir la liste puis revenir

def get_var_name(**kwargs):
    """get variable name
        get_var_name(var = var)
    Returns:
        [str] -- var name
    """
    return list(kwargs.keys())[0]
paulg
la source
0

Il ne renverra pas le nom de la variable mais vous pouvez facilement créer un dictionnaire à partir d'une variable globale.

class CustomDict(dict):
    def __add__(self, other):
        return CustomDict({**self, **other})

class GlobalBase(type):
    def __getattr__(cls, key):
        return CustomDict({key: globals()[key]})

    def __getitem__(cls, keys):
        return CustomDict({key: globals()[key] for key in keys})

class G(metaclass=GlobalBase):
    pass

x, y, z = 0, 1, 2

print('method 1:', G['x', 'y', 'z']) # Outcome: method 1: {'x': 0, 'y': 1, 'z': 2}
print('method 2:', G.x + G.y + G.z) # Outcome: method 2: {'x': 0, 'y': 1, 'z': 2}
user5828964
la source
0

Avec python-varnamevous pouvez facilement le faire:

pip install python-varname

from varname import Wrapper

foo = Wrapper(True)
bar = Wrapper(False)

your_dict = {val.name: val.value for val in (foo, bar)}

print(your_dict)

# {'foo': True, 'bar': False}

Avertissement: je suis l'auteur de cette bibliothèque python-varname.

Panwen Wang
la source
-1
>>> a = 1
>>> b = 1
>>> id(a)
34120408
>>> id(b)
34120408
>>> a is b
True
>>> id(a) == id(b)
True

de cette façon, obtenez varname pour un peut-être «a» ou «b».

su dazhuang
la source