#!/usr/bin/env python # coding: utf-8 # # import and from # Both **import** and **from** are statements, not compile-time declarations. # Thus, they can be nested in **if** like other statements. # # ## import # Assigning an entire module object to a single name # # ## from # - Copy specific names from one file to another. # - Assigning one or more names to objects of the same names in another module. # - No link from a name copied with **from** back to the original file. # - To really change a global name in another file, you must use **import**.(Not Recommaned design) # # ### from gotchas # - **from** only copies names from one module to another, it does not assign the module name itself # - **from** always load the whole file into memory. # There is no way to load part of a module file. # # ### from ... import * # Get copies of all names assigned at the top level of referenced module. # Note that only \* works. Other pattern matching rule won't work. # # In Python3, `from ... import *` can only be used at the top level of a module file, not within functions. # In Python2, it's allowed, but will issue a warning # # *Using `from ... import *` statement might hide variables that have the same names without notice* # Thus, the following design is recommanded. # ```python # from moduel import x, y, z # ``` # ## import and from Equivalence # # # ### from # ```python # from module import name1, name2 # ``` # # ### import # ```python # import module # name1 = module.name1 # name2 = module.name2 # ``` # ## import or from? # - Prefer **import** to **from** for simple modules # - Explicityly list the variables you want in **from** statements # - Limit `from module import *` to at most once per file # ## When import is required? # When you must use the same name defined in two different modules # # e.g. # ```python # # a.py and b.py exist in the same folder to be used as a sample # # # a.py # def func(): # print("This is a") # # # b.py # def func(): # print("This is b") # ``` # In[1]: # main.py from a import func from b import func func() # In[2]: # main2.py import a, b a.func() b.func() # Another way to solve this dilemma is using **as** statement # In[3]: from a import func as afunc from b import func as bfunc afunc() bfunc() # --- # # Module Namespace # Module namespaces can be accessed via the attribute `__dict__` or `dir(M)` # In[4]: import os for key, value in os.__dict__.items(): print(key) print("\t", value) # --- # # Reloading Modules # **reload** currently only works on modules written in Python. # In[5]: import os from imp import reload # Python3 reload(os) # - **reload** expects a module object. # Thus, the module you want to reload must first be successfully imported.. # # - **reload** change the module object in-place. # Thus, every reference to it will be updated by a reload # # - **from** won't be affected by **reload** # - **reload** should be used with **import** not **from** # # - **reload** applys to a single module, not recursive # # - **reload** returns the module object # # - **reload** also accepts a dotted path name # ## Why care about reloading modules? # - Dynamic customization. # - Useful in larger systems, especially when the cost of restarting the entire application. # e.g. game servers, systems that must connect to servers over a network