What’s the difference between the built-in
dir() function and
__dir__ dunder method in Python?
Python’s built-in function
dir(object) returns a list of the object’s attribute names and method names. The
dir() function is a wrapper around the
__dir__() method because it internally calls the object’s dunder method
object.__dir__(). But the two are different in functionality because
dir() performs additional tasks on the output of
object.__dir__() such as sorting the output list.
class Dummy: def __dir__(self): return ['bob', 'alice'] print(dir(Dummy())) # ['alice', 'bob']
Instead of the list
['bob', 'alice'] you obtain the sorted list
['alice', 'bob'] so some further processing must have been done by the
dir(Dummy()) method on the output of the
Dummy().__dir__() method call.
In addition to the sorting, the
dir() function also performs some housekeeping in case the
__dir__() method is not defined by the class. Here‘s the relevant part from the documentation explaining this relationship:
“If the object does not provide
__dir__(), the function tries its best to gather information from the object’s
__dict__ attribute, if defined, and from its type object.“
This means that the
dir() function is a higher-level function that does some advanced processing on top of the
__dir__() method, mainly for usability reasons. But if you have a large list of attribute names, you may not need to spend costly resources on sorting and should rely on the
object.__dir__() method instead in performance-sensitive environments.
In the following example, you see the default output of the
__dir__() methods in a more practical context:
class Car: def __init__(self, color, speed): self.color = color self.speed = speed def accelerate(self): self.speed += 10 def print_color(self): print(self.color) def print_speed(self): print(self.speed) porsche = Car('red', 110) print(dir(porsche)) print(porsche.__dir__())
Here’s the output of this code snippet:
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'accelerate', 'color', 'print_color', 'print_speed', 'speed'] ['color', 'speed', '__module__', '__init__', 'accelerate', 'print_color', 'print_speed', '__dict__', '__weakref__', '__doc__', '__repr__', '__hash__', '__str__', '__getattribute__', '__setattr__', '__delattr__', '__lt__', '__le__', '__eq__', '__ne__', '__gt__', '__ge__', '__new__', '__reduce_ex__', '__reduce__', '__subclasshook__', '__init_subclass__', '__format__', '__sizeof__', '__dir__', '__class__']
You can see that the default list of names is far greater—it contains all the names explicitly and implicitly defined for a given object. For example, the
speed attributes are there (explicitly defined), and the
__str__ and __lt__ functions are there too (implicitly defined for any custom object).
Let’s jump into some background on the dir() method—every advanced-level Python coder should get this! 🙂
If used without argument, Python’s built-in
dir() function returns the function and variable names defined in the local scope—the namespace of your current module. If used with an object argument,
dir(object) returns a list of attribute and method names defined in the object’s scope. Thus,
dir() returns all names in a given scope.
dir() -> names defined in the local scope/namespace. dir(object) -> names defined for the object.
|Arguments||The object for which the names should be returned.|
|Return Value||Returns all names defined in the namespace of the specified object. If no object argument is given, it returns the names defined in the local namespace of the module in which you run the code.|
You can also watch my explainer video to learn even more!
Where to Go From Here?
Enough theory. Let’s get some practice!
Coders get paid six figures and more because they can solve problems more effectively using machine intelligence and automation.
To become more successful in coding, solve more real problems for real people. That’s how you polish the skills you really need in practice. After all, what’s the use of learning theory that nobody ever needs?
You build high-value coding skills by working on practical coding projects!
Do you want to stop learning with toy projects and focus on practical code projects that earn you money and solve real problems for people?
🚀 If your answer is YES!, consider becoming a Python freelance developer! It’s the best way of approaching the task of improving your Python skills—even if you are a complete beginner.
If you just want to learn about the freelancing opportunity, feel free to watch my free webinar “How to Build Your High-Income Skill Python” and learn how I grew my coding business online and how you can, too—from the comfort of your own home.
While working as a researcher in distributed systems, Dr. Christian Mayer found his love for teaching computer science students.
To help students reach higher levels of Python success, he founded the programming education website Finxter.com. He’s author of the popular programming book Python One-Liners (NoStarch 2020), coauthor of the Coffee Break Python series of self-published books, computer science enthusiast, freelancer, and owner of one of the top 10 largest Python blogs worldwide.
His passions are writing, reading, and coding. But his greatest passion is to serve aspiring coders through Finxter and help them to boost their skills. You can join his free email academy here.