ExampleEdit & Run
#Use the dir function

def func():
   a = 2
   b = 3
   print(dir())

func()
Output:
['a', 'b'] [Finished in 0.01595995099999925s]

The dir() function is used to find out a list of names that are defined or associated with a given namespace or object. By names we mean variable names, function names, class names, modules etc.

Syntax:
dir(obj = None)

Calling the function without  any argument will return a list containing all the names available in the local namespace i.e all the functions defined, all the imported modules, all the variable names, class names, etc.

Example with global namespace:

ExampleEdit & Run
dir()
a = 7
b = 'Hello'
def my_func():
    pass

print( dir() )#after defining some variables and functions

import math, re
print( dir() )#after importing some modules
Output:
['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__'] ['__annotations__', '__builtins__', '__doc__, '__loader__', '__name__', '__package__', '__spec__', 'a', 'b', 'my_func'] ['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'a', 'b', 'math', 'my_func', 're']

Example with local namespace:

ExampleEdit & Run
def func():
   a = 7
   b = 10
   message = 'Hello, World!'
   print( dir() )

func()
Output:
['a', 'b', 'message'] [Finished in 0.013201309999999467s]

When called with an argument, the dir() function returns name associated with the object/.namespace. The argument can literally be any Python object such as a module, a function, a string, etc.

ExampleEdit & Run

with module 

import math
print( dir( math ) )
Output:
['__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'cbrt', 'ceil', 'comb', 'copysign', 'cos', 'cosh', 'degrees', 'dist', 'e', 'erf', 'erfc', 'exp', 'exp2', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', 'isinf', 'isnan', 'isqrt', 'lcm', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'modf', 'nan', 'nextafter', 'perm', 'pi', 'pow', 'prod', 'radians', 'remainder', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'tau', 'trunc', 'ulp'] [Finished in 0.014314470000002188s]

The function can especially be very useful in cases where we want to explore the structure of a module or an object. It can help us to quickly get an idea on the usage of a module or an object by seeing the methods, functions and attributes associated with the object. For example if you want to view all the methods that are available on strings, you simply pass the str class or a string object to the function as shown below. 

ExampleEdit & Run
print( dir(str) )
Output:
['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isascii', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'removeprefix', 'removesuffix', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill'] [Finished in 0.012784768000003055s]

As you can see, the returned values includes the dunder(double underscore) also known as the magic methods. The dunder methods have special uses, for example some of them are used in the implementation of the built-in function e.g __len__() for the len() function. These methods are not typically meant to be used by end users directly as they are usually not part of the public interface. We can use the built-in filter() function to remove them from the returned values so that we can remain with the public methods.

ExampleEdit & Run
print( list(filter(lambda x: not x.startswith('__'), dir(str))) , '\n')

print( list(filter(lambda x: not x.startswith('__'), dir(list))) , '\n')

print( list(filter(lambda x: not x.startswith('__'), dir(int))) , '\n')

import re
print( list(filter(lambda x: not x.startswith('__'), dir(re))) )
Output:
['capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isascii', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'removeprefix', 'removesuffix', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill'] ['append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort'] ['as_integer_ratio', 'bit_count', 'bit_length', 'conjugate', 'denominator', 'from_bytes', 'imag', 'numerator', 'real', 'to_bytes'] ['A', 'ASCII', 'DEBUG', 'DOTALL', 'I', 'IGNORECASE', 'L', 'LOCALE', 'M', 'MULTILINE', 'Match', 'NOFLAG', 'Pattern', 'RegexFlag', 'S', 'Scanner', 'T', 'TEMPLATE', 'U', 'UNICODE', 'VERBOSE', 'X', '_MAXCACHE', '_cache', '_casefix', '_compile', '_compile_repl', '_compiler', '_constants', '_expand', '_parser', '_pickle', '_special_chars_map', '_subx', 'compile', 'copyreg', 'enum', 'error', 'escape', 'findall', 'finditer', 'fullmatch', 'functools', 'match', 'purge', 'search', 'split', 'sub', 'subn', 'template'] [Finished in 0.08743900000000338s]