Jak zajrzeć do obiektu Python?

291

Zaczynam pisać w różnych projektach przy użyciu Pythona (w tym tworzenie stron internetowych Django i tworzenie gier Panda3D).

Aby pomóc mi zrozumieć, co się dzieje, chciałbym po prostu „spojrzeć” wewnątrz obiektów Pythona, aby zobaczyć, jak zaznaczają - podobnie jak ich metody i właściwości.

Powiedzmy, że mam obiekt Python. Czego potrzebowałbym do wydrukowania jego zawartości? Czy to w ogóle możliwe?

littlejim84
źródło

Odpowiedzi:

352

Python ma silny zestaw funkcji introspekcji.

Spójrz na następujące wbudowane funkcje :

type()i dir()są szczególnie przydatne do sprawdzania odpowiednio typu obiektu i jego zestawu atrybutów.

Brandon E. Taylor
źródło
25
Nie wiedziałem, że termin ten to „introspekcja”. To świetna pomoc! Podobnie jak wszystkie funkcje, które mi dałeś ... Dziękuję!
littlejim84
2
właściwość, metoda i metoda statyczna nie są powiązane z introspekcją. Wszystkie te metody tworzą specjalne typy obiektów, których można używać do definiowania klas o specjalnym zachowaniu, ale nie pomagają one w sprawdzaniu tych klas lub konstrukcji.
SingleNegationElimination
Odpowiedź od @Brian poniżej pokazuje, jak wyświetlić kod źródłowy różnych obiektów Pythona z poziomu Pythona. Tego właśnie szukałem i jestem pewien, że nie będę sam. (Może warto dołączyć odniesienie do jego odpowiedzi w tej odpowiedzi, ponieważ jest ona najbardziej akceptowana).
michaelavila
To jest jak wbudowane „IntelliSense” dla Pythona. Kocham to.
Bruno Bieri,
7
myślę, że to zła odpowiedź. zamiast dać nam rozwiązanie, po prostu daje nam wszystko, co jest z tym związane w dokumentacji
Ishan Srivastava
176

object.__dict__

mtasic85
źródło
12
vars(object)jest do tego stworzony.
liberforce
6
Właściwie from pprint import pprint; pprint(vars(object))dał mi naprawdę ładny widok na zawartość mojego obiektu. Dzięki @liberforce
N. Maks
najlepszy sposób, aby zobaczyć obiekt i jego zawartość w ciągu
Peter Krauss
Jest to świetny sposób, aby zobaczyć obiekty, które implementują dowolne metody reprezentacji, lub obiekty takie jak googleapiclient.errors.HttpError, które, gdy je drukujesz, na pewno drukują niewystarczające informacje, dzięki @ mtasic85
Felipe Valdes
65

Najpierw przeczytaj źródło.

Po drugie, użyj dir()funkcji.

S.Lott
źródło
92
Odwróciłbym to zamówienie.
bayer
5
Źródło ma więcej informacji niż dir () i jest lepszym nawykiem do rozwijania.
S.Lott,
14
Pozwolę sobie być innego zdania. dir () jest o wiele szybszy i w 99% przypadków pozwala ci dowiedzieć się, czego potrzebujesz w połączeniu z help ().
bayer
7
Zgadzam się z zwykle bezużytecznym. Wiele czasu wystarczy zwykłe wywołanie dir (), dzięki czemu nie będziesz musiał przeglądać kodu źródłowego.
Sasha Chedygov
3
Czasami sprawdzanie obiektów w czasie wykonywania może być przydatne, ale nie czytanie źródeł. Np. Klasy httplib.py i ich metody :).
Denis Barmenkov
61

Dziwi mnie, że nikt jeszcze nie wspomniał o pomocy!

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

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

foo()
    foo!

Pomoc pozwala przeczytać dokumentację i dowiedzieć się, jakie atrybuty może mieć klasa, co jest dość pomocne.

Jason Baker
źródło
Następnie korzystasz z innych wymienionych tutaj technik. Ale jeśli dokumentacja jest dostępna, zastanów się nad kanonem.
Edward Falk
Nie jestem pewien, czy Python zaktualizował tę funkcję w ciągu ostatnich kilku lat, ale „help (nazwa_obiektu)” zapewnia pełny przegląd w bardzo uporządkowanym formacie. To jest opiekun. Dzięki.
Brian Cugelman
27

Jeśli jest to eksploracja, aby zobaczyć, co się dzieje, polecam spojrzeć na IPython . Dodaje to różne skróty w celu uzyskania dokumentacji obiektów, właściwości, a nawet kodu źródłowego. Na przykład dołączając „?” funkcja da pomoc dla obiektu (w rzeczywistości skrót do „help (obj)”, co przy użyciu dwóch? („ func??”) wyświetli kod źródłowy, jeśli jest dostępny.

Istnieje również wiele dodatkowych udogodnień, takich jak uzupełnianie tabulatorów, ładne drukowanie wyników, historia wyników itp., Które sprawiają, że jest to bardzo przydatne w tego rodzaju programowaniu eksploracyjnym.

Dla bardziej programowego wykorzystania introspekcji, podstawowe builtins podoba dir(), vars(), getattretc będzie użyteczny, ale jest warta twojego czasu na sprawdzeniu sprawdzić moduł. Aby pobrać źródło funkcji, użyj „ inspect.getsource” np., Stosując ją do siebie:

>>> 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 jest również często przydatny, jeśli masz do czynienia z zawijaniem lub manipulowaniem funkcjami, ponieważ poda nazwy i wartości domyślne parametrów funkcji.

Brian
źródło
17

Jeśli interesuje Cię GUI, spójrz na objbrowser . Wykorzystuje moduł inspekcji ze standardowej biblioteki Python do introspekcji obiektów pod spodem.

objbrowserscreenshot

titusjan
źródło
9

Możesz wymienić atrybuty obiektu za pomocą dir () w powłoce:

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

Oczywiście istnieje również moduł inspekcji: http://docs.python.org/library/inspect.html#module-inspect

Bayer
źródło
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
źródło
4
Działa to dobrze w Pythonie 3, jeśli po prostu dodasz pareny wokół wydruków.
ConstantineK
8

Spróbuj 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)

Wynik:

__main__.A at 0x1debd68L (
    _p = 8, 
    foo = [0, 1, 2, ..., 7, 8, 9], 
    s = 5
)
Symon
źródło
7

Inni wspominali już o wbudowanym dir (), który brzmi jak to, czego szukasz, ale oto kolejna dobra wskazówka. Wiele bibliotek - w tym większość bibliotek standardowych - jest rozpowszechnianych w formie źródłowej. Oznacza to, że możesz dość łatwo odczytać kod źródłowy bezpośrednio. Sztuka polega na znalezieniu go; na przykład:

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

Plik * .pyc jest skompilowany, więc usuń końcowy „c” i otwórz nieskompilowany plik * .py w swoim ulubionym edytorze lub przeglądarce plików:

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

Uważam, że jest to niezwykle przydatne do odkrywania rzeczy, takich jak które wyjątki są wywoływane z danego API. Tego rodzaju szczegóły rzadko są dobrze udokumentowane w świecie Pythona.

Ryan Bright
źródło
7

Chociaż pprintinni już wspominali, chciałbym dodać trochę kontekstu.

Moduł pprint umożliwia „dowolne drukowanie” dowolnych struktur danych w języku Python w formie, która może być wykorzystana jako dane wejściowe do interpretera. Jeśli sformatowane struktury zawierają obiekty, które nie są podstawowymi typami języka Python, reprezentacja może nie być wczytywalna. Może tak być w przypadku uwzględnienia obiektów takich jak pliki, gniazda, klasy lub instancje, a także wielu innych wbudowanych obiektów, które nie są reprezentowalne jako stałe Pythona.

pprintmoże być bardzo poszukiwany przez programistów z doświadczeniem PHP, którzy szukają alternatywy dla var_dump().

Obiekty z atrybutem dict można ładnie zrzucić za pomocą pprint()mieszania z vars(), co zwraca __dict__atrybut dla modułu, klasy, instancji itp .:

from pprint import pprint
pprint(vars(your_object))

Więc nie ma potrzeby pętli .

Aby zrzucić wszystkie zmienne zawarte w zasięgu globalnym lub lokalnym, po prostu użyj:

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

locals()pokazuje zmienne zdefiniowane w funkcji.
Przydatny jest również dostęp do funkcji z odpowiadającą im nazwą jako kluczem ciągłym , między innymi :

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

Podobnie, za pomocą, dir()aby zobaczyć zawartość modułu lub atrybuty obiektu.

I jest jeszcze więcej.

wp78de
źródło
4

Jeśli chcesz przyjrzeć się parametrom i metodom, jak zauważyli inni, możesz użyć pprintlubdir()

Jeśli chcesz zobaczyć rzeczywistą wartość zawartości, możesz to zrobić

object.__dict__

Lakshman Prasad
źródło
4

Dwa świetne narzędzia do sprawdzania kodu to:

  1. IPython . Terminal pythonowy, który pozwala na sprawdzenie za pomocą uzupełniania tabulacji.

  2. Zaćmienie za pomocą wtyczki PyDev . Ma doskonały debugger, który pozwala na łamanie w danym miejscu i sprawdzanie obiektów poprzez przeglądanie wszystkich zmiennych jako drzewa. Możesz nawet użyć wbudowanego terminala, aby wypróbować kod w tym miejscu lub wpisać obiekt i nacisnąć „.” aby zawierał podpowiedzi do kodu.

wprowadź opis zdjęcia tutaj

frmdstryr
źródło
3

pprint i dir razem działają świetnie

sqram
źródło
3

Do tego celu służy kompilacja biblioteki kodów Pythona: inspekcja Wprowadzono w Pythonie 2.7

Jonathan
źródło
3

Jeśli chcesz zobaczyć kod źródłowy funkcji odpowiadającej obiektowi myobj, możesz wpisać iPythonlub Jupyter Notebook:

myobj??

Sahar
źródło
2
import pprint

pprint.pprint(obj.__dict__)

lub

pprint.pprint(vars(obj))
Northtree
źródło
Chociaż ten kod może odpowiedzieć na pytanie, zapewnienie dodatkowego kontekstu dotyczącego tego, jak i / lub dlaczego rozwiązuje problem, poprawiłoby długoterminową wartość odpowiedzi.
Alexander
1

Jeśli chcesz zajrzeć do aktywnego obiektu, inspectdobrą odpowiedzią jest moduł Pythona . Ogólnie rzecz biorąc, działa w celu uzyskania kodu źródłowego funkcji zdefiniowanych w pliku źródłowym gdzieś na dysku. Jeśli chcesz uzyskać źródło funkcji na żywo i lambd, które zostały zdefiniowane w tłumaczu, możesz użyć dill.source.getsourcez dill. Może również uzyskać kod z metod klasy i funkcji powiązanych lub niezwiązanych zdefiniowanych w curry ... jednak kompilacja tego kodu może nie być możliwa bez kodu obiektu otaczającego.

>>> 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
źródło
1

vars (obj) zwraca atrybuty obiektu.

Omid Farvid
źródło
0

Ponadto, jeśli chcesz przejrzeć listę i słowniki, możesz użyć pprint ()

Glader
źródło
0

Wiele dobrych wskazówek już teraz, ale o najkrótszych i najłatwiejszych (niekoniecznie najlepszych) trzeba jeszcze wspomnieć:

object?
fmb
źródło
-3

Spróbuj użyć:

print(object.stringify())
  • gdzie objectjest nazwa zmiennej obiektu, który próbujesz sprawdzić.

Wyświetla ładnie sformatowane i tabulowane dane wyjściowe pokazujące całą hierarchię kluczy i wartości w obiekcie.

UWAGA: Działa to w python3. Nie jestem pewien, czy działa we wcześniejszych wersjach

AKTUALIZACJA: To nie działa na wszystkich typach obiektów. Jeśli napotkasz jeden z tych typów (np. Obiekt Request), użyj jednego z następujących:

  • dir(object())

lub

import pprint następnie: pprint.pprint(object.__dict__)

Ira Herman
źródło
1
Nie działa na obiekcie „Request” „Obiekt Request” nie ma atrybutu „stringify” ”
AlxVallejo