Finding Python
A few tips for manually discovering Python’s features.
When I took my first stab at learning Python, I was initially turned away. It wasn’t syntax or lack of documentation, but rather the sheer amount of unknowns that pop up, almost immediately.
In this article, I’ll walk you through some techniques I found useful, and show you how you can use them to dig into Python yourself.
Examples will appear as they would when typed into the Python shell.
Read the Docs
One of the best places I’ve found to look is Python’s official documentation (also available here for Python 3).
Here, you can find a pretty extensive rundown of all standard modules available in Python. If you’re wondering about the capabilities or syntax of core Python features, and don’t mind technical writing, you’ll likely find your answers.
I’ll reference the documentation quite a bit in this article.
__doc__
Every public function, class, and method in Python’s standard library will ship with documentation in the form of a docstring.
A particular entity’s docstring can be accessed via its __doc__
attribute:
>>> object.__doc__'The most base type'
Some docstrings will span multiple lines, so they may look better printed out:
>>> print(str.__doc__)str(object='') -> stringReturn a nice string representation of the object.
If the argument is a string, the return value is the same object.
Functions
There are a couple functions I’ve found especially useful when it comes to exploring from both the Python shell and while debugging files.
dir
dir
is an essential function to familiarise yourself with while you explore Python. It returns a list of attributes of whatever is passed to it. If it isn’t passed anything, it returns all attributes of the current scope.
Wondering what you can do with a particular object?
>>> cool_var = str()
>>> dir(cool_var)['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__getslice__', '__gt__', '__hash__', '__init__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '_formatter_field_name_split', '_formatter_parser', 'capitalize', 'center', 'count', 'decode', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'index', 'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
These are all things you could access using the dot .
operator on cool_var
:
>>> cool_var.isalnum<built-in method isalnum of str object at 0x109e0b508>
Ok, so cool_var
has a method
called isalnum
. Perhaps isalnum
has a docstring?
>>> print(cool_var.isalnum.__doc__)S.isalnum() -> boolReturn True if all characters in S are alphanumeric
and there is at least one character in S, False otherwise.
Well-documented code can be quite the dream.
type
The type
function will return the type of a given object.
Pondering the type of a variable?
>>> mystery = str()
>>> type(mystery)<type 'str'>
Note that <type 'str'>
here is the string representation of mystery
‘s type. str
is the actual type mystery
, as we defined it. So if you were to print(str)
, it would be reasonable to expect the same:
>>> print(str)<type 'str'>
type
also has practical use cases outside of exploration. For instance, if you wanted to do something special if something was a str
:
>>> if type(mystery) is str:
... print("Not such a mystery anymore, huh.")
...Not such a mystery anymore, huh.
Builtins
There is a set of classes, objects, and functions, among other things, that will always be there for you in Python. These go by the name builtins, attached to any scope as the module __builtins__
.
You can use the dir
function to list all properties of this module. These just so happen to be the builtins:
>>> dir(__builtins__)['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BufferError', 'BytesWarning', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'NameError', 'None', 'NotImplemented', 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'ReferenceError', 'RuntimeError', 'RuntimeWarning', 'StandardError', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'ZeroDivisionError', '__debug__', '__doc__', '__import__', '__name__', '__package__', 'abs', 'all', 'any', 'apply', 'basestring', 'bin', 'bool', 'buffer', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'cmp', 'coerce', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'execfile', 'exit', 'file', 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'intern', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'long', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'raw_input', 'reduce', 'reload', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'unichr', 'unicode', 'vars', 'xrange', 'zip']
As you can see, some things we use all the time in Python, like print
and len
, are included here.
To use these, it isn’t even necessary to prefix them with __builtins__
— you can just refer to them as they appear in the list. If you can see it here, be assured that you can use it anywhere you want, and it will always be there. No import necessary.
Imports
Imports seem like magic at first. You just add the line import coolstuff
, and all of a sudden, you have a bunch of cool stuff. Where do these packages come from? What other ones are available?
In a given context, modules available for import in will be present on what’s called the module search path. Basically, this is a list of folders containing Python scripts.
There are three places Python will look for modules by default:
- The directory of the running script
- Directories listed in the environment variable
PYTHONPATH
- Default directories specified by your particular Python installation
Directories included by these three sources are combined into the path
property or the sys
module, (sys.path
). sys.path
is a list containing all directories that the running instance of Python should search for modules.
You can actually take a peek yourself:
>>> import sys
>>> print(sys.path)['', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-arm-linux-gnueabihf', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/home/pi/.local/lib/python2.7/site-packages', '/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages']
Inside of these folders will be a bunch of .py
files, yours included (since your script's directory will be part of sys.path
). There may also be Python packages included — directories containing an __init__.py
file, often containing multiple modules, that are treated as a single module with the name of the directory.
When you import
something
, Python looks for a Python file (.py
), cache file (.pyc
) or package named something
in those directories. If it can't find something
, you'll get an ImportError
like this: ImportError: No module named something
.
__file__
Most modules will have a __file__
attribute containing the path of the actual module file:
>>> import os
>>> os.__file__'/usr/local/Cellar/python@2/2.7.16/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'
If you’re ever confused as to where a particular module is coming from, this could point you in the right direction.
That’s a Wrap
Figuring out all of the beautiful tools that Python offers can be tedious at times. I hope these techniques will bring greater ease.
Thanks for reading, and best of luck with your Python endeavours.