Q&A
What is the type() function in Python?
Overview
type() sits at the heart of Python's object model. Everything in Python is an object, and every object has a type. type() lets you inspect that type - and, in its advanced form, construct types programmatically. Understanding it illuminates the fact that classes are themselves instances of type (which is the default metaclass).
graph TD
A["type()"] --> B[1 arg: type(obj) → the object's class]
A --> C[3 args: type(name, bases, dict) → a new class]
B --> D[Introspection: what is this?]
C --> E[Metaprogramming: build classes at runtime]
style A fill:#1e1b4b,color:#fff
Form 1: Inspecting an Object's Type
type(42) # <class 'int'>
type(3.14) # <class 'float'>
type("hello") # <class 'str'>
type([1, 2]) # <class 'list'>
type({"a": 1}) # <class 'dict'>
type(None) # <class 'NoneType'>
x = 10
print(type(x)) # <class 'int'>
print(type(x).__name__) # 'int' (just the name)
This is the most common use - checking what kind of object you have.
type() vs isinstance()
A crucial distinction for type checking:
type(x) == int # True only if x is EXACTLY int
isinstance(x, int) # True if x is int OR a subclass of int
isinstance() respects inheritance and is preferred for type checks:
class Animal: pass
class Dog(Animal): pass
d = Dog()
type(d) == Animal # False (exact type is Dog)
isinstance(d, Animal) # True (Dog IS-A Animal) ✓ usually what you want
Use isinstance() for "is this usable as an X?"; reserve type() == for when you need the exact type.
Form 2: Creating Classes Dynamically
With three arguments, type() builds a new class on the fly:
type(name, bases, namespace)
name- the class name (string).bases- tuple of base classes.namespace- dict of attributes/methods.
# These two are equivalent:
class Dog:
sound = "woof"
def speak(self):
return self.sound
Dog = type("Dog", (), {
"sound": "woof",
"speak": lambda self: self.sound,
})
d = Dog()
print(d.speak()) # woof
The class statement is essentially syntactic sugar over this type(...) call.
Classes Are Instances of type
This reveals Python's metaclass system:
type(42) # <class 'int'> - 42 is an instance of int
type(int) # <class 'type'> - int is an instance of type!
type(type) # <class 'type'> - type is an instance of itself
type is the default metaclass: the "class of classes." This underpins advanced metaprogramming (custom metaclasses, ORMs, frameworks that generate classes).
Practical Uses
- Debugging / introspection - quickly see what an object is.
- Conditional logic (sparingly) - branch on type, though duck typing /
isinstanceis usually better. - Dynamic class creation - frameworks, ORMs, plugin systems that build classes from configuration or schemas.
Why This Matters in Interviews
Python interviews use type() to probe the object model. Know both forms, the type() vs isinstance() distinction (and why isinstance is preferred - it honors inheritance), and the deep fact that classes are instances of type (the metaclass concept). The dynamic-class-creation form is a strong signal of metaprogramming awareness.
Common Pitfalls
- Using
type(x) == SomeClassfor type checks, missing subclasses - preferisinstance. - Comparing types with
isvs==confusingly (useisinstance). - Overusing explicit type checks instead of duck typing (the Pythonic default).
- Confusing
type()(the metaclass/inspector) withtyping(the static type-hint module).
References
- Python
type()docs: https://docs.python.org/3/library/functions.html#type - Python data model (metaclasses): https://docs.python.org/3/reference/datamodel.html