#Use the dir function

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

func()

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.

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:

dir()
//['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__']
a = 7
b = 'Hello'
def my_func():
    pass

dir()#after defining some variables and functions
//['__annotations__', '__builtins__', '__doc__, '__loader__', '__name__', '__package__', '__spec__', 'a', 'b', 'my_func']
import math, re
dir()#after importing some modules
//['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'a', 'b', 'math', 'my_func', 're']

Example with local namespace:

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

//['a', 'b', 'message']

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.

Example:

import math
dir(math)
//['__doc__', '__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']

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.

dir(str)
//['__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']

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.

list(filter(lambda x: not x.startswith('__'), dir(str)))
//['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']
list(filter(lambda x: not x.startswith('__'), dir(list)))
//['append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse',
//'sort']
list(filter(lambda x: not x.startswith('__'), dir(int)))
//['as_integer_ratio', 'bit_count', 'bit_length', 'conjugate', 'denominator', 'from_bytes', 'imag',
//'numerator', 'real', 'to_bytes']
import re
list(filter(lambda x: not x.startswith('__'), dir(re)))
//['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']