Este hilo discute cómo obtener el nombre de una función como una cadena en Python: ¿Cómo obtener el nombre de una función como una cadena?
¿Cómo puedo hacer lo mismo para una variable? A diferencia de las funciones, las variables de Python no tienen el __name__
atributo.
En otras palabras, si tengo una variable como:
foo = dict()
foo['bar'] = 2
Estoy buscando una función / atributo, por ejemplo retrieve_name()
, para crear un DataFrame en Pandas a partir de esta lista , donde los nombres de columna están dados por los nombres de los diccionarios reales:
# List of dictionaries for my DataFrame
list_of_dicts = [n_jobs, users, queues, priorities]
columns = [retrieve_name(d) for d in list_of_dicts]
pip3 install python-varname==0.1.5
; importado usandofrom varname import nameof
test = {}
print(varname.nameof(test))
for i in [0]:
print(varname.nameof(test))
la primera impresión datest
, la impresión en el bucle aumentaVarnameRetrievingError: Callee's node cannot be detected.
v0.2.0
Los únicos objetos en Python que tienen nombres canónicos son módulos, funciones y clases, y, por supuesto, no hay garantía de que este nombre canónico tenga algún significado en ningún espacio de nombres después de que la función o clase haya sido definida o importado el módulo. Estos nombres también se pueden modificar después de crear los objetos, por lo que no siempre son particularmente confiables.
Lo que desea hacer no es posible sin recorrer recursivamente el árbol de objetos con nombre ; un nombre es una referencia unidireccional a un objeto. Un objeto Python común o de variedad de jardín no contiene referencias a sus nombres. ¡Imagínese si cada entero, cada dict, cada lista, cada booleano necesitara mantener una lista de cadenas que representaran nombres que se referían a él! Sería una pesadilla de implementación, con poco beneficio para el programador.
fuente
__name__
siempre se puede modificar, lo que significa que el nombre "canónico" puede no ser un nombre que pueda usarse para obtener el objeto (por ejemplo, al crear clases dinámicamente).Incluso si los valores de las variables no apuntan al nombre, tiene acceso a la lista de todas las variables asignadas y su valor, por lo que me sorprende que solo una persona sugiera recorrer allí para buscar su nombre de var.
Alguien mencionó en esa respuesta que es posible que tenga que caminar por la pila y verificar los locales y globales de todos para encontrar
foo
, pero sifoo
está asignado en el alcance donde está llamando a estaretrieve_name
función, puede usarinspect
's'current frame
para obtener todas esas variables locales .Mi explicación puede ser un poco demasiado prolija (tal vez debería haber usado un "foo" menos palabras), pero así es como se vería en el código ( Tenga en cuenta que si hay más de una variable asignada al mismo valor, lo hará obtener ambos nombres de variables ):
Si está llamando a esta función desde otra función, algo como:
Y desea el en
baz
lugar debar
, solo tendrá que retroceder un alcance más. Esto se puede hacer agregando un extra.f_back
en lacaller_local_vars
inicialización.Vea un ejemplo aquí: ideone
fuente
import hooks
,ironpython
yjython
a, b = 2, 2
,retrieve_name(a)
yretrieve_name(b)
ambos regresarán['a', 'b']
o['b', 'a']
true
para unais
comparacióndef foo(bar): retrieve_name(bar)
, siempre devolverá la barra, pero ¿qué pasa si deseafoo(baz)
volverbaz
) en lugar debar
?callers_local_vars
para ir un alcance más atrás para que vea el alcance de lo que sea que llamefoo
. Cambie la línea para serinspect.currentframe().f_back.f_back.f_locals.items()
(observe el extraf_back
).Con Python 3.8 uno simplemente puede usar la función de depuración de f-string:
fuente
f'{foo=}'.split('=')[0].split('.')[-1]
En python3, esta función obtendrá el nombre más externo en la pila:
Es útil en cualquier parte del código. Atraviesa la pila invertida buscando el primer partido.
fuente
retrieve_name(SomeClass.some_attribute)
no funciona. ¿Puedes ayudar más en eso?stop_on_error
No creo que esto sea posible. Considere el siguiente ejemplo:
El
a
yb
apunta al mismo objeto, pero el objeto no puede saber qué variables apuntan a él.fuente
Se usa así:
fuente
name(variable=variable)
generará salida['variable']
y usar noname(variable=another_variable)
generará salida, sino más bien .['another_variable']
['variable']
>>> a = []
>>> b = a
>>> name(a=b)
['a']
>>> name(b=a)
['b']
`Aquí hay un enfoque. No recomendaría esto para nada importante, porque será bastante frágil. Pero puede hacerse.
Cree una función que use el
inspect
módulo para encontrar el código fuente que lo llamó. Luego, puede analizar el código fuente para identificar los nombres de las variables que desea recuperar. Por ejemplo, aquí hay una función llamadaautodict
que toma una lista de variables y devuelve los nombres de las variables de asignación de diccionario a sus valores. P.ej:Daría:
Inspeccionar el código fuente en sí es mejor que buscar a través de
locals()
oglobals()
porque este último enfoque no le dice cuáles de las variables son las que desea.En cualquier caso, aquí está el código:
La acción ocurre en la línea con
inspect.getouterframes
, que devuelve la cadena dentro del código que llamóautodict
.La desventaja obvia de este tipo de magia es que hace suposiciones sobre cómo está estructurado el código fuente. Y, por supuesto, no funcionará si se ejecuta dentro del intérprete.
fuente
Escribí el paquete de brujería para hacer este tipo de magia de manera robusta. Puedes escribir:
y pasar eso al constructor del marco de datos. Es equivalente a:
fuente
Si desea escribir su propia función, puede hacerlo de manera que pueda verificar una variable definida en locales y luego verificar las variables globales. Si no se encuentra nada, puede comparar en id () para ver si la variable apunta a la misma ubicación en la memoria.
Si su variable está en una clase, puede usar className. dict .keys () o vars (self) para ver si su variable ha sido definida.
fuente
locals
yglobals
... y te arriesgas a equivocarte si no existe ninguno. Es un montón de trabajo sin ganancia útil real.En Python, los
def
yclass
las palabras clave se unirán un nombre específico al objeto que definen (función o clase). Del mismo modo, los módulos reciben un nombre en virtud de ser llamados algo específico en el sistema de archivos. En los tres casos, hay una forma obvia de asignar un nombre "canónico" al objeto en cuestión.Sin embargo, para otros tipos de objetos, tal nombre canónico simplemente puede no existir . Por ejemplo, considere los elementos de una lista. Los elementos en la lista no se nombran individualmente, y es completamente posible que la única forma de referirse a ellos en un programa sea mediante el uso de índices de lista en la lista que lo contiene. Si dicha lista de objetos se pasó a su función, no podría asignar identificadores significativos a los valores.
Python no guarda el nombre en el lado izquierdo de una tarea en el objeto asignado porque:
Entonces, por ejemplo, las funciones definidas usando
lambda
siempre tendrán el "nombre"<lambda>
, en lugar de un nombre de función específico.El mejor enfoque sería simplemente pedirle a la persona que llama que pase una lista (opcional) de nombres. Si escribir
'...','...'
es demasiado engorroso, puede aceptar, por ejemplo, una sola cadena que contenga una lista de nombres separados por comas (como lonamedtuple
hace).fuente
locals (): devuelve un diccionario que contiene las variables locales del ámbito actual. iterando a través de este diccionario podemos verificar la clave que tiene un valor igual a la variable definida, solo extrayendo la clave nos dará el texto de la variable en formato de cadena.
desde (después de un poco de cambios) https://www.tutorialspoint.com/How-to-get-a-variable-name-as-a-string-in-Python
fuente
Creo que es muy difícil hacer esto en Python debido al simple hecho de que nunca sabrás el nombre de la variable que estás usando. Entonces, en su ejemplo, podrías hacer:
En vez de:
fuente
Solo otra forma de hacerlo en función del contenido de la variable de entrada:
(devuelve el nombre de la primera variable que coincide con la variable de entrada; de lo contrario, ninguna. Se puede modificar para obtener todos los nombres de variables que tienen el mismo contenido que la variable de entrada)
fuente
Esta función imprimirá el nombre de la variable con su valor:
fuente
Tengo un método, y aunque no es el más eficiente ... ¡funciona! (y no involucra ningún módulo sofisticado).
Básicamente se compara su ID de variable a variables globales () identificadores de variables' , a continuación, devuelve el nombre del partido.
fuente
Si el objetivo es ayudarlo a realizar un seguimiento de sus variables, puede escribir una función simple que etiquete la variable y devuelva su valor y tipo. Por ejemplo, suponga que i_f = 3.01 y lo redondea a un número entero llamado i_n para usar en un código, y luego necesita una cadena i_s que irá a un informe.
Esto se imprime en la ventana en cada llamada con fines de depuración y también produce una cadena para el informe escrito. El único inconveniente es que debe escribir la variable dos veces cada vez que llama a la función.
Soy un novato en Python y encontré esta forma muy útil de registrar mis esfuerzos mientras programo e intento hacer frente a todos los objetos en Python. Una falla es que whatis () falla si llama a una función descrita fuera del procedimiento donde se usa. Por ejemplo, int (i_f) era una llamada de función válida solo porque Python conoce la función int . Puede llamar a whatis () usando int (i_f ** 2), pero si por alguna extraña razón elige definir una función llamada int_squared, debe declararse dentro del procedimiento donde se usa whatis ().
fuente
Quizás esto podría ser útil:
La función pasa por la lista de ID de valores del ámbito global (el espacio de nombres podría editarse), encuentra el índice de la variable o función deseada / requerida en función de su ID, y luego devuelve el nombre de la lista de nombres globales basados en el índice adquirido.
fuente
El siguiente método no devolverá el nombre de la variable, pero con este método puede crear fácilmente un marco de datos si la variable está disponible en el ámbito global.
fuente
Para las constantes, puede usar una enumeración, que admite recuperar su nombre.
fuente
Intento obtener el nombre de inspeccionar a los locales, pero no puede procesar varios me gusta a [1], b.val. Después de eso, tuve una nueva idea: ¡obtener el nombre var del código, y lo intento succ! código como a continuación:
fuente
Puede intentar lo siguiente para recuperar el nombre de una función que definió (aunque no funciona para las funciones integradas):
fuente