Question

Python Equivalent of PHP var_dump(): repr, pprint, type, and vars

phppythondebugging

Question

When debugging PHP, var_dump() is useful because it displays a variable's type, value, and nested contents. What is the best Python equivalent for inspecting a variable, including its type, value, and an object's properties?

Short Answer

Python has no single built-in function that exactly matches PHP's var_dump(). In practice, combine type() to see a value's type, repr() for an unambiguous representation, pprint.pp() for readable nested collections, and vars() to inspect an object's stored attributes.

Concept

Python debugging output is usually built from small, focused tools rather than one all-purpose var_dump() function.

  • print(value) displays a human-friendly value using str(value).
  • repr(value) displays a developer-oriented representation that is often more precise.
  • type(value) tells you the object's class or type.
  • pprint.pp(value) formats nested lists and dictionaries across multiple lines.
  • vars(object) returns an object's attribute dictionary when the object has one.
  • dir(object) lists attribute names, including methods and inherited attributes.

This matters because Python values can be simple values, nested data structures, class instances, functions, and many other kinds of objects. The most useful inspection tool depends on what you need to learn: its value, type, stored state, or available behavior.

For interactive debugging, Python's built-in debugger (breakpoint()) is often more effective than adding many temporary print statements.

Mental Model

Think of a Python variable as a labeled box.

  • print() lets you look at the item in the box.
  • type() tells you what kind of item it is.
  • repr() gives you the item's precise catalog description, including details that normal display may hide.
  • pprint.pp() neatly lays out a box that contains many smaller boxes.
  • vars() opens an object's own storage compartment and shows the attributes it directly keeps.

PHP's var_dump() performs several of these inspections at once. Python commonly asks for each piece of information explicitly.

Take Quiz

Syntax and Examples

Use type() and repr() together for a compact var_dump()-style check:

value = {"name": "Ada", "scores": [98, 100]}

print("type:", type(value))
print("value:", repr(value))

Output:

type: <class 'dict'>
value: {'name': 'Ada', 'scores': [98, 100]}

For large or nested dictionaries and lists, use pprint.pp():

from pprint import pp

response = {
    "user": {"id": 7, "name": "Ada Lovelace"},
    "orders": [
        {"id": 101, "total": 29.99},
        {"id": 102, "total": 15.50},
    ],
}

pp(response)

pp() is available in Python 3.8 and later. On older versions, use pprint(response):

from pprint import pprint

pprint(response)

To inspect an instance's stored attributes:

class User:
    def __init__(self, name, active):
        self.name = name
        self.active = active

user = User("Ada", True)

print(vars(user))
# {'name': 'Ada', 'active': True}

A reusable helper can combine the most common checks:

from pprint import pformat

def dump(value):
    print(f"type: {type(value).__name__}")
    print(f"value: {pformat(value)}")

dump(["draft", {"published": False}])

Step by Step Execution

Consider this nested API-like value:

from pprint import pp

payload = {
    "ok": True,
    "items": [{"id": 1, "title": "Notebook"}],
}

print(type(payload).__name__)
pp(payload)
print(type(payload["items"]).__name__)

Execution trace:

  1. payload is assigned a dictionary containing a Boolean and a list.
  2. type(payload) produces the dictionary's type object.
  3. .__name__ extracts the short, readable name: dict.
  4. pp(payload) prints the entire nested dictionary with readable indentation when needed.
  5. payload["items"] accesses the value stored under the "items" key.
  6. That value is a list, so the final line prints list.

Expected output:

dict
{'ok': True, 'items': [{'id': 1, 'title': 'Notebook'}]}
list

Real World Use Cases

  • API debugging: Pretty-print a JSON response after it has been decoded into Python dictionaries and lists.
  • Form validation: Inspect submitted data and its types when a field unexpectedly arrives as a string, list, or None.
  • Data processing: Check the shape of a record before transforming a CSV row or database result.
  • Class debugging: Use vars(instance) to confirm whether an initializer stored the expected attributes.
  • Test failures: Use repr() to expose invisible differences, such as a trailing newline, extra spaces, or an empty string.
  • Interactive exploration: Use dir() to discover methods on an unfamiliar library object.
Take Quiz

Real Codebase Usage

In production code, temporary printing is useful during development, but logging and debuggers are usually better long-term choices.

Prefer repr() in diagnostic messages

repr() makes strings and special characters clear:

if token != expected_token:
    raise ValueError(f"Unexpected token: {token!r}")

The !r format conversion is equivalent to applying repr(token) inside an f-string.

Pretty-print structured debug data

from pprint import pformat
import logging

logger = logging.getLogger(__name__)

logger.debug("Request payload:\n%s", pformat(payload))

pformat() returns a string, which makes it suitable for logs. pp() prints immediately to standard output.

Use a breakpoint for deeper inspection

def calculate_total(items):
    breakpoint()
    return sum(item["price"] for item in items)

When execution pauses, you can inspect values interactively instead of repeatedly editing source code to add prints.

Inspect object state carefully

attributes = vars(user)

This works for many normal class instances. If it fails, the class may use __slots__ or may not expose a normal attribute dictionary. In that case, inspect known properties or use a debugger.

Common Mistakes

Assuming print() reveals everything

value = "hello\n"
print(value)

The newline is hard to spot because it changes the output layout. Use repr() instead:

print(repr(value))
# 'hello\n'

Calling vars() on every value

This may fail:

print(vars(42))

Integers do not have an instance attribute dictionary, so Python raises TypeError. Use type() and repr() for built-in scalar values.

Treating dir() as an object's stored data

print(dir(user))

dir() includes methods, inherited names, and implementation details. It is useful for discovering available attributes, not for a clean dump of instance state. Prefer vars(user) when you specifically want directly stored attributes.

Using __dict__ without checking

print(user.__dict__)

This is often equivalent to vars(user), but it is less flexible and can fail for objects without __dict__. Prefer vars(user).

Leaving sensitive debug output in logs

Do not log passwords, tokens, session cookies, or full personal records. Redact sensitive fields before printing or logging them.

Expecting pprint to reveal an object's internals

pprint makes representations readable; it does not automatically expose private internal state. Combine it with vars() when appropriate:

from pprint import pp

pp(vars(user))

Comparisons

ToolBest forWhat it showsImportant note
print(value)Quick, friendly outputstr(value)Can hide whitespace and formatting details.
repr(value)Precise debugging outputDeveloper representationOften shows quotes, escapes, and constructor-like output.
type(value)Identifying a value's typeA type object, such as <class 'list'>Use type(value).__name__ for just list.
pprint.pp(value)Nested lists and dictionariesReadable formatted representationPrimarily improves layout, not introspection.
vars(obj)Instance stateThe object's attribute dictionaryRaises TypeError if no attribute dictionary exists.
dir(obj)Discovering available namesAttributes and methodsIncludes inherited and implementation-related names.
breakpoint()Interactive investigationA debugging sessionLets you inspect many values without more print calls.

A practical closest match to basic var_dump() output is:

print(type(value).__name__)
print(repr(value))

For nested structures, replace the second line with pp(value).

Take Quiz

Cheat Sheet

# Value shown for people
print(value)

# Precise developer representation
print(repr(value))
print(f"{value!r}")

# Type
print(type(value))
print(type(value).__name__)

# Readable nested collections (Python 3.8+)
from pprint import pp
pp(value)

# Turn pretty output into a string, useful for logging
from pprint import pformat
text = pformat(value)

# Directly stored attributes of many class instances
print(vars(obj))

# Names available on an object, including methods
print(dir(obj))

# Pause execution and inspect interactively
breakpoint()

Quick rules:

  • Use repr() when exact text matters.
  • Use pp() for deeply nested dictionaries and lists.
  • Use vars() for an object's own attributes, not for integers, strings, or every possible object.
  • Use dir() to discover names, not as a clean state dump.
  • Remove temporary debug output or replace it with appropriately configured logging.

FAQ

Is there a direct Python equivalent to PHP var_dump()?

No single built-in function exactly matches it. The usual combination is type(value) plus repr(value), with pprint.pp(value) for nested data.

What is the difference between print() and repr() in Python?

print() uses a readable string form. repr() aims for an unambiguous developer representation, often exposing quotes, escape sequences, and precise values.

How do I pretty-print a dictionary in Python?

Use from pprint import pp followed by pp(my_dict). For older Python versions, use pprint(my_dict).

How can I print all attributes of a Python object?

For many class instances, use vars(obj). It returns the object's stored attribute dictionary. Use dir(obj) if you also need to discover methods and inherited attributes.

Why does vars() raise TypeError?

The object may not have an attribute dictionary. Built-in values such as int and some classes using __slots__ do not provide one.

Should I use print statements or a debugger?

Use prints for quick checks. Use breakpoint() or an IDE debugger when you need to inspect several values, step through execution, or examine a complex problem.

How do I include a useful value representation in an error message?

Use !r in an f-string:

raise ValueError(f"Invalid value: {value!r}")
Take Quiz

Mini Project

Description

Build a small debugging helper for a simulated API response. It will display a label, the value's type, and a readable representation. This mirrors the most useful parts of PHP's var_dump() while using normal Python tools.

Goal

Create a debug_dump() function that makes nested Python values easy to inspect during development.

Requirements

Create a function named debug_dump(value, label="value").

Print the label and the short type name.

Pretty-print the supplied value so nested data remains readable.

Call the function with a nested dictionary representing an API response.

Call the function once more with a string containing a newline.

Take Quiz

Keep learning

Related questions

View more