type
built-in function__class__
method# in repl
>>> i = 7
>>> type(i)
#=> <class 'int'>
>>> repr(int)
#=> "<class 'int'>"
>>> type(i) is int
#=> True
>>> type(type(i))
#=> <class 'type'>
>>> i.__class__
#=> <class 'int'>
>>> i.__class__.__class__
#=> <class 'type'>
>>> i.__class__.__class__.__class__
#=> <class 'type'>
>>> issubclass(type, object)
#=> True
>>> type(object)
#=> <class 'type'>
>>> isinstance(i, int)
#=> True
dir
: returns list of attribute names for instance
callable
: returns boolean indicating if passed arg can be invoked or called
# in repl
>>> i = 7
>>> dir(i)
#=> ['__abs__', '__add__', '__and__', ..., 'real', 'to_bytes']
>>> getattr(i, 'denominator')
#=> 1
>>> getattr(i, 'conjugate')
#=> <built-in method conjugate of int object at 0x100233160>
>>> callable(getattr(i, 'conjugate'))
#=> True
>>> hasattr(i, 'bit_length')
#=> True
>>> hasattr(i, 'index')
#=> False
globals()
: returns dictionary representing global namespace
actually, the returned dictionary is the global namespace
locals()
: returns dictionary representing local scope namespace
# in repl
>>> globals()
#=> {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__builtins__': <module 'builtins' (built-in)>}
>>> a = 42
>>> globals()
#=> {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'a': 42}
>>> globals()['tau'] = 6.283185
>>> tau
6.283185
>>> tau / 2
3.1415925
>>> locals()
#=> {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'a': 42, 'tau': 6.283185}
>>> def report_scope(arg):
... from pprint import pprint as pp
... x = 496
... pp(locals(), width=10)
...
>>> report_scope(42)
#=> {'arg': 42,
#=> 'pp': <function pprint at 0x10f9d9280>,
#=> 'x': 496}
>>>
>>> name = "Joe Bloggs"
>>> age = 28
>>> country = "New Zealand"
>>>
##### NOTE: not suggested for normal use but can be handy for debugging
>>> "{name} is {age} years old and is from {country}".format(**locals())
#=> 'Joe Bloggs is 28 years old and is from New Zealand'
>>>
inspect
moduleinspect
)# in repl
>>> import inspect
>>> import sorted_set # <- from example in Collections
>>>
>>> inspect.ismodule(sorted_set)
#=> True
>>>
>>> inspect.getmembers(sorted_set)
#=> [('Sequence', <class 'collections.abc.Sequence'>), ('Set', <class 'collections.abc.Set'>), ('SortedSet', <class 'sorted_set.SortedSet'>), ...]
>>>
>>> inspect.getmembers(sorted_set, inspect.isclass)
#=> [('Sequence', <class 'collections.abc.Sequence'>), ('Set', <class 'collections.abc.Set'>), ('SortedSet', <class 'sorted_set.SortedSet'>), ('chain', <class 'itertools.chain'>)]
### NOTE: 'chain' was included because the class is imported in the scope of the 'sorted_set' module
>>>
>>> inspect.getmembers(sorted_set.SortedSet, inspect.isfunction)
#=> [('__add__', <function SortedSet.__add__ at 0x101896b90>), ('__and__', <function Set.__and__ at 0x1006dc9e0>), ('__contains__', <function SortedSet.__contains__ at 0x101896560>), ('__eq__', <function SortedSet.__eq__ at 0x101896830>), ('__ge__', <function Set.__ge__ at 0x1006dc7a0>), ('__getitem__', <function SortedSet.__getitem__ at 0x101896710>), ('__gt__', <function Set.__gt__ at 0x1006dc710>), ...]
>>>
>>> init_sig = inspect.signature(sorted_set.SortedSet.__init__)
>>> init_sig
#=> <inspect.Signature object at 0x1006e3c10>
>>> init_sig.parameters
#=> mappingproxy(OrderedDict([('self', <Parameter at 0x1018ad7e0 'self'>), ('items', <Parameter at 0x1018ad838 'items'>)]))
>>> repr(init_sig.parameters['items'].default)
#=> 'None'
>>>
>>> str(init_sig)
#=> '(self, items=None)'
>>>
>>> inspect.signature(abs)
#=> raises 'ValueError: no signature found for builtin function <built-in function abs>'
Goal: create function which, when passed single object, prints out a nicely formatted dump of object's attributes and methods (similar to getmembers()
but with more finesse)
import inspect
import itertools
import os
import reprlib
from sorted_set import SortedSet # <= from 'Collections' example
window_width, _ = os.get_terminal_size()
heading_separator = "=" * (window_width // 2)
def full_sig(method):
try:
return method.__name__ + inspect.signature(method)
except ValueError:
return method.__name__ + '(...)'
def brief_doc(obj):
doc = obj.__doc__
if doc is not None:
lines = doc.splitlines()
if len(lines) > 0:
return lines[0]
return ''
def print_table(rows_of_columns, *headers):
num_columns = len(rows_of_columns[0])
num_headers = len(headers)
if len(headers) != num_columns:
raise TypeError("Expected {} header arguments, "
"got {}".format(num_columns, num_headers))
rows_of_columns_with_header = itertools.chain([headers], rows_of_columns)
columns_of_rows = list(zip(*rows_of_columns_with_header))
column_widths = [max(map(len, column)) for column in columns_of_rows]
column_specs = ('{{:{w}}}'.format(w=width) for width in column_widths)
format_spec = ' '.join(column_specs)
print(format_spec.format(*headers))
rules = ('-' * width for width in column_widths)
print(format_spec.format(*rules))
for row in rows_of_columns:
print(format_spec.format(*row))
print('\n\n')
def dump(obj):
print("Type")
print(heading_separator)
print(type(obj), end='\n\n')
print("Documentation")
print(heading_separator)
print(inspect.getdoc(obj), end='\n\n')
print("Attributes")
print(heading_separator)
all_attr_names = SortedSet(dir(obj))
method_names = SortedSet(
filter(lambda attr_name: callable(getattr(obj, attr_name)), all_attr_names)
)
assert method_names <= all_attr_names # tests `issubset`
attr_names = all_attr_names - method_names # tests `difference`
# use `reprlib.repr` to trim down values in intelligent way
attr_names_and_values = [(name, reprlib.repr(getattr(obj, name)))
for name in attr_names]
print_table(attr_names_and_values, "Name", "value")
print("Methods")
print(heading_separator)
methods = (getattr(obj, method_name) for method_name in method_names)
method_names_and_doc = [(full_sig(method), brief_doc(method))
for method in methods]
print_table(method_names_and_doc, "Name", "Description")