¿Cómo miro dentro de un objeto Python?

291

Estoy empezando a codificar en varios proyectos usando Python (incluido el desarrollo web Django y el desarrollo de juegos Panda3D).

Para ayudarme a comprender lo que está sucediendo, me gustaría básicamente 'mirar' dentro de los objetos de Python para ver cómo funcionan, como sus métodos y propiedades.

Digamos que tengo un objeto Python, ¿qué necesitaría para imprimir su contenido? ¿Es eso posible?

littlejim84
fuente

Respuestas:

352

Python tiene un fuerte conjunto de características de introspección.

Eche un vistazo a las siguientes funciones integradas :

type()y dir()son particularmente útiles para inspeccionar el tipo de un objeto y su conjunto de atributos, respectivamente.

Brandon E Taylor
fuente
25
No sabía que el término era 'introspección'. Esa es una gran ayuda! Además de todas las funciones que me has dado ... ¡Gracias!
littlejim84
2
propiedad, método de clase y método estático no están relacionados con la introspección. Todos estos métodos crean tipos especiales de objetos que pueden usarse para definir clases con un comportamiento especial, pero no son de ayuda para inspeccionar esas clases o construcciones.
SingleNegationElimination
La respuesta de @Brian a continuación muestra cómo ver también el código fuente de varios objetos de Python desde Python. Eso es lo que estaba buscando originalmente y estoy seguro de que no estaré solo. (Podría valer la pena incluir una referencia a su respuesta en esta respuesta, ya que es la más aceptada.)
michaelavila
Es como "IntelliSense" incorporado para python. Me encanta.
Bruno Bieri
77
Creo que es una mala respuesta. en lugar de darnos una solución, simplemente nos da todo lo relacionado con eso en la documentación
Ishan Srivastava
176

object.__dict__

mtasic85
fuente
12
vars(object)está hecho para eso.
liberforce
66
En realidad, from pprint import pprint; pprint(vars(object))me dio una buena vista sobre el contenido de mi objeto. Gracias @liberforce
N. Maks
la mejor manera de ver el objeto y su contenido en una cadena
Peter Krauss
Esta es una excelente manera de ver los objetos que implementan cualquier método de representación, u objetos como googleapiclient.errors.HttpError que cuando los imprime imprimen información insuficiente, gracias @ mtasic85
Felipe Valdes
65

Primero, lee la fuente.

Segundo, usa la dir()función.

S.Lott
fuente
92
Revertiría ese orden.
bayer
55
La fuente es más informativa que dir () y un mejor hábito para desarrollar.
S.Lott
14
Siento disentir. dir () es mucho más rápido y en el 99% de los casos, le permite descubrir lo que necesita en combinación con help ().
bayer
77
Estoy de acuerdo con usualmente inútil. Muchas veces, una simple llamada a dir () será suficiente, lo que le ahorrará la molestia de tener que mirar a través del código fuente.
Sasha Chedygov
3
En ocasiones, inspeccionar objetos en tiempo de ejecución puede ser útil, pero leer fuentes no. Por ejemplo, las clases httplib.py y sus métodos :).
Denis Barmenkov
61

¡Me sorprende que nadie haya mencionado la ayuda todavía!

In [1]: def foo():
   ...:     "foo!"
   ...:

In [2]: help(foo)
Help on function foo in module __main__:

foo()
    foo!

La ayuda le permite leer la cadena de documentación y tener una idea de los atributos que podría tener una clase, lo cual es bastante útil.

Jason Baker
fuente
Luego usas las otras técnicas mencionadas aquí. Pero si la cadena de documentación está disponible, considérela canon.
Edward Falk
No estoy seguro de si Python actualizó esta función en los últimos años, pero "help (object_name)" proporciona una descripción completa en un formato altamente estructurado. Es un guardián. Gracias.
Brian Cugelman
27

Si esto es para explorar para ver qué está pasando, recomendaría mirar IPython . Esto agrega varios accesos directos para obtener una documentación de objetos, propiedades e incluso código fuente. Por ejemplo, agregar un "?" a una función proporcionará la ayuda para el objeto (efectivamente, un acceso directo para "help (obj)", cuando se use dos? '(" func??") mostrará el código fuente si está disponible.

También hay muchas comodidades adicionales, como la finalización de pestañas, la impresión bonita de resultados, el historial de resultados, etc., que lo hacen muy útil para este tipo de programación exploratoria.

Para un uso más programática de la introspección, las órdenes internas básicas como dir(), vars(), getattretc. será útil, pero es bien vale la pena su tiempo para revisar la inspeccione módulo. Para buscar el origen de una función, use " inspect.getsource" por ejemplo, aplicándolo a sí mismo:

>>> print inspect.getsource(inspect.getsource)
def getsource(object):
    """Return the text of the source code for an object.

    The argument may be a module, class, method, function, traceback, frame,
    or code object.  The source code is returned as a single string.  An
    IOError is raised if the source code cannot be retrieved."""
    lines, lnum = getsourcelines(object)
    return string.join(lines, '')

inspect.getargspec También es útil con frecuencia si se trata de envolver o manipular funciones, ya que proporcionará los nombres y los valores predeterminados de los parámetros de la función.

Brian
fuente
18

Si está interesado en una GUI para esto, eche un vistazo a objbrowser . Utiliza el módulo de inspección de la biblioteca estándar de Python para la introspección de objetos debajo.

objbrowserscreenshot

titusjan
fuente
9

Puede enumerar los atributos de un objeto con dir () en el shell:

>>> dir(object())
['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']

Por supuesto, también está el módulo de inspección: http://docs.python.org/library/inspect.html#module-inspect

bayer
fuente
8
"""Visit http://diveintopython.net/"""

__author__ = "Mark Pilgrim ([email protected])"


def info(object, spacing=10, collapse=1):
    """Print methods and doc strings.

    Takes module, class, list, dictionary, or string."""
    methodList = [e for e in dir(object) if callable(getattr(object, e))]
    processFunc = collapse and (lambda s: " ".join(s.split())) or (lambda s: s)
    print "\n".join(["%s %s" %
                     (method.ljust(spacing),
                      processFunc(str(getattr(object, method).__doc__)))
                     for method in methodList])

if __name__ == "__main__":
    print help.__doc__
Erenon
fuente
44
Esto funciona bien en Python 3 si solo agrega parens alrededor de las impresiones.
ConstantineK
8

Prueba ppretty

from ppretty import ppretty


class A(object):
    s = 5

    def __init__(self):
        self._p = 8

    @property
    def foo(self):
        return range(10)


print ppretty(A(), indent='    ', depth=2, width=30, seq_length=6,
              show_protected=True, show_private=False, show_static=True,
              show_properties=True, show_address=True)

Salida:

__main__.A at 0x1debd68L (
    _p = 8, 
    foo = [0, 1, 2, ..., 7, 8, 9], 
    s = 5
)
Symon
fuente
7

Otros ya han mencionado el dir () incorporado que suena como lo que estás buscando, pero aquí hay otro buen consejo. Muchas bibliotecas, incluida la mayoría de la biblioteca estándar, se distribuyen en forma de origen. Lo que significa que puede leer fácilmente el código fuente directamente. El truco está en encontrarlo; por ejemplo:

>>> import string
>>> string.__file__
'/usr/lib/python2.5/string.pyc'

El archivo * .pyc está compilado, por lo tanto, elimine la 'c' final y abra el archivo * .py sin compilar en su editor o visor de archivos favorito:

/usr/lib/python2.5/string.py

He encontrado esto increíblemente útil para descubrir cosas como las excepciones que se generan de una API determinada. Este tipo de detalles rara vez está bien documentado en el mundo de Python.

Ryan Bright
fuente
7

Si bien pprintotros ya lo han mencionado, me gustaría agregar algo de contexto.

El módulo pprint ofrece la capacidad de "imprimir de manera bonita" estructuras de datos arbitrarias de Python en una forma que puede usarse como entrada para el intérprete. Si las estructuras formateadas incluyen objetos que no son tipos fundamentales de Python, la representación puede no ser cargable. Este puede ser el caso si se incluyen objetos como archivos, sockets, clases o instancias, así como muchos otros objetos integrados que no son representables como constantes de Python.

pprintpodría ser muy demandado por desarrolladores con experiencia en PHP que buscan una alternativa a var_dump().

Los objetos con un atributo dict se pueden volcar muy bien usando pprint()mezclado con vars(), que devuelve el __dict__atributo para un módulo, clase, instancia, etc.

from pprint import pprint
pprint(vars(your_object))

Entonces, no hay necesidad de un bucle .

Para volcar todas las variables contenidas en el ámbito global o local simplemente use:

pprint(globals())
pprint(locals())

locals()muestra variables definidas en una función.
También es útil acceder a funciones con su nombre correspondiente como una clave de cadena, entre otros usos :

locals()['foo']() # foo()
globals()['foo']() # foo()

Del mismo modo, se utiliza dir()para ver el contenido de un módulo o los atributos de un objeto.

Y aún hay más.

wp78de
fuente
4

Si desea ver los parámetros y métodos, como otros han señalado, puede usar pprintodir()

Si desea ver el valor real de los contenidos, puede hacer

object.__dict__

Lakshman Prasad
fuente
4

Dos excelentes herramientas para inspeccionar el código son:

  1. IPython . Un terminal de Python que le permite inspeccionar usando la finalización de tabulación.

  2. Eclipse con el complemento PyDev . Tiene un excelente depurador que le permite romper en un lugar determinado e inspeccionar objetos explorando todas las variables como un árbol. Incluso puede usar el terminal incorporado para probar el código en ese punto o escribir el objeto y presionar '.' para que le dé sugerencias de código para usted.

ingrese la descripción de la imagen aquí

frmdstryr
fuente
3

pprint y dir juntos funcionan muy bien

sqram
fuente
3

Hay una compilación de la biblioteca de código de Python solo para este propósito: inspeccionar Introducido en Python 2.7

Jonathan
fuente
3

Si está interesado en ver el código fuente de la función correspondiente al objeto myobj, puede escribir iPythono Jupyter Notebook:

myobj??

Sahar
fuente
2
import pprint

pprint.pprint(obj.__dict__)

o

pprint.pprint(vars(obj))
northtree
fuente
Si bien este código puede responder la pregunta, proporcionar un contexto adicional con respecto a cómo y / o por qué resuelve el problema mejoraría el valor a largo plazo de la respuesta.
Alexander
1

Si desea mirar dentro de un objeto vivo, entonces el inspectmódulo de Python es una buena respuesta. En general, funciona para obtener el código fuente de las funciones que se definen en un archivo fuente en algún lugar del disco. Si desea obtener la fuente de funciones en vivo y lambdas que se definieron en el intérprete, puede usar dill.source.getsourcedesde dill. También puede obtener el código de métodos y funciones de clase vinculados o no definidos definidos en curry ... sin embargo, es posible que no pueda compilar ese código sin el código del objeto adjunto.

>>> from dill.source import getsource
>>> 
>>> def add(x,y):
...   return x+y
... 
>>> squared = lambda x:x**2
>>> 
>>> print getsource(add)
def add(x,y):
  return x+y

>>> print getsource(squared)
squared = lambda x:x**2

>>> 
>>> class Foo(object):
...   def bar(self, x):
...     return x*x+x
... 
>>> f = Foo()
>>> 
>>> print getsource(f.bar)
def bar(self, x):
    return x*x+x

>>> 
Mike McKerns
fuente
1

vars (obj) devuelve los atributos de un objeto.

Omid Farvid
fuente
0

Además, si desea mirar dentro de la lista y los diccionarios, puede usar pprint ()

Glader
fuente
0

Muchos buenos consejos ya, pero el más corto y fácil (no necesariamente el mejor) aún no se ha mencionado:

object?
fmb
fuente
-3

Intenta usar:

print(object.stringify())
  • donde objectestá el nombre de la variable del objeto que está intentando inspeccionar.

Esto imprime una salida con formato y pestañas que muestra toda la jerarquía de claves y valores en el objeto.

NOTA: Esto funciona en python3. No estoy seguro si funciona en versiones anteriores

ACTUALIZACIÓN: Esto no funciona en todos los tipos de objetos. Si encuentra uno de esos tipos (como un objeto Request), use uno de los siguientes:

  • dir(object())

o

import pprint luego: pprint.pprint(object.__dict__)

Ira Herman
fuente
1
No funciona en un objeto 'Solicitud' "El objeto 'Solicitud' no tiene el atributo 'stringify'"
AlxVallejo