Як я заглядаю всередину об’єкта Python?


291

Я починаю кодувати різні проекти за допомогою Python (включаючи веб-розробку Django та розробку ігор Panda3D).

Щоб допомогти мені зрозуміти, що відбувається, я хотів би в основному "заглянути" всередині об'єктів Python, щоб побачити, як вони галочують - як їхні методи та властивості.

Так що скажіть, у мене є об’єкт Python, що мені потрібно, щоб роздрукувати його вміст? Це навіть можливо?

Відповіді:


352

Python має сильний набір особливостей самоаналізу.

Погляньте на такі вбудовані функції :

type()і dir()особливо корисні для огляду типу об'єкта та його набору атрибутів відповідно.


25
Не знав, що термін "самоаналіз". Це чудова допомога! Як і всі функції, які ви мені дали ... Дякую!
littlejim84

2
властивість, класметод і статичний метод не пов'язані з самоаналізм. Усі ці методи створюють спеціальні типи об'єктів, які можна використовувати для визначення класів із особливою поведінкою, але не допомагають при огляді цих класів чи конструкцій.
SingleNegationElimination

Відповідь від @Brian нижче показує, як ви також можете переглянути вихідний код різних об’єктів python зсередини python. Це те, що я спочатку шукав, і я впевнений, що не буду один. (Можливо, варто включити в цю відповідь посилання на його відповідь, оскільки це найбільш прийнято.)
michaelavila

Це як вбудований "IntelliSense" для python. Я це люблю.
Бруно Бієрі

7
я думаю, що це погана відповідь. замість того, щоб давати нам рішення, він просто дає нам усе, що стосується цього, у документації
Ішан Срівастава

176

object.__dict__


12
vars(object)зроблено для цього.
liberforce

6
Насправді from pprint import pprint; pprint(vars(object))дав мені дуже гарний погляд на вміст мого об’єкта. Спасибі @liberforce
Н. Макс

найкращий спосіб побачити об’єкт та його вміст у рядку
Пітер Краус

Це прекрасний спосіб побачити об’єкти, які реалізують будь-які способи представлення, або такі об’єкти, як googleapiclient.errors.HttpError, який, коли ви їх роздруковуєте, напевно надрукує недостатню кількість інформації, дякую @ mtasic85
Феліпе Вальдес

65

Спочатку прочитайте джерело.

По-друге, використовуйте dir()функцію.


92
Я скасував би це наказ.
байєр

5
Джерело є більш інформативним, ніж dir (), і краще розвивати звичку.
S.Lott

14
Дозволю собі не погодитися. dir () просто набагато швидше, і в 99% випадків давайте дізнаємось, що вам потрібно в поєднанні з help ().
байєр

7
Я згоден, як правило, з непотрібним. Багато часу буде достатньо простого дзвінка на dir (), що допоможе вам врятувати проблеми перегляду вихідного коду.
Саша Чедігов

3
Інколи огляд об’єктів під час виконання може бути корисним, але читання джерел - ні. Наприклад, клас httplib.py та їх методи :).
Денис Барменков

61

Я здивований, поки ніхто не згадав про допомогу!

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

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

foo()
    foo!

Довідка дозволяє прочитати docstring та отримати уявлення про те, якими атрибутами може бути клас, що дуже корисно.


Потім ви використовуєте інші згадані тут методи. Але якщо докстринг доступний, врахуйте його канон.
Едвард Фолк

Я не впевнений, чи python оновлював цю функцію за останні кілька років, але "help (name_name_name)" забезпечує повний огляд у високоструктурованому форматі. Це хранитель. Дякую.
Брайан Кугельман

27

Якщо це для дослідження, щоб побачити, що відбувається, я рекомендую подивитися на IPython . Це додає різні ярлики для отримання документації на об'єкти, властивостей і навіть вихідного коду. Наприклад, додавання "?" функції дасть допомогу для об'єкта (фактично, ярлик для "help (obj)", коли використовується два? 's ("func?? ") буде відображено вихідний код, якщо він доступний.

Також є маса додаткових зручностей, таких як заповнення вкладок, досить друк результатів, історія результатів тощо, що робить його дуже зручним для такого роду дослідницьких програмувань.

Для більш програмного використання інтроспекції, основні вбудовані команди люблять dir(), vars(), і getattrт.д. буде корисно, але це добре стоїть вашого часу , щоб перевірити інспектувати модуль. Щоб отримати джерело функції, використовуйте, inspect.getsourceнаприклад, " " застосувавши його до себе:

>>> 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 також часто корисний, якщо ви маєте справу з обгортанням або маніпулюванням функціями, оскільки він дасть імена та значення за замовчуванням параметрів функції.


17

Якщо вас зацікавив графічний інтерфейс, погляньте на objbrowser . Для введення об'єкта під ним використовується модуль перевірки зі стандартної бібліотеки Python.

objbrowserscreenshot


9

Ви можете перерахувати атрибути об'єкта з dir () в оболонці:

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

Звичайно, є і модуль перевірки: 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
Це добре працює в python 3, якщо ви просто додаєте паролі навколо відбитків.
КонстантинК

8

Спробуйте 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)

Вихід:

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

7

Інші вже згадували вбудований dir (), який звучить як те, що ви шукаєте, але ось ще одна непогана порада. Багато бібліотек, включаючи більшість стандартних бібліотек, поширюються у вихідному вигляді. Це означає, що ви можете легко читати вихідний код безпосередньо. Хитрість полягає в тому, щоб знайти його; наприклад:

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

Файл * .pyc компілюється, тож видаліть проміжний 'c' та відкрийте некомпільований * .py файл у вашому улюбленому редакторі чи переглядачі файлів:

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

Я вважаю це надзвичайно корисним для виявлення речей, на зразок яких винятки зібрано із заданого API. Цей вид деталей рідко є добре задокументованим у світі Python.


7

Хоча pprintце вже згадувалося іншими, я хотів би додати деякий контекст.

Модуль pprint забезпечує можливість «симпатичного друку» довільних структур даних Python у формі, яка може бути використана як вхід до інтерпретатора. Якщо форматовані структури включають об'єкти, які не є основними типами Python, представлення може бути не завантажуваним. Це може бути так, якщо включені такі об'єкти, як файли, сокети, класи або екземпляри, а також багато інших вбудованих об'єктів, які не можуть бути представлені константами Python.

pprint Можливо, користуються великим попитом розробники з фоном PHP, які шукають альтернативу var_dump() .

Об'єкти з атрибутом dict можна красиво скинути за допомогою pprint()змішаного з vars(), який повертає __dict__атрибут для модуля, класу, екземпляра тощо:

from pprint import pprint
pprint(vars(your_object))

Отже, не потрібно петлі .

Для скидання всіх змінних, що містяться у глобальній чи локальній області, просто використовуйте:

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

locals()показує змінні, визначені у функції.
Також корисно отримати доступ до функцій з відповідним ім'ям як рядкового ключа, серед інших звичаїв :

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

Аналогічно, використовуючи dir() для перегляду вміст модуля або атрибути об'єкта.

А ще є більше.


4

Якщо ви хочете подивитися на параметри та методи, як зазначали інші, ви можете цілком використовувати pprintабоdir()

Якщо ви хочете побачити фактичне значення вмісту, ви можете зробити це

object.__dict__


4

Два чудові інструменти для перевірки коду:

  1. IPython . Термінал python, який дозволяє перевірити, використовуючи завершення вкладки.

  2. Затемнення за допомогою плагіна PyDev . Він має чудовий налагоджувач, який дозволяє зламати на заданому місці та оглянути об’єкти, переглядаючи всі змінні як дерево. Ви навіть можете використовувати вбудований термінал, щоб спробувати код на цьому місці або введіть об’єкт і натисніть '.' щоб він дав вам підказки для коду.

введіть тут опис зображення




3

Якщо вам цікаво переглянути вихідний код функції, що відповідає об'єкту myobj, ви можете ввести iPythonабо Jupyter Notebook:

myobj??


2
import pprint

pprint.pprint(obj.__dict__)

або

pprint.pprint(vars(obj))

Хоча цей код може відповісти на питання, надаючи додатковий контекст щодо того, як та / або чому він вирішує проблему, покращить довгострокове значення відповіді.
Олександр

1

Якщо ви хочете заглянути всередину живого об’єкта, то inspectмодуль python - це хороша відповідь. Загалом, він працює для отримання вихідного коду функцій, визначених у вихідному файлі десь на диску. Якщо ви хочете отримати джерело живих функцій та лямбда, які були визначені в інтерпретаторі, ви можете скористатися dill.source.getsourceз dill. Він також може отримати код для методів та функцій, пов'язаних або незв'язаних класів, визначених у curries ... однак, ви не зможете скласти цей код без коду об'єкта, що додається.

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

Крім того, якщо ви хочете заглянути все в список і словники, ви можете використовувати pprint ()


0

Уже є багато хороших підказок, але найкоротший і найпростіший (не обов’язково найкращий) ще належить згадати:

object?

-3

Спробуйте скористатися:

print(object.stringify())
  • де objectім'я змінної об'єкта, який ви намагаєтесь перевірити.

Це виводить добре відформатований та вкладений вихід, який показує всю ієрархію клавіш і значень в об'єкті.

ПРИМІТКА. Це працює в python3. Не впевнений, чи працює він у попередніх версіях

ОНОВЛЕННЯ: Це працює не на всіх типах об'єктів. Якщо ви зіткнулися з одним із цих типів (наприклад, об'єктом запиту), скористайтеся одним із наведених нижче варіантів:

  • dir(object())

або

import pprint тоді: pprint.pprint(object.__dict__)


1
Не працює над об’єктом "Запити" "Об'єкт" Запит "не має атрибута" Стримати ""
AlxVallejo
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.