¿Es posible recuperar cualquier información de clase de un objeto de marco? Sé cómo obtener el archivo (frame.f_code.co_filename), function (frame.f_code.co_name) y el número de línea (frame.f_lineno), pero me gustaría poder obtener también el nombre de la clase del objeto activo instancia del marco (o None si no está en una instancia).Python: ¿Cómo recuperar información de clase de un objeto 'frame'?
Respuesta
No creo que, en el nivel de objeto marco, hay alguna forma de encontrar el objeto real de la función python que se ha llamado.
Sin embargo, si su código se basan en la convención común: nombrar el parámetro de ejemplar de un método self
, entonces se podría hacer lo siguiente:
def get_class_from_frame(fr):
import inspect
args, _, _, value_dict = inspect.getargvalues(fr)
# we check the first parameter for the frame function is
# named 'self'
if len(args) and args[0] == 'self':
# in that case, 'self' will be referenced in value_dict
instance = value_dict.get('self', None)
if instance:
# return its class
return getattr(instance, '__class__', None)
# return None otherwise
return None
Si no desea utilizar getargvalues
, puede use directamente frame.f_locals
en lugar de value_dict
y frame.f_code.co_varnames[:frame.f_code.co_argcount]
en lugar de args
.
Tenga en cuenta que esto es todavía sólo un partido basado en la convención, por lo que no es portátil, y propenso a errores:
- si una función uso no método
self
como el primer nombre del parámetro, entoncesget_class_from_frame
va mal devuelve la clase del primer parámetro. - puede ser engañoso cuando se trabaja con descriptores (devolverá la clase del descriptor, no de la instancia real a la que se accede).
@classmethod
y@staticmethod
no tomarán un parámetroself
y se implementan con descriptores.- y seguramente mucho más
Dependiendo de qué es exactamente lo que quiere hacer, es posible que desee tomar algún tiempo para profundizar y encontrar soluciones para todos estos problemas (se puede comprobar la función de marco de existir en el la clase devuelta y comparte la misma fuente, es posible detectar las llamadas del descriptor, lo mismo para los métodos de clase, etc.)
Esto es un poco más corto, pero tiene más o menos el mismo valor. Devuelve Ninguno si el nombre de la clase no está disponible.
def get_class_name():
f = sys._getframe(1)
try:
class_name = f.f_locals['self'].__class__.__name__
except KeyError:
class_name = None
return class_name
¡Buena respuesta! Mejor aún, podrías hacer '' f.f_locals ['__ clase __'] .__ nombre__'', que también debería cubrir los casos '' @ classmethod'' y '' @ staticmethod''. –
@LucioPaiva que no funciona. No hay clave '' __class __ ''en f_locals. – Pithikos
Acabo de encontrar esta publicación porque me enfrentaba con el mismo problema. Sin embargo, no consideré que el método del "yo" sea una solución aceptable por todos los motivos ya enumerados.
El siguiente código muestra un enfoque diferente: dado un objeto de marco, busca en las globales un objeto con un nombre de miembro y un bloque de código coincidentes. La búsqueda no es exhaustiva, por lo que es posible que no se descubran todas las clases, pero las clases que se encuentran deben ser las que buscamos porque verificamos los códigos coincidentes.
Objeto del código es anteponer un nombre de función con su nombre de clase, si se encuentran:
def get_name(frame):
code = frame.f_code
name = code.co_name
for objname, obj in frame.f_globals.iteritems():
try:
assert obj.__dict__[name].func_code is code
except Exception:
pass
else: # obj is the class that defines our method
name = '%s.%s' % (objname, name)
break
return name
Nota el uso de __dict__
en lugar de getattr
para evitar la captura de las clases derivadas.
Tenga en cuenta además que se puede evitar una búsqueda global si self = frame.f_locals['self']; obj = self.__class__
da una coincidencia, o cualquier obj in self.__class__.__bases__
o más profundo, por lo que sin duda hay espacio para la optimización/hibridación.
Si un método es un método de clase, la clase será el primer argumento. Esto imprime el tipo del primer arg si está presente para cada marco de pila de llamadas:
def some_method(self):
for f in inspect.getouterframes(inspect.currentframe()):
args, _,_, local_dict = inspect.getargvalues(f[0])
if args:
first_arg = args[0]
first_value = local_dict[first_arg]
print(type(first_value).__name__)
- 1. cómo recuperar información de la fila eliminada
- 2. recuperar un objeto de hashset en C#
- 3. ¿Recuperar información múltiple por un solo número?
- 4. Recuperar texto de un objeto de RemoteViews
- 5. ¿Cómo puedo recuperar la información del monitor?
- 6. Extrayendo información de un Tuple (Python)
- 7. ¿Cómo puedo recuperar una clase anidada en python?
- 8. JavaScript: ¿Recuperar nombres clave de un objeto?
- 9. ¿Cómo recuperar todas las ID de objeto?
- 10. ¿Cómo se asigna un nombre de clase totalmente calificado a su objeto de clase en Python?
- 11. Recuperar método Información de una función F #
- 12. ¿Convertir cadena a objeto de clase Python?
- 13. Derivando clase de `objeto` en python
- 14. recuperar único objeto de NSFetchRequest
- 15. Cómo recuperar información de forma programática desde LDAP
- 16. Cómo recuperar información EXIF de una imagen en Rails
- 17. ¿Cómo recuperar información útil del sistema en Java?
- 18. Cómo recuperar datos de la clase de cursor
- 19. Recuperar información de la versión desde archivos de gran tamaño
- 20. Recuperar encabezados de explorador en Python
- 21. clase Nombre de clase (objeto), ¿qué tipo de palabra es 'objeto' en Python?
- 22. ¿Cómo clonar un objeto generador de Python?
- 23. Obtener el nombre de clase totalmente calificado de un objeto en Python
- 24. Obtener la función de Python para un objeto de código
- 25. Active Directory: Recuperar información del usuario
- 26. Recuperar cuadro delimitador de un objeto multipolígono geodjango
- 27. Python/Tkinter Cómo actualizar la información en la cuadrícula
- 28. Recuperar datos de XML python
- 29. Objeto de intercambio (instancia de clase) en python usando Managers
- 30. Idiomatic Python para generar un nuevo objeto desde una clase
Gracias por su respuesta, Clément; es detallado y reflexivo. ¡Todavía espero obtener más de una respuesta! Pero si no, este tendrá que ser suficiente ... –
OK, esperó el tiempo suficiente. ¡Esta es una buena respuesta! Esperaba un mejor soporte de las estructuras de cuadros, pero es lo que es. Gracias de nuevo, Clément! –
Para agregar uno a la lista, tenga cuidado de que 'self' pueda ser una instancia de una clase derivada, que podría no ser la que nos interesa. – gertjan