wake-up-neo.net

Den Namen einer Variablen als String erhalten

In diesem Thread wird erläutert, wie der Name einer Funktion als Zeichenfolge in Python abgerufen wird: Wie erhalte ich einen Funktionsnamen als Zeichenfolge in Python?

Wie kann ich dasselbe für eine Variable tun? (Beachten Sie, dass Python-Variablen zumindest in Python __name__ nicht das Attribut 2.7.x haben.)

Mit anderen Worten, wenn ich eine Variable wie:

foo = dict()
foo['bar'] = 2

Ich suche nach einer Funktion/einem Attribut, z. retrieve_name:

retrieve_name(foo) 

das gibt den String 'foo' zurück

Aktualisieren:

Da die Leute fragen, warum ich das machen möchte, hier ein Beispiel. Ich möchte aus dieser Liste einen DataFrame in Pandas erstellen }, wobei die Spaltennamen durch die Namen der eigentlichen Wörterbücher angegeben werden:

# List of dictionaries for my DataFrame
list_of_dicts = [n_jobs, users, queues, priorities]
55

Die einzigen Objekte in Python, die kanonische Namen haben, sind Module, Funktionen und Klassen. Natürlich kann nicht garantiert werden, dass dieser kanonische Name in einem beliebigen Namespace eine Bedeutung hat, nachdem die Funktion oder Klasse definiert oder das Modul importiert wurde. Diese Namen können auch nach der Erstellung der Objekte geändert werden, sodass sie nicht immer besonders vertrauenswürdig sind.

Was Sie tun möchten, ist nicht möglich ohne rekursiv durch den Baum der benannten Objekte zu laufen ; Ein Name ist eine unidirektionale Referenz auf ein Objekt. Ein allgemeines Python-Objekt oder eine Gartenart enthält keine Verweise auf seine Namen. Stellen Sie sich vor, jeder Integer, jedes Diktat, jede Liste, jeder Booleaner müsste eine Liste von Strings führen, die Namen repräsentieren, die darauf verweisen. Es wäre ein Albtraum der Implementierung, von dem der Programmierer wenig profitieren würde.

57
kindall

Auch wenn Variablenwerte nicht auf den Namen verweisen, haben Sie Zugriff auf die Liste aller zugewiesenen Variablen und deren Wert. Ich bin also erstaunt, dass nur eine Person vorgeschlagen hat, sich dort durchzuschleifen, um nach Ihrem Variablennamen zu suchen.

Jemand hat in dieser Antwort erwähnt, dass Sie möglicherweise den Stapel durchgehen und alle Einheimischen und Globalen überprüfen müssen, um foo zu finden, aber wenn foo in dem Bereich zugewiesen ist, in dem Sie dies aufrufen _retrieve_name_ Funktion können Sie inspect 's _current frame_ verwenden, um alle diese lokalen Variablen abzurufen.

Meine Erklärung mag ein bisschen zu wortreich sein (vielleicht hätte ich ein "foo" weniger Wörter verwenden sollen), aber so würde es im Code aussehen ( Beachten Sie, dass wenn es mehr als ein Wort gibt Variable, die demselben Wert zugewiesen ist, erhalten Sie beide Variablennamen ):

_import inspect

x,y,z = 1,2,3

def retrieve_name(var):
    callers_local_vars = inspect.currentframe().f_back.f_locals.items()
    return [var_name for var_name, var_val in callers_local_vars if var_val is var]

print retrieve_name(y)
_

Wenn Sie diese Funktion von einer anderen Funktion aus aufrufen, geschieht Folgendes:

_def foo(bar):
    return retrieve_name(bar)

foo(baz)
_

Und Sie möchten die baz anstelle von bar, Sie müssen nur einen Bereich weiter zurückgehen. Dies kann durch Hinzufügen eines zusätzlichen _.f_back_ in der _caller_local_vars_ -Initialisierung erreicht werden.

Sehen Sie sich hier ein Beispiel an: ideone

63
scohe001

Ich glaube nicht, dass das möglich ist. Betrachten Sie das folgende Beispiel:

>>> a = []
>>> b = a
>>> id(a)
140031712435664
>>> id(b)
140031712435664

Die Variable a und b zeigen auf dasselbe Objekt, das Objekt kann jedoch nicht wissen, welche Variablen darauf zeigen.

16
korylprince
def name(**variables):
    return [x for x in variables]

Es wird so verwendet:

name(variable=variable)
13
fdvfcges

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.

12
juan Isaza

Hier ist ein Ansatz. Ich würde es nicht für etwas Wichtiges empfehlen, weil es ziemlich spröde wird. Aber es kann gemacht werden.

Erstellen Sie eine Funktion, die das Modul inspect verwendet, um den Quellcode zu suchen, der es aufgerufen hat. Anschließend können Sie den Quellcode analysieren, um die Variablennamen zu ermitteln, die Sie abrufen möchten. Hier ist zum Beispiel eine Funktion namens autodict, die eine Liste von Variablen übernimmt und ein Wörterbuch zurückgibt, das Variablennamen ihren Werten zuordnet. Z.B.:

x = 'foo'
y = 'bar'
d = autodict(x, y)
print d

Würde geben:

{'x': 'foo', 'y': 'bar'}

Die Überprüfung des Quellcodes selbst ist besser als das Durchsuchen der locals() oder globals(), da der letztere Ansatz Ihnen nicht sagt, welche der Variablen die gewünschten sind.

Auf jeden Fall hier der Code:

def autodict(*args):
    get_rid_of = ['autodict(', ',', ')', '\n']
    calling_code = inspect.getouterframes(inspect.currentframe())[1][4][0]
    calling_code = calling_code[calling_code.index('autodict'):]
    for garbage in get_rid_of:
        calling_code = calling_code.replace(garbage, '')
    var_names, var_values = calling_code.split(), args
    dyn_dict = {var_name: var_value for var_name, var_value in
                Zip(var_names, var_values)}
    return dyn_dict

Die Aktion findet in der Zeile mit inspect.getouterframes statt, die die Zeichenfolge im Code mit dem Namen autodict zurückgibt.

Der offensichtliche Nachteil dieser Art von Magie ist, dass Annahmen darüber gemacht werden, wie der Quellcode strukturiert ist. Und natürlich funktioniert es überhaupt nicht, wenn es im Interpreter ausgeführt wird.

5
Zachary Ernst

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

from sorcery import dict_of

columns = dict_of(n_jobs, users, queues, priorities)

und übergeben Sie dies an den Dataframe-Konstruktor. Es entspricht:

columns = dict(n_jobs=n_jobs, users=users, queues=queues, priorities=priorities)
4
Alex Hall

In Python binden die Schlüsselwörter def und class einen bestimmten Namen an das von ihnen definierte Objekt (Funktion oder Klasse). In ähnlicher Weise erhalten Module einen Namen, indem sie im Dateisystem als spezifisch bezeichnet werden. In allen drei Fällen gibt es eine offensichtliche Möglichkeit, dem betreffenden Objekt einen "kanonischen" Namen zuzuweisen.

Bei anderen Arten von Objekten kann ein solcher kanonischer Name jedoch einfach nicht vorhanden sein . Betrachten Sie beispielsweise die Elemente einer Liste. Die Elemente in der Liste werden nicht einzeln benannt, und es ist durchaus möglich, dass die einzige Möglichkeit, sie in einem Programm darauf zu beziehen, darin besteht, Listenindizes in der enthaltenden Liste zu verwenden. Wenn eine solche Liste von Objekten an Ihre Funktion übergeben wurde, konnten Sie den Werten möglicherweise keine aussagekräftigen Bezeichner zuweisen.

Python speichert den Namen auf der linken Seite einer Zuweisung nicht in dem zugewiesenen Objekt, weil:

  1. Es müsste herausgefunden werden, welcher Name unter mehreren in Konflikt stehenden Objekten "kanonisch" war.
  2. Es macht keinen Sinn für Objekte, die niemals einem expliziten Variablennamen zugeordnet sind.
  3. Es wäre äußerst ineffizient,
  4. Wörtlich macht das keine andere Sprache.

So haben beispielsweise Funktionen, die mit lambda definiert wurden, immer den "Namen" <lambda> und nicht einen bestimmten Funktionsnamen.

Der beste Ansatz wäre, den Anrufer einfach zu bitten, eine (optionale) Namensliste zu übergeben. Wenn die Eingabe von '...','...' zu umständlich ist, können Sie z. eine einzelne Zeichenfolge, die eine durch Kommas getrennte Liste von Namen enthält (wie namedtuple).

3
nneonneo

Ich denke, es ist so schwierig, dies in Python zu tun, weil Sie den Namen der verwendeten Variable nie kennen werden. In seinem Beispiel könnten Sie also Folgendes tun:

Anstatt:

list_of_dicts = [n_jobs, users, queues, priorities]

dict_of_dicts = {"n_jobs" : n_jobs, "users" : users, "queues" : queues, "priorities" : priorities}
2
Joe Camel
>>> locals()['foo']
{}
>>> globals()['foo']
{}

wenn Sie eine eigene Funktion schreiben möchten, kann dies so erfolgen, dass Sie nach einer in Einheimischen definierten Variablen suchen und dann Globals überprüfen. Wenn nichts gefunden wird, können Sie mit id () vergleichen, ob die Variable auf dieselbe Stelle im Speicher zeigt.

Wenn sich Ihre Variable in einer Klasse befindet, können Sie className. dict . Keys () oder vars (self) verwenden, um festzustellen, ob Ihre Variable definiert wurde.

2
blakev

Diese Funktion gibt den Variablennamen mit dem folgenden Wert aus:

def print_this(var):
    callers_local_vars = inspect.currentframe().f_back.f_locals.items()
    print(str([k for k, v in callers_local_vars if v is var][0])+': '+str(var))
***Input & Function call:***
my_var = 10

print_this(my_var)

***Output**:*
my_var: 10
1
iDilip

Sie können Folgendes versuchen, um den Namen einer von Ihnen definierten Funktion abzurufen (funktioniert jedoch nicht für integrierte Funktionen):

import re
def retrieve_name(func):
    return re.match("<function\s+(\w+)\s+at.*", str(func)).group(1)

def foo(x):
    return x**2

print(retrieve_name(foo))
# foo
0
Sandipan Dey

Ich versuche, den Namen von Einheimischen zu ermitteln, aber er kann var nicht wie [1], b.val ..__ verarbeiten. Danach bekam ich eine neue Idee - holen Sie sich den Var-Namen aus dem Code und ich versuche es es ist erfolgreich! code wie folgt: 

#direct get from called function code
def retrieve_name_ex(var):
    stacks = inspect.stack()
    try:
        func = stacks[0].function
        code = stacks[1].code_context[0]
        s = code.index(func)
        s = code.index("(", s + len(func)) + 1
        e = code.index(")", s)
        return code[s:e].strip()
    except:
        return ""
0
Ryan

Für Konstanten können Sie eine Aufzählung verwenden, die das Abrufen des Namens unterstützt.

0
Dana

Wenn Sie dabei helfen möchten, Ihre Variablen zu verfolgen, können Sie eine einfache Funktion schreiben, die die Variable beschriftet und deren Wert und Typ zurückgibt. Angenommen, i_f = 3.01 und Sie runden es auf eine Ganzzahl namens i_n, die in einem Code verwendet werden soll, und benötigen dann eine Zeichenfolge i_s, die in einen Bericht aufgenommen wird. 

def whatis(string, x):
    print(string+' value=',repr(x),type(x))
    return string+' value='+repr(x)+repr(type(x))
i_f=3.01
i_n=int(i_f)
i_s=str(i_n)
i_l=[i_f, i_n, i_s]
i_u=(i_f, i_n, i_s)

## make report that identifies all types
report='\n'+20*'#'+'\nThis is the report:\n'
report+= whatis('i_f ',i_f)+'\n'
report+=whatis('i_n ',i_n)+'\n'
report+=whatis('i_s ',i_s)+'\n'
report+=whatis('i_l ',i_l)+'\n'
report+=whatis('i_u ',i_u)+'\n'
print(report)

Dies wird bei jedem Aufruf zu Debugging-Zwecken im Fenster angezeigt und liefert auch eine Zeichenfolge für den schriftlichen Bericht. Der einzige Nachteil ist, dass Sie die Variable bei jedem Aufruf der Funktion zweimal eingeben müssen.

Ich bin ein Python-Neuling und fand diese sehr nützliche Methode, um meine Bemühungen während des Programmierens zu protokollieren und zu versuchen, mit allen Objekten in Python fertig zu werden. Ein Fehler ist, dass whatis () fehlschlägt, wenn eine Funktion aufgerufen wird, die außerhalb der Prozedur beschrieben wird, in der sie verwendet wird. Zum Beispiel war int (i_f) nur ein gültiger Funktionsaufruf, weil die Funktion int Python bekannt ist. Sie könnten whatis () mit int (i_f ** 2) aufrufen, aber wenn Sie sich aus einem merkwürdigen Grund dafür entscheiden, eine Funktion namens int_squared zu definieren, muss diese innerhalb der Prozedur deklariert werden, in der whatis () verwendet wird.

0
Guy Vandegrift

dies ist eine weitere Möglichkeit, die auf dem Inhalt der Eingabevariablen basiert:

(es gibt den Namen der ersten Variablen zurück, die mit der Eingabevariable übereinstimmt, andernfalls Keine. Man kann ihn ändern, um alle Variablennamen zu erhalten, die denselben Inhalt wie die Eingabevariable haben.

def retrieve_name(x, Vars=vars()):
    for k in Vars:
        if type(x) == type(Vars[k]):
            if x is Vars[k]:
                return k
    return None
0
ses