-
Notifications
You must be signed in to change notification settings - Fork 5
Chapter 5: Modules and packages
A Python module, simply put, is a .py file. A module can contain any Python code we like. I created e.g.the Python program mCipher, which contain some encrypting/decrypting methods and can be imported. The module must be placed within PATH, best in the Lib directory.
->>> import mCipher as m
->>> m.vigenere("I have a cat","Python",1)
'XFTCSNRYM'
->>> m.vigenere('XFTCSNRYM',"Python",0)
'IHAVEACAT'
->>>
->>> import os
->>> os.listdir
<built-in function listdir>
->>> os.listdir()
['01-KfN1400010001-watermarked.tif', '01-KfN1400010001.tif', '01-KfN1400010001_watermark.jpg', '01-KfN1400010001_watermark.tif', '01-KfN14B02720001.txt', '01-KfN14B02720001.xml', '12345_zmena_pixelu.py', '2cervence']
->>> list(os.walk("."))
for root, dirs, files in os.walk("."):
path = root.split(os.sep)
print((len(path) - 1) * '***', os.path.basename(root))
for file in files:
print(len(path) * '---', file)
->>> import os,mCipher
->>> type(mCipher)
<class 'module'>
->>> from mCipher import vigenere, trans_cipher
->>> import mCipher
->>> dir(mCipher)
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'affine_cipher', 'attrgetter', 'caesar_cipher', 'getKey', 'itemgetter', 'm', 'makeVernamCypher', 'trans_cipher', 'vigenere']
->>> from mCipher import *
->>>
->>> from os.path import dirname as my_dirs
->>>
Here are a few import examples:
->>> import os
print(os.path.basename(filename)) # safe fully qualified access
->>> import os.path as path
print(path.basename(filename)) # risk of name collision with path
->>> from os import path
print(path.basename(filename)) # risk of name collision with path
->>> from os.path import basename
print(basename(filename)) # risk of name collision with basename
->>> from os.path import *
print(basename(filename)) # risk of many name collisions
- usr/lib - Linux
but it must be in path.
->>> import mCipher
->>> print(mCipher.__file__)
C:/JCU/IOS 655 Python a Bash/pokusy\mCipher.py
->>>
->>> import nonsense
Traceback (most recent call last):
File "<pyshell#80>", line 1, in <module>
import nonsense
ImportError: No module named 'nonsense'
->>>
When Python needs a module’s byte-code compiled code, it generates it automatically—this differs from, say, Java, where compiling to byte code must be done explicitly. 1.First Python looks for a file with the same name but with the extension .pyo — optimized byte-code compiled version of the module. If there is no .pyo file (or if it is older than the .py file, that is, if it is out of date),
- Python looks for a file with the extension .pyc—this is a nonoptimized byte-code compiled version of the module. If
Python finds an up-to-date byte-code compiled version of the module, it loads it;
- otherwise, Python loads the .py file and compiles a byte-code compiled version.
Either way, Python ends up with the module in memory in byte-code compiled form. If Python had to byte-compile the .py file, it saves a .pyc version (or .pyo if -O was specified on Python’scommand line, or is set in the PYTHONOPTIMIZE environment variable), providing the directory is writable. Saving the byte code can be avoided by using the -B command line option, or by setting the PYTHONDONTWRITEBYTECODE environment variable. When Python is installed, the standard library modules are usually byte-code compiled as part of the installation process.
Packages are namespaces which contain multiple packages and modules themselves. They are simply directories, but with a twist. Can be installed e.g. through pip or easy_install etc. Each package in Python is a directory which MUST contain a special file called __init__.py. This file can be empty, and it indicates that the directory it contains is a Python package, so it can be imported the same way a module can be imported. If we create a directory called marta, which marks the package name, we can then create a module inside that package called bar. We also must not forget to add the *__init__.py* file inside the marta directory.
A shallow copy creates a new object which stores the reference of the original elements.
So, a shallow copy doesn’t create a copy of nested objects, instead it just copies the reference of nested objects. This means, a copy process does not recurse or create copies of nested objects itself.
->>> import copy
->>>old_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
->>>new_list = copy.copy(old_list)
->>> print("Old list:", old_list)
->>> print("New list:", new_list)
->>> Old list: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
->>> New list: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
->>> old_list = [[1, 1, 1], [2, 2, 2], [3, 3, 3]]
->>> new_list = copy.copy(old_list)
#append - add to the end
->>> old_list.append([4, 4, 4])
->>> print("Old list:", old_list)
->>> print("New list:", new_list)
Old list: [[1, 1, 1], [2, 2, 2], [3, 3, 3], [4, 4, 4]]
New list: [[1, 1, 1], [2, 2, 2], [3, 3, 3]]
#Adding new nested object using Shallow copy
->>> old_list = [[1, 1, 1], [2, 2, 2], [3, 3, 3]]
->>> new_list = copy.copy(old_list)
->>> old_list[1][1] = 'AA'
->>> print("Old list:", old_list)
->>> print("New list:", new_list)
A deep copy creates a new object and recursively adds the copies of nested objects present in the original elements.
->>> import copy
->>> old_list = [[1, 1, 1], [2, 2, 2], [3, 3, 3]]
->>> new_list = copy.deepcopy(old_list)
->>> print("Old list:", old_list)
->>> print("New list:", new_list)
Old list: [[1, 1, 1], [2, 2, 2], [3, 3, 3]]
New list: [[1, 1, 1], [2, 2, 2], [3, 3, 3]]
# add nested data
->>> old_list = [[1, 1, 1], [2, 2, 2], [3, 3, 3]]
->>> new_list = copy.deepcopy(old_list)
->>> old_list[1][0] = 'BB'
->>> print("Old list:", old_list)
->>> print("New list:", new_list)
Old list: [[1, 1, 1], ['BB', 2, 2], [3, 3, 3]]
New list: [[1, 1, 1], [2, 2, 2], [3, 3, 3]]
# and see
->>> a
[2, 3, 4, 88, 9999]
->>> b=copy.copy(a)
->>> c=deepcopy(a)
->>> id(a)
140569946565704
->>> id(b)
140569921928520
->>> id(c)
140569947011400
->>> d=a
->>> id(d)
140569946565704
->>> a.append(123456)
->>> print(a,b,c,d)
[2, 3, 4, 88, 9999, 123456] [2, 3, 4, 88, 9999] [2, 3, 4, 88, 9999] [2, 3, 4, 88, 9999, 123456]
->>>
Link to Python documentation and basics tutorial - https://docs.python.org/3.10/tutorial/index.html