vars()

The direct pointer to __dict__ — instance-only attributes, declaration order, live view.

Built-in functionPython 1.0+Live demo
Common call
attrs = vars(obj)
Returns
a dict — LIVE view of __dict__
Replaces
`obj.__dict__` — the same result, just less punctuation
Watch out
the result is LIVE — mutating it mutates the object; not all objects have __dict__
vars([object])
dict

Demo

Live evaluation
Try:
Inputs
kindstrmodule / class / instance
Output
vars('module')
'{\'__name__\': \'sample\', \'greet\': <function greet>, \'VERSION\': \'1.0\'}'

The demo picks a category (module / class / instance) and shows what vars() would return for a representative object. Modules have __dict__ containing their names. User classes have __dict__ containing methods and class attributes. Instances have __dict__ containing per-instance attributes. Built-in types like str do NOT have __dict__ and raise TypeError.

Parameters

NameTypeRequiredDescription
objectAnynoAn object with a __dict__ attribute (most user classes, modules, and instances). Without an argument, returns locals(). Built-in types (int, list, str, ...) do NOT have __dict__ and raise TypeError.

Return value

dictThe __dict__ attribute of the given object. Without an argument, returns the local scope (like locals()). With an object: returns its __dict__ — the instance-specific writable attribute namespace. Not all objects have __dict__ (e.g. built-in types like int, list, str).

Common patterns

Inspect an instance&apos;s data
Quick way to see all instance attributes without printing methods.
print(vars(user))
# {"name": "Alice", "age": 30}
Serialize a simple dataclass
vars gives you the field dict directly.
import json
json.dumps(vars(obj))
Compare instance state
Two instances have equal state when their vars are equal.
vars(a) == vars(b)
Mutate through vars
The returned dict is LIVE — assigning through it changes the object.
vars(obj)["new_attr"] = value
# same as: obj.new_attr = value

Examples

1. Instance
class C: pass c = C() c.x = 1 vars(c)
Returns
{'x': 1}
2. Class
class C: x = 1 def m(self): pass vars(C)
Returns
{'x': 1, 'm': <function C.m>, ...}
3. Empty instance
class C: pass vars(C())
Returns
{}
4. No argument
vars()
Returns
same as locals()
5. Built-in raises
vars(42)
Returns
TypeError: vars() argument must have __dict__ attribute
6. Live mutation
vars(obj)["y"] = 5 obj.y
Returns
5 # dict is LIVE

Pitfalls

1. Built-in immutable types have NO __dict__
int, float, str, tuple, and most other built-in types are implemented in C and lack the Python-level __dict__. Calling vars() on them raises TypeError.
Rejected
vars(42)
TypeError: vars() argument must have __dict__ attribute
Use dir instead
dir(42)
list of names on int
2. vars() vs dir() — very different
vars returns just the __dict__ (instance-only, writable attributes). dir walks the whole MRO (all attributes accessible via getattr, including inherited methods). They return different things almost always.
Assumed same
set(vars(obj)) == set(dir(obj))
False for almost any object
Different tools
vars(obj)   # just instance attrs
dir(obj)   # all accessible names
3. The returned dict is LIVE — mutations affect the object
vars does not copy — it returns the actual __dict__. Assigning through it modifies the object. Sometimes useful, sometimes surprising.
Snapshot lost
snapshot = vars(obj)
obj.x = 99
snapshot["x"]
99 # the snapshot updated too
Copy for a snapshot
snapshot = dict(vars(obj))
independent copy
4. Classes with __slots__ have no __dict__
__slots__ classes intentionally lack __dict__ for memory efficiency. Instances of such classes cannot be inspected with vars().
Slotted rejected
class Point:
    __slots__ = ("x", "y")

vars(Point())
TypeError: vars() argument must have __dict__ attribute
Use dir + getattr
{s: getattr(obj, s) for s in obj.__slots__}
equivalent dict

When to use

Use it
  • Inspecting instance state during debugging
  • Serializing simple &quot;data bag&quot; objects to JSON or repr
  • Iterating over an object&apos;s writable attributes
  • Building an equality check based on instance state
Reach for something else
  • Object might not have __dict__ → guard with hasattr(obj, "__dict__")
  • You want inherited methods too → dir(obj)
  • You want a snapshot → wrap in dict() to copy
  • __slots__ classes → attribute-by-attribute access

Notes

Complexity
O(1) — direct attribute access
Return
The live __dict__ mapping — same object each call
CPython impl
Python/bltinmodule.c :: builtin_vars — returns tp_dict or object.__dict__
Memory
No allocation — returns the existing dict
Thread-safe
Depends on whether the underlying dict is safe from concurrent mutation

FAQ

vars gives you the __dict__ — just the instance-specific writable attributes, in declaration order (Python 3.7+). dir walks the whole MRO to return every accessible name (including inherited methods), sorted alphabetically. Both are useful; they answer different questions.

History

1.0
vars() has been a builtin since Python 1.0.
3.7
Class __dict__ preserves declaration order (as an ordered dict was already since 3.6, guaranteed in 3.7).