{ "cells": [ { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "# Module Design\n", "- Minimize Coupling: Avoid Global Variables\n", "- Maximize Cohesion: One Purpose\n", " \n", "## Data Hiding\n", "There is no way to prevent a client from changing names inside a module \n", "In Python, data hiding is a convention, not a constraint.\n", "\n", "### `_x` and `__all__`\n", "- Name with a single underscore (`_x`)\n", " - What not to be copied\n", " - A client imports using **`from *`** will ignore these variables\n", " - It's **not private declaration**. You can still import them.\n", "- `__all__`\n", " - What to be copied, higher priority that `_x`\n", " - When this feature is used, **`from *`** will copy out only names listed in `__all__` list. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Enabling Future Language Features `__future__`\n", "```python\n", "from __future__ import featurename\n", "```" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "['absolute_import',\n", " 'all_feature_names',\n", " 'barry_as_FLUFL',\n", " 'division',\n", " 'generators',\n", " 'nested_scopes',\n", " 'print_function',\n", " 'unicode_literals',\n", " 'with_statement']" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import __future__\n", "\n", "[\n", " featurename\n", " for featurename in dir(__future__)\n", " if not featurename.startswith(\"_\") and featurename[0].islower()\n", "]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Although import from future is supported, there is no way to import from the past" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Mixed Usage Modes: `__name__` and `__main__`\n", "- If the file is being run as a top-level program, **`__name__`** is set to **`__main__`**. \n", "- If it's imported, **`__name__`** is set to the modules's name as known by its clients\n", "\n", "This **`__name__`** servers as usage mode flag" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "__main__\n" ] } ], "source": [ "if __name__ == \"__main__\":\n", " print(__name__)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# The as Extension for import and from\n", "\n", "## import as\n", "\n", "```python\n", "import modulename as name\n", "```\n", "\n", "is the same as\n", "\n", "```python\n", "import modulename\n", "name = modulename\n", "del modulename\n", "```\n", "\n", "\n", "\n", "\n", "## from import as\n", "```python\n", "from module1 import utility as util1\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Import Module by Name String\n", "Original import cannot import a module by name string \n", "\n", "The following two way can do so\n", "- `__import__`\n", " - It's is generally intended for customizing import operations by reassignment in the built-in scope\n", "- `importlib.import_module`\n", " - The optional second argument can give the package the anchor point for resolving relative imports\n", "\n", "They returns the module object, so assign it to a name to keep it" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "['F_OK',\n", " 'MutableMapping',\n", " 'O_APPEND',\n", " 'O_BINARY',\n", " 'O_CREAT',\n", " 'O_EXCL',\n", " 'O_NOINHERIT',\n", " 'O_RANDOM',\n", " 'O_RDONLY',\n", " 'O_RDWR',\n", " 'O_SEQUENTIAL',\n", " 'O_SHORT_LIVED',\n", " 'O_TEMPORARY',\n", " 'O_TEXT',\n", " 'O_TRUNC',\n", " 'O_WRONLY',\n", " 'P_DETACH',\n", " 'P_NOWAIT',\n", " 'P_NOWAITO',\n", " 'P_OVERLAY',\n", " 'P_WAIT',\n", " 'R_OK',\n", " 'SEEK_CUR',\n", " 'SEEK_END',\n", " 'SEEK_SET',\n", " 'TMP_MAX',\n", " 'W_OK',\n", " 'X_OK',\n", " '_Environ',\n", " '__all__',\n", " '__builtins__',\n", " '__cached__',\n", " '__doc__',\n", " '__file__',\n", " '__loader__',\n", " '__name__',\n", " '__package__',\n", " '__spec__',\n", " '_execvpe',\n", " '_exists',\n", " '_exit',\n", " '_get_exports_list',\n", " '_putenv',\n", " '_unsetenv',\n", " '_wrap_close',\n", " 'abort',\n", " 'access',\n", " 'altsep',\n", " 'chdir',\n", " 'chmod',\n", " 'close',\n", " 'closerange',\n", " 'cpu_count',\n", " 'curdir',\n", " 'defpath',\n", " 'device_encoding',\n", " 'devnull',\n", " 'dup',\n", " 'dup2',\n", " 'environ',\n", " 'errno',\n", " 'error',\n", " 'execl',\n", " 'execle',\n", " 'execlp',\n", " 'execlpe',\n", " 'execv',\n", " 'execve',\n", " 'execvp',\n", " 'execvpe',\n", " 'extsep',\n", " 'fdopen',\n", " 'fsdecode',\n", " 'fsencode',\n", " 'fstat',\n", " 'fsync',\n", " 'get_exec_path',\n", " 'get_handle_inheritable',\n", " 'get_inheritable',\n", " 'get_terminal_size',\n", " 'getcwd',\n", " 'getcwdb',\n", " 'getenv',\n", " 'getlogin',\n", " 'getpid',\n", " 'getppid',\n", " 'isatty',\n", " 'kill',\n", " 'linesep',\n", " 'link',\n", " 'listdir',\n", " 'lseek',\n", " 'lstat',\n", " 'makedirs',\n", " 'mkdir',\n", " 'name',\n", " 'open',\n", " 'pardir',\n", " 'path',\n", " 'pathsep',\n", " 'pipe',\n", " 'popen',\n", " 'putenv',\n", " 'read',\n", " 'readlink',\n", " 'remove',\n", " 'removedirs',\n", " 'rename',\n", " 'renames',\n", " 'replace',\n", " 'rmdir',\n", " 'sep',\n", " 'set_handle_inheritable',\n", " 'set_inheritable',\n", " 'spawnl',\n", " 'spawnle',\n", " 'spawnv',\n", " 'spawnve',\n", " 'st',\n", " 'startfile',\n", " 'stat',\n", " 'stat_float_times',\n", " 'stat_result',\n", " 'statvfs_result',\n", " 'strerror',\n", " 'supports_bytes_environ',\n", " 'supports_dir_fd',\n", " 'supports_effective_ids',\n", " 'supports_fd',\n", " 'supports_follow_symlinks',\n", " 'symlink',\n", " 'sys',\n", " 'system',\n", " 'terminal_size',\n", " 'times',\n", " 'times_result',\n", " 'umask',\n", " 'uname_result',\n", " 'unlink',\n", " 'urandom',\n", " 'utime',\n", " 'waitpid',\n", " 'walk',\n", " 'write']" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "module_name = \"os\"\n", "os = __import__(module_name)\n", "dir(os)" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "['__displayhook__',\n", " '__doc__',\n", " '__excepthook__',\n", " '__interactivehook__',\n", " '__loader__',\n", " '__name__',\n", " '__package__',\n", " '__spec__',\n", " '__stderr__',\n", " '__stdin__',\n", " '__stdout__',\n", " '_clear_type_cache',\n", " '_current_frames',\n", " '_debugmallocstats',\n", " '_getframe',\n", " '_home',\n", " '_mercurial',\n", " '_xoptions',\n", " 'api_version',\n", " 'argv',\n", " 'base_exec_prefix',\n", " 'base_prefix',\n", " 'builtin_module_names',\n", " 'byteorder',\n", " 'call_tracing',\n", " 'callstats',\n", " 'copyright',\n", " 'displayhook',\n", " 'dllhandle',\n", " 'dont_write_bytecode',\n", " 'exc_info',\n", " 'excepthook',\n", " 'exec_prefix',\n", " 'executable',\n", " 'exit',\n", " 'flags',\n", " 'float_info',\n", " 'float_repr_style',\n", " 'getallocatedblocks',\n", " 'getcheckinterval',\n", " 'getdefaultencoding',\n", " 'getfilesystemencoding',\n", " 'getprofile',\n", " 'getrecursionlimit',\n", " 'getrefcount',\n", " 'getsizeof',\n", " 'getswitchinterval',\n", " 'gettrace',\n", " 'getwindowsversion',\n", " 'hash_info',\n", " 'hexversion',\n", " 'implementation',\n", " 'int_info',\n", " 'intern',\n", " 'maxsize',\n", " 'maxunicode',\n", " 'meta_path',\n", " 'modules',\n", " 'path',\n", " 'path_hooks',\n", " 'path_importer_cache',\n", " 'platform',\n", " 'prefix',\n", " 'ps1',\n", " 'ps2',\n", " 'ps3',\n", " 'setcheckinterval',\n", " 'setprofile',\n", " 'setrecursionlimit',\n", " 'setswitchinterval',\n", " 'settrace',\n", " 'stderr',\n", " 'stdin',\n", " 'stdout',\n", " 'thread_info',\n", " 'version',\n", " 'version_info',\n", " 'warnoptions',\n", " 'winver']" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import importlib\n", "\n", "module_name = \"sys\"\n", "sys = importlib.import_module(module_name)\n", "dir(sys)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Transitive Module Reloads\n", "To achieve it, scanning modules' **`__dict__`** namespace and check each item's **type** to find nested modules to reload. \n", "It works only on **import**, not **from**. \n", "The transitive reloader relies on the fact that module reloads update module objects in place." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Module Gotchas\n", "## Statement Order Matters in Top-Level Code\n", "Don't mix def with top-level code. \n", "Put **def** at the top of the file and top-level code at bottom" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def func():\n", " print(x)\n", "\n", "\n", "x = 1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "When imported, the above module would cause an error." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## from Copies Names but Doesn't Link\n", "**from** is a name-copy operation, not a name aliasing.\n", "\n", "## `from *` Can Obscure the Meaning of Variables\n", "Again, avoiding using **`from *`** or at most once per file.\n", "\n", "## reload May Not Impact from Imports" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.4.3" } }, "nbformat": 4, "nbformat_minor": 0 }