Maneira mais simples de criar dicionário de variáveis ​​separadas?


220

Gostaria de poder obter o nome de uma variável como uma string, mas não sei se o Python tem tantos recursos de introspecção. Algo como:

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

Quero fazer isso porque tenho várias variáveis ​​que gostaria de transformar em um dicionário como:

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

Mas eu gostaria de algo mais automático que isso.

Python tem locals()e vars(), então eu acho que existe um caminho.


31
Como as pessoas parecem estar confusas sobre o que é pedido, vou reafirmar aqui, porque é uma pergunta interessante. Dado um array [foo, bar, baz], você deseja um dicionário como {'foo': foo, 'bar': bar, 'baz': baz} e não sabe quais variáveis ​​estão no array. então o questionador está perguntando como você obtém o nome de uma variável como uma string em python. Agora, espero que as pessoas possam navegar pelas respostas terríveis para encontrar os poucos lugares onde você aprende por que essa não é realmente uma boa ideia em python.
Jesse Sherlock #


2
Um uso da técnica seria simplificar as chamadas de formatação de string: '{var} {foo} {bar}'. Format (** named (var, foo, bar)), em que "named" é a função que retorna o dict ( 'var': var) como descrito.
Gordon Feijão

4
Eu acho que essa é realmente uma pergunta ruim porque os nomes são mapeados para objetos, você pode ter vários nomes apontando para o mesmo objeto e nunca vi necessidade de realizar o objetivo de inverter esse mapeamento. Portanto, o fato de a resposta errada ser aceita aqui não faz sentido - se uma pesquisa no Google trouxe você aqui, você está claramente fazendo a pergunta errada.
Aaron Hall

1
Essa é uma ótima idéia para depuração!
john ktejik

Respostas:


48

Você está tentando fazer isso?

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

Exemplo

>>> 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}

1
rlotun está mais próximo do "espírito" inicial, pois permite descobrir o nome. Eu poderia usar tanto a sua resposta. Ou talvez apenas use minha maldita mão para digitar. Algumas coisas simplesmente não são feitos para ser que automatizado ...
e-satis

7
@ e-satis: Para que o @ rlotun funcione, você deve fornecer a lista de variáveis. Se você possui a lista de variáveis, qual é o sentido de "descobrir" os nomes deles?
S.Lott

4
Por que avaliar em vez de usar explicitamente locais e globais?

1
@ Roger Pate: Porque eu não conseguia descobrir qual era o objetivo de todo o exercício.
S.Lott

242
Esta resposta não responde à pergunta. Se você possui a lista de variáveis, qual é o sentido de "descobrir" os nomes deles? Evitar duplicação para que, em vez de print('x: ' + x)um, possa escrever magic_print(x)e ter a mesma saída sem escrever o nome da variável duas vezes.
Piotr Dobrogost

130

Como o desenrolador disse, isso não é realmente algo que você faz no Python - as variáveis ​​são, na verdade, mapeamentos de nomes para objetos.

No entanto , aqui está uma maneira de tentar fazê-lo:

 >>> 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'

14
Essa ideia tem mérito, mas observe que, se dois nomes de variáveis ​​fizerem referência ao mesmo valor (por exemplo True), um nome de variável não intencional poderá ser retornado.
unutbu

14
Por que ao id(v) == id(a)invés de v is a? Isso falhará para objetos vinculados a várias variáveis, como ints, strings e quaisquer tipos definidos pelo usuário implementados de maneira semelhante.

Sim, v is aseria uma escolha melhor. E sim, certamente perigoso, considerando todas as armadilhas potenciais que podem surgir! ;-)
rlotun 31/03

16
@ e-satis Estou surpreso que você não tenha marcado esta resposta como a resposta que concordo com o seu comentário, dizendo que rlotun está mais próximo do "espírito" inicial, pois permite descobrir o nome . Além disso a resposta de S. Lott não aswer sua pergunta em tudo ...
Piotr Dobrogost

2
"exagero e perigoso" ... e usar eval não é?
bug

63

Eu queria fazer isso bastante. Esse hack é muito parecido com a sugestão de rlotun, mas é uma linha, o que é importante para mim:

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]

3
@keflavich Gostei muito dessa abordagem e a tenho usado de tempos em tempos agora. No entanto, eu não posso fazê-lo funcionar dentro de funções. Eu acho que existem maneiras "melhores" de fazer isso, mas nenhuma é tão simples quanto nbubis coloca. Você conseguiu usá-lo nas funções keflavich? Este é o lugar onde eu faço uma pergunta sobre isso.
Leo

10
Observe que no Python 3, iteritems()é substituído poritems()
Jonathan Wheeler

Isso não é confiável: spam = 1; blah = 1; blah_name = [ k for k,v in locals().items() if v is blah][0]; print(blah_name)Saídasspam
andreasdr

1
@andreasdr é porque spam = 1, blah = 1; assert spam is blah. A solução é interrompida ao comparar tipos de dados primitivos.
Jyun

17

Isso é um truque. Não funcionará em todas as distribuições de implementações Python (em particular, aquelas que não possuem 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}

Observe que esse hack é frágil:

make_dict(bar,
          foo)

(chamar make_dict em 2 linhas) não funcionará.

Em vez de tentar gerar o dict a partir dos valores foo e bar, seria muito mais Pythonic gerar o dict a partir dos nomes de variáveis da string 'foo'e 'bar':

dict([(name,locals()[name]) for name in ('foo','bar')])

1
+1 para o hack inteligente. Obviamente, o rastreio é muito lento, portanto pode ser lento usá-lo.
e-satis

1
+1111111 !!!! Sim, é lento, mas ao usar para substituir print("a_very_long_name: {}'.format(a_very_long_name))quem se importa!
Frnhr 5/12/2014

14

Isso não é possível no Python, que realmente não tem "variáveis". Python tem nomes e pode haver mais de um nome para o mesmo objeto.


Sim, eu sei, simplifiquei a pergunta, mas esperava mais algo como "get_var_tags (var) [0]".
e-satis

10

Acho que meu problema ajudará a ilustrar por que essa pergunta é útil e pode fornecer um pouco mais de insight sobre como respondê-la. Eu escrevi uma pequena função para fazer uma verificação rápida em linha em várias variáveis ​​no meu código. Basicamente, ele lista o nome da variável, tipo de dados, tamanho e outros atributos, para que eu possa detectar rapidamente os erros que cometi. O código é simples:

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)))

Portanto, se você tiver uma situação complicada de dicionário / lista / tupla, seria bastante útil que o intérprete retornasse o nome da variável que você atribuiu. Por exemplo, aqui está um dicionário estranho:

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'>

Não tenho certeza se coloco isso no lugar certo, mas achei que poderia ajudar. Espero que sim.


Então, com sua verificação geral, isso explica o fato de que variáveis ​​/ nomes podem estar apontando para coisas diferentes em momentos diferentes do código? Por exemplo, myconnectionpoderia estar apontando para um valor booleano em um ponto, um número inteiro em outro momento e uma conexão de soquete em outro ponto na execução do código?

9

Escrevi uma pequena função útil, baseada na resposta a esta pergunta. Estou colocando aqui caso seja útil.

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)

uso:

>> a = 4
>> what(a)
a = 4
>>|

6

Acho que, se você já possui uma lista específica de valores, é assim descrito por @S. Lotts é o melhor; no entanto, a maneira descrita abaixo funciona bem para obter todas as variáveis ​​e classes adicionadas ao longo do código SEM a necessidade de fornecer o nome da variável, embora você possa especificá-las, se desejar. O código pode ser estendido para excluir 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')

Resultado:

{'baz': 3, 'foo': 1, 'bar': 2}
{'foo': 1}
{'foo': 1, 'bar': 2}

6

No python 3 isso é fácil

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

isto imprimirá:

myVariable 5


Isto é semelhante à abordagem de rlotun mas um simplier bit
officialhopsof

10
-1. Abra uma nova janela de intérprete e tente for v in locals().
Air

Não tenho muita certeza do que você quer dizer.
officialhopsof

4
Isto lhe dará um erro: RuntimeError: dicionário tamanho alterado durante a iteração ...
Nizar B.

2
como você pode fazerfor v in list(locals()):
Phylliida

5

Python3. Use inspecionar para capturar o espaço para nome local de chamada e use as idéias apresentadas aqui. Pode retornar mais de uma resposta, conforme indicado.

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

Boa resposta, mas para mim é melhor com: ... id (eval (nome, nenhum, frame.f_back.f_locals)) == ...
Emmanuel DUMAS

5

Aqui está a função que eu criei para ler os nomes das variáveis. É mais geral e pode ser usado em diferentes aplicações:

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]

Para usá-lo na pergunta especificada:

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

4

Ao ler o tópico, vi muitos atritos. É fácil dar uma resposta ruim e deixar alguém dar a resposta correta. Enfim, aqui está o que eu encontrei.

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

Os nomes são um pouco diferentes - eles não são realmente propriedades do objeto, e o próprio objeto não sabe como é chamado.

Um objeto pode ter qualquer número de nomes ou nenhum nome.

Os nomes vivem em espaços para nome (como um espaço para nome do módulo, um espaço para nome da instância, o espaço para nome local da função).

Nota: que ele diz que o objeto em si não sabe como é chamado , então essa foi a pista. Objetos Python não são auto-referenciais. Depois, diz: Nomes vivem em espaços para nome . Temos isso em TCL / TK. Talvez minha resposta ajude (mas me ajudou)

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

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

Portanto, há 'jj' no final da lista.

Reescreva o código como:

    jj = 123
    print eval ("'" + str (id (jj)) + "'")
    para x em dir ():
        ID de impressão (eval (x))

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

Essa parte desagradável do código é o nome da variável / objeto / seja lá o que você pedantics chamar.

Então aí está. O endereço de memória de 'jj' é o mesmo quando o procuramos diretamente, como quando procuramos no dicionário no espaço de nomes global. Tenho certeza que você pode fazer uma função para fazer isso. Lembre-se de qual namespace sua variável / objeto / wypci está.

QED.


6
Você tem dois usos loucos de eval aqui. A primeira é exatamente o mesmo que: print id(jj). O segundo simplesmente pesquisa o nome e pode ser feito mais facilmente vars().
Ned Batchelder

2

Talvez eu esteja pensando demais nisso, mas ..

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'

Ótimo! Era isso que eu estava procurando. Obrigado @ 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)

2

Fiz upload de uma solução para o pypi . É um módulo que define um equivalente da nameoffunção do C # .

Ele itera através das instruções do bytecode para o quadro em que é chamado, obtendo os nomes das variáveis ​​/ atributos passados ​​para ele. Os nomes são encontrados no .argreprde LOADinstruções seguinte nome da função.


2

Eu escrevi a feitiçaria de pacotes para fazer esse tipo de mágica de maneira robusta. Você pode escrever:

from sorcery import dict_of

my_dict = dict_of(foo, bar)

1

A maioria dos objetos não possui um atributo __name__ . (Classes, funções e módulos possuem; mais tipos internos que possuem um?)

O que mais você esperaria print(my_var.__name__)além de print("my_var")? Você pode simplesmente usar a string diretamente?

Você pode "cortar" um ditado:

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"})

Alternativamente:

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)

2
+1, mas eu sei que esse nome não existe, por que todo mundo leva esse "algo parecido" literalmente? Sua solução não resolve o problema, já que eu não quero codificar o nome; caso contrário, eu faria a solução de ditado que já dei na pergunta.
e-satis

3
@ e-satis: Se simplesmente usar tudo em locals () resolve seu problema, não tenho idéia do que você está perguntando. Suponho que você esteja bem com a chamada some_func(var), então tentei ressaltar que não há muito longe some_func("var"), com o dictslice permitindo que você obtenha o mapeamento de nome-valor para várias variáveis ​​ao mesmo tempo.

1

Bem, encontrei a mesma necessidade há alguns dias e tive que obter o nome de uma variável que apontava para o próprio objeto .

E por que era tão necessário?

Em resumo, eu estava construindo um plug-in para o Maya . O plug-in principal foi criado usando C ++, mas a GUI é desenhada através do Python (pois não exige muito processador). Como ainda não sei como returnmúltiplos valores do plug-in, exceto o padrão MStatus, portanto, para atualizar um dicionário em Python, tive que passar o nome da variável, apontando para o objeto que implementa a GUI e qual continha o próprio dicionário no plug-in e, em seguida, use o MGlobal::executePythonCommand()para atualizar o dicionário a partir do escopo global do Maya .

Para fazer isso, o que eu fiz foi algo como:

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

Eu sei que não é a solução perfeita nas globalsmuitas chaves que podem estar apontando para o mesmo objeto, por exemplo:

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

e que a abordagem não é segura para threads. Corrija-me se eu estiver errada.

Pelo menos essa abordagem resolveu meu problema, obtendo o nome de qualquer variável no escopo global que apontava para o próprio objeto e o passava para o plug-in, como argumento, para uso interno.

Eu tentei isso int(a classe inteira primitiva), mas o problema é que essas classes primitivas não são ignoradas (corrija a terminologia técnica usada se estiver errada). Você pode reimplementar inte depois fazer, int = foomas a = 3nunca será um objeto foosenão o primitivo. Para superar que você tem que a = foo(3)chegar a.name()ao trabalho.


1

Com o python 2.7 e mais recente, também há compreensão de dicionário, o que o torna um pouco mais curto. Se possível, eu usaria getattr em vez de eval (eval é mau) como na resposta superior. O eu pode ser qualquer objeto que tenha o contexto que você está olhando. Pode ser um objeto ou locals = locals () etc.

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

1

Eu estava trabalhando em um problema semelhante. @ S.Lott disse "Se você tem a lista de variáveis, qual é o sentido de" descobrir "os nomes deles?" E minha resposta é apenas para ver se isso poderia ser feito e se, por algum motivo, você deseja classificar suas variáveis ​​por tipo em listas. De qualquer forma, em minha pesquisa, me deparei com esse segmento e minha solução é um pouco expandida e é baseada na solução @rlotun. Outra coisa, @unutbu disse: "Essa ideia tem mérito, mas observe que, se dois nomes de variáveis ​​fizerem referência ao mesmo valor (por exemplo, True), um nome de variável não intencional poderá ser retornado". Neste exercício, que era verdade, então eu lidei com isso usando uma compreensão lista semelhante a este para cada possibilidade: isClass = [i for i in isClass if i != 'item']. Sem ele "item" apareceria em cada lista.

__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 []
'''

O problema que eu levaria com isso é que nomes não são propriedades de objetos. Um único objeto pode ter vários nomes ou nenhum nome. Por exemplo, você adicionou pi = pieao seu código e obteria uma entrada extra na sua isFloatlista. Se você adicionou tuple_1[0]à sua mixedDataTypeslista, nenhum nome será encontrado, apesar de "um" estar no seu código duas vezes (embora, graças à cadeia de caracteres interna, ambos sejam referências ao mesmo objeto).
Blckknght

1
@Blckknght --- eu concordo. Esta é apenas outra maneira de fazer algo que realmente não deveria ser feito. Eu não disse que produz resultados únicos ou que é infalível. Ao fazer isso, descobri que o uso de pie ecomo variáveis ​​causava saída indesejada e isso ocorre porque ambos fazem parte da mathbiblioteca. Para mim, este foi apenas um exercício para ver se poderia ser feito, mesmo que o resultado final não seja perfeito. No meu aprendizado dessa língua, passar por livros só vai tão longe. Na minha opinião, se você realmente quer aprender o idioma, precisa tocar "what if" e ver o que você propõe.
Michael Swartz

1

você pode usar o 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

outro exemplo:

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

1

No python3, essa função obterá o nome mais externo da pilha:

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]

É útil em qualquer lugar do código. Atravessa a pilha invertida procurando a primeira correspondência.


0

Embora essa seja provavelmente uma péssima idéia, ela segue as mesmas linhas da resposta de rlotun, mas retornará o resultado correto com mais frequência.

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

Você chama assim:

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

0

deve obter a lista e retornar

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

0

Ele não retornará o nome da variável, mas você pode criar dicionário a partir da variável global facilmente.

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}

0

Com python-varnamevocê pode facilmente fazê-lo:

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}

Isenção de responsabilidade: sou o autor dessa biblioteca python-varname.


-1
>>> a = 1
>>> b = 1
>>> id(a)
34120408
>>> id(b)
34120408
>>> a is b
True
>>> id(a) == id(b)
True

dessa forma, obtenha varname para um talvez 'a' ou 'b'.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.