As powerful as Python is, it would be almost impossible to write meaningful code without importing certain modules.
Yes, handwritten code can sometimes replace information available in a module. For example, your code might contain the statement:
lower = 'abcdefghijklmnopqrstuvwxyz'
and your hand-written code is as good as:
lower = string.ascii_lowercase
In this situation you might decide that it's not necessary to import string.
But, what about a statement like:
This statement provides essential information about the most recent error which execution of your code has caused.
Only an expert could create hand-written code to replace this statement and an expert would not want to do so.
When so many powerful features are available in python's modules, it makes good sense to use them.
With appropriate modules imported, your code reflects your good knowledge of python and your willingness to
reap the benefits of the labor of others whose contribution to python makes our professional lives easier.
You're already familiar with some of python's modules: decimal, sys.
In this lesson we'll look first at module string and the basic syntax concerning the use of module
string.
The simplest way to use module string is to open python and import it.
$ python3.6
Python 3.6.3 (v3.6.3:2c5fed86e0, Oct 3 2017, 00:32:08)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import string
>>>
To see what you have imported:
>>> globals()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'string': <module 'string' from '/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/string.py'>}
>>> string
<module 'string' from '/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/string.py'>
>>>
This shows that module string has been imported and it's available, but it doesn't tell us much about string.
For more information about module string:
>>> dir (string)
['Formatter', 'Template', '_ChainMap', '_TemplateMetaclass', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_re', '_string', 'ascii_letters', 'ascii_lowercase', 'ascii_uppercase', 'capwords', 'digits', 'hexdigits', 'octdigits', 'printable', 'punctuation', 'whitespace']
>>>
for v in dir(string) :
print ('###########################')
print ( v )
print ( eval( 'string.'+v ),'\n' )
###########################
Formatter
<class 'string.Formatter'>
###########################
Template
<class 'string.Template'>
###########################
_ChainMap
<class 'collections.ChainMap'>
###########################
_TemplateMetaclass
<class 'string._TemplateMetaclass'>
###########################
__all__
['ascii_letters', 'ascii_lowercase', 'ascii_uppercase', 'capwords', 'digits', 'hexdigits', 'octdigits', 'printable', 'punctuation', 'whitespace', 'Formatter', 'Template']
###########################
__builtins__
**** Lengthy list of builtins. ****
###########################
__cached__
/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/__pycache__/string.cpython-36.pyc
###########################
__doc__
A collection of string constants.
Public module variables:
whitespace -- a string containing all ASCII whitespace
ascii_lowercase -- a string containing all ASCII lowercase letters
ascii_uppercase -- a string containing all ASCII uppercase letters
ascii_letters -- a string containing all ASCII letters
digits -- a string containing all ASCII decimal digits
hexdigits -- a string containing all ASCII hexadecimal digits
octdigits -- a string containing all ASCII octal digits
punctuation -- a string containing all ASCII punctuation characters
printable -- a string containing all ASCII characters considered printable
###########################
__file__
/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/string.py
###########################
__loader__
<_frozen_importlib_external.SourceFileLoader object at 0x10209ff98>
###########################
__name__
string
###########################
__package__
###########################
__spec__
ModuleSpec(name='string', loader=<_frozen_importlib_external.SourceFileLoader object at 0x10209ff98>, origin='/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/string.py')
###########################
_re
<module 're' from '/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/re.py'>
###########################
_string
<module '_string' (built-in)>
###########################
ascii_letters
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
###########################
ascii_lowercase
abcdefghijklmnopqrstuvwxyz
###########################
ascii_uppercase
ABCDEFGHIJKLMNOPQRSTUVWXYZ
###########################
capwords
<function capwords at 0x1020a02f0>
###########################
digits
0123456789
###########################
hexdigits
0123456789abcdefABCDEF
###########################
octdigits
01234567
###########################
printable
0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
^M^K^L
###########################
punctuation
!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
###########################
whitespace
^M^K^L
Now that you know what's in module string, you can access the contents of string by name:
>>> string.__file__
'/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/string.py'
>>> string.__spec__
ModuleSpec(name='string', loader=<_frozen_importlib_external.SourceFileLoader object at 0x1018accc0>, origin='/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/string.py')
>>> string.digits
'0123456789'
>>>
|
For more information about the contents of string, change syntax slightly and try again:
$ python3.6
Python 3.6.3 (v3.6.3:2c5fed86e0, Oct 3 2017, 00:32:08)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from string import *
>>> globals()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'ascii_letters': 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', 'ascii_lowercase': 'abcdefghijklmnopqrstuvwxyz', 'ascii_uppercase': 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'capwords': <function capwords at 0x100786ae8>, 'digits': '0123456789', 'hexdigits': '0123456789abcdefABCDEF', 'octdigits': '01234567', 'printable': '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c', 'punctuation': '!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~', 'whitespace': ' \t\n\r\x0b\x0c', 'Formatter': <class 'string.Formatter'>, 'Template': <class 'string.Template'>}
>>>
With a little formatting we see:
'ascii_letters': 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
'ascii_lowercase': 'abcdefghijklmnopqrstuvwxyz',
'ascii_uppercase': 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
'capwords': <function capwords at 0x100786ae8>,
'digits': '0123456789',
'hexdigits': '0123456789abcdefABCDEF',
'octdigits': '01234567',
'printable': '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c',
'punctuation': '!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~',
'whitespace': ' \t\n\r\x0b\x0c',
'Formatter': <class 'string.Formatter'>,
'Template': <class 'string.Template'>}
The values in the left hand column above are keys of dictionary globals() and they are always strings.
In the right hand column are the values associated with the keys of the left hand.
As you can see, the values may or may not be strings.
Because globals() is a dictionary, it may be accessed like a dictionary:
>>> [ v for v in globals() if '__' not in v ]
['ascii_letters', 'ascii_lowercase', 'ascii_uppercase', 'capwords', 'digits', 'hexdigits', 'octdigits', 'printable', 'punctuation', 'whitespace', 'Formatter', 'Template']
# These values are the same as string.__all__ .
>>> globals()['digits']
'0123456789'
>>> globals()['ascii_uppercase']
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
>>>
The one name not seen in globals() is string.
>>> string
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'string' is not defined
>>>
>>> 'string' in globals()
False
>>>
The contents of string are now available:
>>> ascii_uppercase
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
>>> punctuation
'!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'
>>> whitespace
' \t\n\r\x0b\x0c'
>>> whitespace == ' \t\n\r\v\f'
True
>>>
Experiment with the contents of string:
>>> capwords('the authOrizEd biogRAPHY of tHomas jeFferSON')
'The Authorized Biography Of Thomas Jefferson'
>>>
>>> printable == digits + ascii_lowercase + ascii_uppercase + punctuation + whitespace
True
>>>
>>> dir(string._re)
['A', 'ASCII', 'DEBUG', 'DOTALL', 'I', 'IGNORECASE', 'L', 'LOCALE', 'M', 'MULTILINE', 'RegexFlag', 'S', 'Scanner', 'T', 'TEMPLATE', 'U', 'UNICODE', 'VERBOSE', 'X', '_MAXCACHE', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '__version__', '_alphanum_bytes', '_alphanum_str', '_cache', '_compile', '_compile_repl', '_expand', '_locale', '_pattern_type', '_pickle', '_subx', 'compile', 'copyreg', 'enum', 'error', 'escape', 'findall', 'finditer', 'fullmatch', 'functools', 'match', 'purge', 'search', 'split', 'sre_compile', 'sre_parse', 'sub', 'subn', 'template']
>>> import re
>>>
>>> dir(re)
['A', 'ASCII', 'DEBUG', 'DOTALL', 'I', 'IGNORECASE', 'L', 'LOCALE', 'M', 'MULTILINE', 'RegexFlag', 'S', 'Scanner', 'T', 'TEMPLATE', 'U', 'UNICODE', 'VERBOSE', 'X', '_MAXCACHE', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '__version__', '_alphanum_bytes', '_alphanum_str', '_cache', '_compile', '_compile_repl', '_expand', '_locale', '_pattern_type', '_pickle', '_subx', 'compile', 'copyreg', 'enum', 'error', 'escape', 'findall', 'finditer', 'fullmatch', 'functools', 'match', 'purge', 'search', 'split', 'sre_compile', 'sre_parse', 'sub', 'subn', 'template']
>>>
>>> re == string._re
True
>>>
Note:
While the statement import * is convenient, Python's Documentation states:
In most cases Python programmers do not use this facility since it introduces an unknown set of names into the interpreter, possibly hiding some things you have already defined.
.... in general the practice of importing * from a module or package is frowned upon, since it often causes poorly readable code. However, it is okay to use it to save typing in interactive sessions.
|
|
>>> whitespace = 'Hello, world!' ; whitespace
'Hello, world!'
>>>
>>> whitespace = ' \t\n\r\x0b\x0c' ; whitespace
' \t\n\r\x0b\x0c'
>>>
>>> whitespace = 'Hello, world!' ; whitespace
'Hello, world!'
>>>
>>> from string import whitespace ; whitespace
' \t\n\r\x0b\x0c'
>>>
|
After you become familiar with the contents of module string, you may decide to import only the module
and use the syntax that requires the name of the module:
$ python3.6
Python 3.6.3 (v3.6.3:2c5fed86e0, Oct 3 2017, 00:32:08)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import string
>>>
>>> whitespace
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'whitespace' is not defined
>>> string.whitespace
' \t\n\r\x0b\x0c'
>>>
>>> punctuation
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'punctuation' is not defined
>>> string.punctuation
'!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'
>>>
You can change the contents of module string, but this not recommended. In extreme cases, you may have to quit() python and start again.
|
|
In this case we will be working with module decimal. If this module is new to you, spend some time looking at
module decimal as if it were module string above.
In the present working directory create a Python source file, for example, myDec.py . This will become module
myDec.
# file myDec.py
import decimal
# Handy abbreviations:
D = decimal.Decimal
getC = decimal.getcontext()
T = decimal.DecimalTuple
# User-written function:
def doit(v1) :
return D(v1) + D(5)
Invoke Python in interactive mode:
$ python3.6
Python 3.6.3 (v3.6.3:2c5fed86e0, Oct 3 2017, 00:32:08)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>> from myDec import *
>>> globals()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>,
'decimal': <module 'decimal' from '/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/decimal.py'>,
'D': <class 'decimal.Decimal'>,
'getC': Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999, capitals=1, clamp=0, flags=[], traps=[InvalidOperation, DivisionByZero, Overflow]),
'T': <class 'decimal.DecimalTuple'>,
'doit': <function doit at 0x1018a1950>}
>>>
>>> decimal # Loaded from module myDec.
<module 'decimal' from '/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/decimal.py'>
>>>
>>> dir (decimal)
['BasicContext', 'Clamped', 'Context', 'ConversionSyntax', 'Decimal', 'DecimalException', 'DecimalTuple', 'DefaultContext', 'DivisionByZero', 'DivisionImpossible', 'DivisionUndefined', 'ExtendedContext', 'FloatOperation', 'HAVE_THREADS', 'Inexact', 'InvalidContext', 'InvalidOperation', 'MAX_EMAX', 'MAX_PREC', 'MIN_EMIN', 'MIN_ETINY', 'Overflow', 'ROUND_05UP', 'ROUND_CEILING', 'ROUND_DOWN', 'ROUND_FLOOR', 'ROUND_HALF_DOWN', 'ROUND_HALF_EVEN', 'ROUND_HALF_UP', 'ROUND_UP', 'Rounded', 'Subnormal', 'Underflow', '__builtins__', '__cached__', '__doc__', '__file__', '__libmpdec_version__', '__loader__', '__name__', '__package__', '__spec__', '__version__', 'getcontext', 'localcontext', 'setcontext']
>>>
>>> The various contexts:
>>>
>>> type(decimal.BasicContext)
<class 'decimal.Context'>
>>>
>>> type(decimal.DefaultContext)
<class 'decimal.Context'>
>>>
>>> type(decimal.ExtendedContext)
<class 'decimal.Context'>
>>>
>>> type(decimal.getcontext)
<class 'builtin_function_or_method'>
>>> type(decimal.getcontext())
<class 'decimal.Context'>
>>>
>>> T
<class 'decimal.DecimalTuple'>
>>> D
<class 'decimal.Decimal'>
>>> doit
<function doit at 0x1018a1950>
>>>
>>> getC
Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999, capitals=1, clamp=0, flags=[], traps=[InvalidOperation, DivisionByZero, Overflow])
>>>
>>> doit(7)
Decimal('12')
>>>
>>> getC.prec=31
>>> getC
Context(prec=31, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999, capitals=1, clamp=0, flags=[], traps=[InvalidOperation, DivisionByZero, Overflow]) # prec was changed to 31.
>>>
>>> getC.prec=28
>>> D(1234567890123456789012345678901234567890)+0
Decimal('1.234567890123456789012345679E+39') # Precision of 28.
>>>
>>> getC.prec=10
>>> D(1234567890123456789012345678901234567890)+0
Decimal('1.234567890E+39') # precision of 10
>>>
>>> getC
Context(prec=10, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999, capitals=1, clamp=0, flags=[Inexact, Rounded], traps=[InvalidOperation, DivisionByZero, Overflow]) # Precision of 10.
>>>
>>> T(1,(3,4,5,6),-3)
DecimalTuple(sign=1, digits=(3, 4, 5, 6), exponent=-3)
>>> T(1,(3,4,5,6),-3).sign
1
>>> T(1,(3,4,5,6),-3).digits
(3, 4, 5, 6)
>>> T(1,(3,4,5,6),-3).exponent
-3
>>>
>>> D(T(1,(3,4,5,6),-3))
Decimal('-3.456')
Let your file myDec.py be:
import decimal
# If module decimal was previously loaded, this statement is ignored.
# If module decimal was not previously loaded, this statement is executed.
# Same for 'import sys' below.
import sys
# Handy abbreviations:
getC = decimal.getcontext()
T = decimal.DecimalTuple
# User-written function:
def D (v1) :
'''
This function converts value v1 to decimal object.
If there is an error in conversion, this function
attempts to avoid introducing another error in the
'except' clause by ensuring that module 'sys' is
available. It was loaded above.
'''
if isinstance (v1, decimal.Decimal) : return v1
error = output = ''
try : output = decimal.Decimal(str(v1))
except : error = sys.exc_info()[:2]
if error :
print ('myDec.D: error converting', str(v1)[:80], 'to Decimal:')
print (' ', error)
return None
return output
Invoke Python in interactive mode:
$ python3.6
Python 3.6.3 (v3.6.3:2c5fed86e0, Oct 3 2017, 00:32:08)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>> from myDec import *
>>>
>>> dir()
['D', 'T', '__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'decimal', 'getC', 'sys']
>>>
>>> sorted(dir()) == sorted([ v for v in globals() ])
True
>>> v1 = Decimal(6)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'Decimal' is not defined
>>> decimal.Decimal(6)
Decimal('6')
>>>
>>> D(6)
Decimal('6')
>>> type(D(6))
<class 'decimal.Decimal'>
>>> D(1.23)
Decimal('1.23')
>>> decimal.Decimal(1.23)
>>> Decimal('1.229999999999999982236431605997495353221893310546875')
>>>
>>> D(4.).as_tuple()
DecimalTuple(sign=0, digits=(4, 0), exponent=-1)
>>> D(4.).as_tuple().digits
(4, 0)
>>>
>>> D(49.).sqrt()
Decimal('7.0')
>>>
>>> D(3+4j)
myDec.D: error converting (3+4j) to Decimal:
(<class 'decimal.InvalidOperation'>, InvalidOperation([<class 'decimal.ConversionSyntax'>],))
>>>
|
|
This example (on UNIX) shows how to access global variables across modules.
Create 2 files test1.py and test.py.
# test1.py
def test1_ReceiveGlobals(dict1) :
for v in dict1 :
globals()[v] = dict1[v]
def test1_SendGlobals() :
return globals()
|
# test.py
from test1 import *
def set_globals() :
t1 = (
('test1_23',67),
('test1_24',83),
('common_1',17), # This name is repeated below against "global".
('common_2',23), # This name is repeated below against "global".
)
dict1 = dict( t1 )
test1_ReceiveGlobals(dict1)
global test_46,test_47
global common_1,common_2 # These 2 names exist in "dict1" above.
test_46 = 79
test_47 = 41
common_1 = 'φιλοσοφοῦμεν ἄνευ μαλακίας.' # This name exists in "dict1" above.
common_2 = 'These are the times that ....' # This name exists in "dict1" above.
def print_globals() :
print ()
print ('globals():')
for v in [v for v in globals() if '__' not in v]:
print ('globals[{}] = {}'.format(v, globals()[v]))
test1_globals = test1_SendGlobals()
print ()
print ('test1_globals:')
for v in [v for v in test1_globals if '__' not in v]:
print ('test1_globals[{}] = {}'.format(v, test1_globals[v]))
print_globals()
set_globals()
print_globals()
|
Invoke test.py:
$ python3.6 ./test.py >sout 2>serr ; echo $? ; wc sout serr
0
28 107 1224 sout
0 0 0 serr
28 107 1224 total
# file sout
globals():
globals[test1_ReceiveGlobals] = <function test1_ReceiveGlobals at 0x1022451e0> # Common to both.
globals[test1_SendGlobals] = <function test1_SendGlobals at 0x102245268> # Common to both.
globals[set_globals] = <function set_globals at 0x100561e18> # Unique to test.
globals[print_globals] = <function print_globals at 0x1022452f0> # Unique to test.
test1_globals:
test1_globals[test1_ReceiveGlobals] = <function test1_ReceiveGlobals at 0x1022451e0> # Common to both.
test1_globals[test1_SendGlobals] = <function test1_SendGlobals at 0x102245268> # Common to both.
globals():
globals[test1_ReceiveGlobals] = <function test1_ReceiveGlobals at 0x1022451e0> # Common to both.
globals[test1_SendGlobals] = <function test1_SendGlobals at 0x102245268> # Common to both.
globals[set_globals] = <function set_globals at 0x100561e18> # Unique to test.
globals[print_globals] = <function print_globals at 0x1022452f0> # Unique to test.
globals[test_46] = 79 # Unique to test.
globals[test_47] = 41 # Unique to test.
globals[common_1] = φιλοσοφοῦμεν ἄνευ μαλακίας. # Name exists in test1 below. Value is different.
globals[common_2] = These are the times that .... # Name exists in test1 below. Value is different.
test1_globals:
test1_globals[test1_ReceiveGlobals] = <function test1_ReceiveGlobals at 0x1022451e0> # Common to both.
test1_globals[test1_SendGlobals] = <function test1_SendGlobals at 0x102245268> # Common to both.
test1_globals[test1_23] = 67 # Unique to test1.
test1_globals[test1_24] = 83 # Unique to test1.
test1_globals[common_1] = 17 # Name exists in test above. Value is different.
test1_globals[common_2] = 23 # Name exists in test above. Value is different.
|
File test5.py:
def test5_doit() :
main5_doit()
|
File main5.py:
import test5
def main5_doit() :
print ('in main5_doit()')
test5.test5_doit()
|
Invoke main5.py:
$ python3.6 ./main5.py
Traceback (most recent call last):
File "./main5.py", line 6, in <module>
test5.test5_doit()
File "...../test5.py", line 2, in test5_doit
main5_doit()
NameError: name 'main5_doit' is not defined
$
|
Add one line of code to file main5.py:
import test5
def main5_doit() :
print ('in main5_doit()')
test5.main5_doit = main5_doit
test5.test5_doit()
|
Invoke main5.py:
$ python3.6 ./main5.py
in main5_doit()
$
|
Function main5_doit() in main module was invoked by code in imported module test5.
|
|
|