it-swarm.com.de

Einfachere Möglichkeit, ein Wörterbuch mit separaten Variablen zu erstellen?

Ich möchte gerne den Namen einer Variablen als String erhalten, aber ich weiß nicht, ob Python über so viele Introspektionsfähigkeiten verfügt. So etwas wie:

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

Ich möchte das tun, weil ich eine Menge Vars habe, die ich gerne in ein Wörterbuch verwandeln möchte:

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

Aber ich hätte gerne etwas Automatischeres als das.

Python hat locals() und vars(), also gibt es einen Weg.

213
e-satis

Versuchst du das zu tun?

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

Beispiel 

>>> 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}
46
S.Lott

Wie gesagt, das ist nicht wirklich etwas, was Sie in Python tun - Variablen sind eigentlich Namenszuordnungen zu Objekten.

Allerdings , hier ist eine Möglichkeit, es zu versuchen:

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

Ich wollte das ziemlich oft machen. Dieser Hack ist dem Vorschlag von rlotun sehr ähnlich, aber es ist ein Einzeiler, was mir wichtig ist:

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]
61
keflavich

Das ist ein Hack. Es funktioniert nicht auf allen Python-Implementierungsdistributionen (insbesondere auf solchen, die nicht traceback.extract_stack haben.)

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}

Beachten Sie, dass dieser Hack zerbrechlich ist:

make_dict(bar,
          foo)

(Aufruf von make_dict in zwei Zeilen) funktioniert nicht.

Anstatt zu versuchen, das Dict aus den Werten foo und bar zu generieren, wäre es viel mehr Pythonic, das Dict aus den Zeichenfolgen Variablennamen 'foo' und 'bar' zu generieren:

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

Dies ist in Python nicht möglich, das wirklich keine "Variablen" hat. Python hat Namen, und für dasselbe Objekt können mehrere Namen vorhanden sein.

14
unwind

Ich denke, mein Problem wird helfen zu veranschaulichen, warum diese Frage nützlich ist, und es könnte ein wenig mehr Einblick in die Antwort geben. Ich habe eine kleine Funktion geschrieben, um eine schnelle Inline-Überprüfung der verschiedenen Variablen in meinem Code durchzuführen. Im Allgemeinen werden Variablenname, Datentyp, Größe und andere Attribute aufgelistet, sodass ich schnell Fehler feststellen kann, die ich gemacht habe. Der Code ist einfach:

def details(val):
  vn = val.__                #  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)))

Wenn Sie eine komplizierte Situation für Wörterbuch/Liste/Tuple haben, ist es sehr hilfreich, wenn der Interpreter den von Ihnen zugewiesenen Variablennamen zurückgibt. Zum Beispiel ist hier ein komisches Wörterbuch:

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

Ich bin mir nicht sicher, ob ich das an die richtige Stelle stelle, aber ich dachte, es könnte helfen. Ich hoffe es tut es.

10
TheProletariat

Ich habe eine nette kleine nützliche Funktion geschrieben, die auf der Antwort auf diese Frage basiert. Ich stelle es hier für den Fall, dass es nützlich ist.

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)

verwendungszweck:

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

In Python 3 ist das einfach

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

dies wird drucken:

myVariable 5

6
officialhopsof

Ich finde, wenn Sie bereits eine bestimmte Liste von Werten haben, die von @S beschriebene Weise. Lot ist das Beste; Die unten beschriebene Methode funktioniert jedoch gut, um alle Variablen und Klassen im gesamten CodeOHNEhinzuzufügen, wobei der Variablenname angegeben werden muss. Sie können sie jedoch angeben, wenn Sie möchten. Code kann erweitert werden, um Klassen auszuschließen.

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 __== '__main__':
    foo = 1
    bar = 2
    baz = 3
    print magic_print()
    print magic_print('foo')
    print magic_print('foo','bar')

Ausgabe:

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

Hier ist die Funktion, die ich zum Lesen der Variablennamen erstellt habe. Es ist allgemeiner und kann in verschiedenen Anwendungen verwendet werden:

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]

Um es in der angegebenen Frage zu verwenden:

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

Python3. Verwenden Sie inspect, um den aufrufenden lokalen Namespace zu erfassen, und verwenden Sie die hier präsentierten Ideen. Kann wie angegeben mehr als eine Antwort zurückgeben.

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
5
vvxxii

Beim Lesen des Threads sah ich sehr viel Reibung. Es ist einfach genug, eine falsche Antwort zu geben, und dann die richtige Antwort von jemandem geben zu lassen. Wie auch immer, hier ist was ich gefunden habe.

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

Die Namen sind etwas anders - sie sind keine wirklichen Eigenschaften des Objekts und das Objekt selbst weiß nicht, wie es heißt.

Ein Objekt kann beliebig viele oder gar keine Namen haben.

Namen befinden sich in Namespaces (z. B. einem Modulnamespace, einem Instanznamespace oder dem lokalen Namespace einer Funktion).

Beachten Sie: dass es heißt das Objekt selbst weiß nicht, wie es heißtDas war also der Anhaltspunkt. Python Objekte sind nicht selbstreferenziell. Dann heißt es: Namen leben in Namespaces. Wir haben dies in TCL/TK. Also vielleicht hilft meine Antwort (aber es hat mir geholfen)

 
 jj = 123 
 print eval ("'" + str (id (jj)) + "'") 
 print dir () 
 
 166707048 
 ['__ builtins__', '__ doc__', '__ file__', '__ name__', '__ package__', 'jj'] 

Am Ende der Liste steht also "jj".

Schreiben Sie den Code um als:

 
 jj = 123 
 print eval ("'" + str (id (jj)) + "'") 
 für x in dir (): 
 print id (eval (x)) 
 
 161922920 
 ['__ builtins__', '__ doc__', '__ file__', '__ name__', '__ package__', 'jj'] 
 3077447796 
 136515736 
 3077408320 
 3077656800 
 136515736 
 161922920 

Dieses fiese Bit der Code-ID ist der Name von Variable/Objekt/Was auch immer-Sie-Pedantik-nennen-es.

Also, da ist es. Die Speicheradresse von 'jj' ist dieselbe, wenn wir direkt danach suchen, wie wenn wir das Wörterbuch im globalen Namensraum nachschlagen. Ich bin sicher, Sie können eine Funktion erstellen, um dies zu tun. Denken Sie daran, in welchem ​​Namespace sich Ihre Variable/Objekt/Wypci befindet.

QED.

4

Ich habe das Paket Sorcery geschrieben, um diese Art von Magie robust auszuführen. Du kannst schreiben:

from sorcery import dict_of

my_dict = dict_of(foo, bar)
2
Alex Hall
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
xmduhan

Ich habe eine Lösung auf pypi hochgeladen. Es ist ein Modul, das ein Äquivalent der nameof-Funktion von C # definiert. 

Es iteriert durch Bytecode-Anweisungen für den Rahmen, in dem es aufgerufen wird, und erhält die Namen von Variablen/Attributen, die an ihn übergeben werden. Die Namen befinden sich in den Anweisungen .argrepr von LOAD nach dem Namen der Funktion.

2
user7340830

Mit Python 2.7 und neuer gibt es auch ein Wörterbuchverstehen, was es etwas kürzer macht. Wenn möglich würde ich getattr anstelle von eval (eval is böse) wie in der Top-Antwort verwenden. Das Selbst kann ein beliebiges Objekt sein, das den Kontext hat, den Sie betrachten. Es kann ein Objekt oder Einheimische sein = Einheimische () usw. 

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

Die meisten Objekte haben kein_NAME_Attribut. (Klassen, Funktionen und Module tun dies; gibt es weitere eingebaute Typen, die einen haben?)

Was würden Sie für print(my_var.__name__) anders als print("my_var") erwarten? Kannst du die Zeichenfolge einfach direkt verwenden?

Sie könnten ein Diktat "schneiden":

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

Alternative:

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)
1
Roger Pate

Nun, ich bin vor ein paar Tagen auf dasselbe need gestoßen und musste den name einer Variablen erhalten, der auf das object selbst zeigte.

Und warum war es so notwendig?

Kurz gesagt, ich baute ein Plug-In für Maya. Das Kern-Plug-In wurde mit C++ erstellt, aber die grafische Benutzeroberfläche wird durch Python (nicht prozessorintensiv) gezeichnet. Da ich bis auf die Standardvariable return nicht wissen kann, wie viele Werte aus dem Plug-In MStatus sind, musste ich zum Aktualisieren eines Wörterbuchs in Python den Namen der Variablen übergeben und auf das Objekt verweisen, das die GUI implementiert und die das Wörterbuch selbst enthielt, an das Plug-In und dann mit MGlobal::executePythonCommand() das Wörterbuch aus dem globalen Geltungsbereich von Maya zu aktualisieren.

Das zu tun, was ich getan habe, war so etwas wie:

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

Ich weiß, dass es nicht die perfekte Lösung ist, in der globals viele Schlüssel auf dasselbe object zeigen könnten.

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

und dass der Ansatz nicht Thread-sicher ist. Korrigiere mich, wenn ich falsch liege.

Zumindest konnte dieser Ansatz mein Problem dadurch lösen, dass der Name name einer beliebigen Variablen im globalen Gültigkeitsbereich auf das Objekt object selbst abgerufen und an das Plug-In als Argument übergeben wird, das intern verwendet wird.

Ich habe dies mit int (der primitiven Ganzzahlenklasse) versucht, aber das Problem ist, dass diese primitiven Klassen nicht umgangen werden (bitte korrigieren Sie die verwendete technische Terminologie, falls sie falsch ist). Sie könnten int erneut implementieren und dann int = foo ausführen, aber a = 3 wird niemals ein Objekt von foo sein, sondern des Primitivs. Um dies zu überwinden, müssen Sie a = foo(3) verwenden, um a.name() zur Arbeit zu bringen.

1

Bei python3 erhält diese Funktion den äußersten Namen im Stack:

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]

Es ist überall im Code nützlich. Durchläuft den umgekehrten Stapel und sucht nach dem ersten Treffer.

1
juan Isaza

Ich arbeitete an einem ähnlichen Problem. @ S.Lott sagte: "Wenn Sie die Liste der Variablen haben, was ist der Sinn, ihre Namen zu" entdecken "? Und meine Antwort ist nur zu sehen, ob dies getan werden könnte und ob Sie aus irgendeinem Grund Ihre Variablen nach Typ in Listen sortieren möchten. Bei meinen Recherchen bin ich also auf diesen Thread gestoßen, und meine Lösung ist etwas erweitert und basiert auf der @rlotun-Lösung. Eine andere Sache, @unutbu, sagte: "Diese Idee ist wertvoll, aber beachten Sie, dass, wenn zwei Variablennamen auf denselben Wert verweisen (z. B." True "), ein unbeabsichtigter Variablenname zurückgegeben werden könnte. In dieser Übung war das richtig, also habe ich mich damit befasst, indem ich für jede Möglichkeit ein ähnliches Listenverständnis verwendete: isClass = [i for i in isClass if i != 'item']. Ohne sie würde "item" in jeder Liste erscheinen.

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

Vielleicht denke ich darüber nach, aber ..

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

sie können easydict verwenden

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

ein anderes Beispiel:

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

Dies ist wahrscheinlich eine schreckliche Idee, entspricht jedoch der Antwort von rlotun, wird jedoch häufiger das korrekte Ergebnis liefern.

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

Sie nennen es so:

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

sollte Liste bekommen und dann zurückkehren 

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