Come guardo dentro un oggetto Python?


291

Sto iniziando a programmare in vari progetti usando Python (incluso lo sviluppo web di Django e lo sviluppo di giochi Panda3D).

Per aiutarmi a capire cosa sta succedendo, vorrei sostanzialmente "guardare" all'interno degli oggetti Python per vedere come spuntano, come i loro metodi e proprietà.

Quindi dire che ho un oggetto Python, di cosa avrei bisogno per stampare il suo contenuto? È anche possibile?

Risposte:


352

Python ha un solido set di funzionalità di introspezione.

Dai un'occhiata alle seguenti funzioni integrate :

type()e dir()sono particolarmente utili per ispezionare il tipo di un oggetto e il suo insieme di attributi, rispettivamente.


25
Non sapevo che il termine fosse "introspezione". Questo è di grande aiuto! Oltre a tutte le funzioni che mi hai dato ... Grazie!
littlejim84,

2
proprietà, classmethod e staticmethod non sono correlati all'introspezione. Tutti questi metodi creano tipi speciali di oggetti che possono essere utilizzati per definire le classi con un comportamento speciale, ma non sono di alcun aiuto nell'ispezione di tali classi o costrutti.
SingleNegationElimination

La risposta di @Brian di seguito mostra come visualizzare anche il codice sorgente di vari oggetti Python dall'interno di Python. Questo è quello che stavo cercando in origine e sono sicuro che non sarò solo. (Potrebbe valere la pena includere un riferimento alla sua risposta in questa risposta poiché è la più accettata.)
michaelavila

È come "IntelliSense" incorporato per Python. Lo adoro.
Bruno Bieri,

7
penso che sia una cattiva risposta. invece di darci una soluzione ci dà solo tutto ciò che è correlato a quello nella documentazione
Ishan Srivastava,

176

object.__dict__


12
vars(object)è fatto per quello.
liberforce,

6
In realtà from pprint import pprint; pprint(vars(object))mi ha dato una vista davvero bella sul contenuto del mio oggetto. Grazie @liberforce
N. Maks

il modo migliore per vedere l'oggetto e il suo contenuto in una stringa
Peter Krauss il

Questo è un ottimo modo per vedere oggetti che implementano qualsiasi metodo di rappresentazione o oggetti come googleapiclient.errors.HttpError che quando li stampi stampano sicuramente informazioni insufficienti, grazie @ mtasic85
Felipe Valdes

65

Innanzitutto, leggi la fonte.

Secondo, usa la dir()funzione.


92
Avrei invertito quell'ordine.
Bayer,

5
La fonte è più informativa di dir () e un'abitudine migliore da sviluppare.
S.Lott,

14
Mi permetto di dissentire. dir () è molto più veloce e nel 99% dei casi scopriamo di cosa hai bisogno in combinazione con help ().
Bayer,

7
Sono d'accordo di solito inutile. Molte volte, sarà sufficiente una semplice chiamata a dir (), risparmiando così la difficoltà di dover consultare il codice sorgente.
Sasha Chedygov,

3
A volte ispezionare gli oggetti in fase di esecuzione può essere utile, ma non leggere le fonti. Ad esempio le classi httplib.py e i loro metodi :).
Denis Barmenkov,

61

Sono sorpreso che nessuno abbia ancora menzionato l'aiuto!

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

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

foo()
    foo!

La guida ti consente di leggere la documentazione e avere un'idea di quali attributi potrebbe avere una classe, il che è piuttosto utile.


Quindi usi le altre tecniche menzionate qui. Ma se il docstring è disponibile, consideralo canone.
Edward Falk,

Non sono sicuro che Python abbia aggiornato questa funzione negli ultimi anni, ma "help (nome_oggetto)" fornisce una panoramica completa in un formato altamente strutturato. È un custode. Grazie.
Brian Cugelman,

27

Se questo è per l'esplorazione per vedere cosa sta succedendo, consiglierei di guardare IPython . Ciò aggiunge varie scorciatoie per ottenere una documentazione, proprietà e persino un codice sorgente degli oggetti. Ad esempio aggiungendo un "?" a una funzione fornirà l'aiuto per l'oggetto (effettivamente una scorciatoia per "help (obj)", dove usando due? "(" func??") verrà visualizzato il codice sorgente se è disponibile.

Ci sono anche molte altre comodità, come il completamento delle schede, la stampa piuttosto dei risultati, la cronologia dei risultati ecc. Che lo rendono molto utile per questo tipo di programmazione esplorativa.

Per un uso più programmatico di introspezione, i comandi incorporati di base come dir(), vars(), getattrecc sarà utile, ma è merita il vostro tempo di controllare le ispezionare modulo. Per recuperare l'origine di una funzione, utilizzare " inspect.getsource" ad esempio, applicandolo a se stesso:

>>> 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 è spesso utile se hai a che fare con funzioni di wrapping o manipolazione, in quanto fornirà i nomi e i valori predefiniti dei parametri delle funzioni.


18

Se sei interessato a una GUI per questo, dai un'occhiata a objbrowser . Utilizza il modulo inspect dalla libreria standard Python per l'introspezione dell'oggetto sottostante.

objbrowserscreenshot


9

Puoi elencare gli attributi di un oggetto con dir () nella shell:

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

Naturalmente, c'è anche il modulo inspect : http://docs.python.org/library/inspect.html#module-inspect


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

__author__ = "Mark Pilgrim (mark@diveintopython.org)"


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__

4
Funziona bene in Python 3 se aggiungi solo parentesi attorno alle stampe.
ConstantineK,

8

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

Produzione:

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

7

Altri hanno già menzionato il dir () integrato che suona come quello che stai cercando, ma ecco un altro buon consiglio. Molte librerie, inclusa la maggior parte delle librerie standard, sono distribuite in formato sorgente. Ciò significa che puoi leggere facilmente il codice sorgente direttamente. Il trucco sta nel trovarlo; per esempio:

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

Il file * .pyc è compilato, quindi rimuovi la 'c' finale e apri il file * .py non compilato nel tuo editor preferito o nel visualizzatore di file:

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

Ho trovato questo incredibilmente utile per scoprire cose come quali eccezioni vengono sollevate da una determinata API. Questo tipo di dettaglio è raramente ben documentato nel mondo Python.


7

Mentre pprintè già stato menzionato da altri, vorrei aggiungere un po 'di contesto.

Il modulo pprint offre la possibilità di "stampare piuttosto" strutture di dati Python arbitrarie in una forma che può essere utilizzata come input per l'interprete. Se le strutture formattate includono oggetti che non sono tipi Python fondamentali, la rappresentazione potrebbe non essere caricabile. Questo può accadere se sono inclusi oggetti come file, socket, classi o istanze, nonché molti altri oggetti incorporati che non sono rappresentabili come costanti Python.

pprintpotrebbe essere molto richiesto dagli sviluppatori con un background PHP alla ricerca di un'alternativa a var_dump().

Gli oggetti con un attributo dict possono essere scaricati correttamente usando pprint()mixed with vars(), che restituisce l' __dict__attributo per un modulo, classe, istanza, ecc .:

from pprint import pprint
pprint(vars(your_object))

Quindi, non c'è bisogno di un loop .

Per scaricare tutte le variabili contenute nell'ambito globale o locale, utilizzare semplicemente:

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

locals()mostra le variabili definite in una funzione.
È anche utile accedere alle funzioni con il nome corrispondente come chiave stringa, tra gli altri usi :

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

Allo stesso modo, usando dir()per vedere il contenuto di un modulo o gli attributi di un oggetto.

E c'è ancora di più.


4

Se si desidera esaminare parametri e metodi, come altri hanno sottolineato, è possibile utilizzare pprintodir()

Se vuoi vedere il valore reale dei contenuti, puoi farlo

object.__dict__


4

Due grandi strumenti per l'ispezione del codice sono:

  1. IPython . Un terminale Python che ti permette di ispezionare usando il completamento della scheda.

  2. Eclipse con il plugin PyDev . Ha un eccellente debugger che ti permette di rompere in un determinato punto e ispezionare gli oggetti sfogliando tutte le variabili come un albero. Puoi persino usare il terminale incorporato per provare il codice in quel punto o digitare l'oggetto e premere '.' per avere suggerimenti sul codice per te.

inserisci qui la descrizione dell'immagine


3

pprint e dir insieme funzionano alla grande


3

Esiste una libreria di codici Python compilata proprio per questo scopo: inspect Introduce in Python 2.7


3

Se sei interessato a vedere il codice sorgente della funzione corrispondente all'oggetto myobj, puoi digitare iPythono Jupyter Notebook:

myobj??


2
import pprint

pprint.pprint(obj.__dict__)

o

pprint.pprint(vars(obj))

Sebbene questo codice possa rispondere alla domanda, fornire un contesto aggiuntivo riguardo a come e / o perché risolve il problema migliorerebbe il valore a lungo termine della risposta.
Alexander,

1

Se vuoi guardare dentro un oggetto live, allora il inspectmodulo di Python è una buona risposta. In generale, funziona per ottenere il codice sorgente delle funzioni definite in un file sorgente da qualche parte sul disco. Se si desidera ottenere la fonte di funzioni live e lambda definite nell'interprete, è possibile utilizzare dill.source.getsourceda dill. Può anche ottenere il codice da metodi e funzioni di classe associati o non associati definiti nei curry ... tuttavia, potresti non essere in grado di compilare quel codice senza il codice dell'oggetto che lo racchiude.

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

>>> 


0

Inoltre, se vuoi guardare all'interno dell'elenco e dei dizionari, puoi usare pprint ()


0

Molti buoni consigli già, ma il più breve e semplice (non necessariamente il migliore) deve ancora essere menzionato:

object?

-3

Prova a usare:

print(object.stringify())
  • dove si objecttrova il nome della variabile dell'oggetto che si sta tentando di ispezionare.

Questo stampa un output ben formattato e tabulato che mostra tutta la gerarchia di chiavi e valori nell'oggetto.

NOTA: funziona in python3. Non sono sicuro che funzioni nelle versioni precedenti

AGGIORNAMENTO: questo non funziona su tutti i tipi di oggetti. Se incontri uno di questi tipi (come un oggetto Request), utilizza invece uno dei seguenti:

  • dir(object())

o

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


1
Non funziona su un oggetto 'Richiesta' "L'oggetto 'Richiesta' non ha alcun attributo 'stringify'"
AlxVallejo,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.