11. ਮਿਆਰੀ ਲਾਇਬ੍ਰੇਰੀ ਦਾ ਸੰਖੇਪ ਜਾਣ-ਪਛਾਣ --- ਭਾਗ II¶
ਇਹ ਦੂਜਾ ਜਾਣ-ਪਛਾਣ ਦੌਰਾ ਹੋਰ ਉੱਨਤ ਮੌਡਿਊਲਾਂ ਨੂੰ ਕਵਰ ਕਰਦਾ ਹੈ ਜੋ ਪੇਸ਼ੇਵਰ ਪ੍ਰੋਗਰਾਮਿੰਗ ਦੀਆਂ ਲੋੜਾਂ ਨੂੰ ਸਮਰਥਨ ਦਿੰਦੇ ਹਨ। ਇਹ ਮੌਡਿਊਲ ਛੋਟੀਆਂ ਸਕ੍ਰਿਪਟਾਂ ਵਿੱਚ ਕਦਾਚਿਤ ਹੀ ਵਰਤੇ ਜਾਂਦੇ ਹਨ।
11.1. ਆਉਟਪੁੱਟ ਫਾਰਮੈਟਿੰਗ¶
reprlib ਮੌਡਿਊਲ repr() ਦਾ ਇੱਕ ਐਸਾ ਸੰਸਕਰਣ ਪ੍ਰਦਾਨ ਕਰਦਾ ਹੈ ਜੋ ਵੱਡੇ ਜਾਂ ਬਹੁਤ ਡੂੰਘੇ ਤੌਰ 'ਤੇ ਨੇਸਟ ਕੀਤੇ ਕੰਟੇਨਰਾਂ ਦੇ ਸੰਖੇਪ ਪ੍ਰਦਰਸ਼ਨ ਲਈ ਅਨੁਕੂਲਿਤ ਕੀਤਾ ਗਿਆ ਹੈ:
>>> import reprlib
>>> reprlib.repr(set('supercalifragilisticexpialidocious'))
"{'a', 'c', 'd', 'e', 'f', 'g', ...}"
pprint ਮੌਡਿਊਲ ਬਿਲਟ-ਇਨ ਅਤੇ ਵਰਤੋਂਕਾਰ ਦੁਆਰਾ ਪਰਿਭਾਸ਼ਿਤ ਵਸਤੂਆਂ ਨੂੰ ਦੁਭਾਸ਼ੀਏ ਦੁਆਰਾ ਪੜ੍ਹਨਯੋਗ ਢੰਗ ਨਾਲ ਪ੍ਰਿੰਟ ਕਰਨ ਲਈ ਹੋਰ ਉੱਨਤ ਨਿਯੰਤਰਣ ਪ੍ਰਦਾਨ ਕਰਦਾ ਹੈ। ਜਦੋਂ ਨਤੀਜਾ ਇੱਕ ਲਾਈਨ ਤੋਂ ਲੰਮਾ ਹੋਵੇ, ਤਾਂ "pretty printer" ਡਾਟਾ ਸੰਰਚਨਾ ਨੂੰ ਹੋਰ ਸਪਸ਼ਟ ਤੌਰ 'ਤੇ ਦਿਖਾਉਣ ਲਈ ਲਾਈਨ ਬ੍ਰੇਕ ਅਤੇ ਇੰਡੈਂਟੇਸ਼ਨ ਸ਼ਾਮਲ ਕਰਦਾ ਹੈ:
>>> import pprint
>>> t = [[[['black', 'cyan'], 'white', ['green', 'red']], [['magenta',
... 'yellow'], 'blue']]]
...
>>> pprint.pprint(t, width=30)
[[[['black', 'cyan'],
'white',
['green', 'red']],
[['magenta', 'yellow'],
'blue']]]
textwrap ਮੌਡਿਊਲ ਪਾਠ ਦੇ ਪੈਰਾਗ੍ਰਾਫਾਂ ਨੂੰ ਦਿੱਤੀ ਗਈ ਸਕ੍ਰੀਨ ਚੌੜਾਈ ਦੇ ਅਨੁਕੂਲ ਫਾਰਮੈਟ ਕਰਦਾ ਹੈ:
>>> import textwrap
>>> doc = """The wrap() method is just like fill() except that it returns
... a list of strings instead of one big string with newlines to separate
... the wrapped lines."""
...
>>> print(textwrap.fill(doc, width=40))
The wrap() method is just like fill()
except that it returns a list of strings
instead of one big string with newlines
to separate the wrapped lines.
locale ਮੌਡਿਊਲ ਸੱਭਿਆਚਾਰ-ਵਿਸ਼ੇਸ਼ ਡਾਟਾ ਫਾਰਮੈਟਾਂ ਦੇ ਡਾਟਾਬੇਸ ਤੱਕ ਪਹੁੰਚ ਪ੍ਰਦਾਨ ਕਰਦਾ ਹੈ। locale ਦੇ format ਫੰਕਸ਼ਨ ਦਾ grouping ਐਟ੍ਰਿਬਿਊਟ ਸਮੂਹ ਵਿਭਾਜਕਾਂ ਨਾਲ ਸੰਖਿਆਵਾਂ ਨੂੰ ਫਾਰਮੈਟ ਕਰਨ ਦਾ ਸਿੱਧਾ ਤਰੀਕਾ ਦਿੰਦਾ ਹੈ:
>>> import locale
>>> locale.setlocale(locale.LC_ALL, 'English_United States.1252')
'English_United States.1252'
>>> conv = locale.localeconv() # get a mapping of conventions
>>> x = 1234567.8
>>> locale.format_string("%d", x, grouping=True)
'1,234,567'
>>> locale.format_string("%s%.*f", (conv['currency_symbol'],
... conv['frac_digits'], x), grouping=True)
'$1,234,567.80'
11.2. ਟੈਂਪਲੇਟਿੰਗ¶
string ਮੌਡਿਊਲ ਵਿੱਚ ਇੱਕ ਬਹੁ-ਉਦੇਸ਼ੀ Template ਕਲਾਸ ਸ਼ਾਮਲ ਹੈ ਜਿਸਦਾ ਸਰਲ ਸਿੰਟੈਕਸ ਅੰਤਿਮ ਵਰਤੋਂਕਾਰਾਂ ਦੁਆਰਾ ਸੰਪਾਦਨ ਲਈ ਉਚਿਤ ਹੈ। ਇਸ ਨਾਲ ਵਰਤੋਂਕਾਰ ਆਪਣੀਆਂ ਐਪਲੀਕੇਸ਼ਨਾਂ ਨੂੰ ਸੋਧੇ ਬਿਨਾਂ ਉਹਨਾਂ ਨੂੰ ਅਨੁਕੂਲਿਤ ਕਰ ਸਕਦੇ ਹਨ।
ਇਹ ਫਾਰਮੈਟ ਵੈਧ Python ਪਛਾਣਕਰਤਾਵਾਂ (ਅੱਖਰ-ਅੰਕ ਅਤੇ ਅੰਡਰਸਕੋਰ) ਨਾਲ ਬਣੇ $ ਅਧਾਰਿਤ placeholder ਨਾਂ ਵਰਤਦਾ ਹੈ। placeholder ਨੂੰ braces ਵਿੱਚ ਰੱਖਣ ਨਾਲ ਉਸ ਤੋਂ ਬਾਅਦ ਹੋਰ ਅੱਖਰ-ਅੰਕੀ ਅੱਖਰ ਬਿਨਾਂ ਖਾਲੀ ਥਾਂ ਦੇ ਲਿਖੇ ਜਾ ਸਕਦੇ ਹਨ। $$ ਲਿਖਣ ਨਾਲ ਇੱਕ escaped $ ਬਣਦਾ ਹੈ:
>>> from string import Template
>>> t = Template('${village}folk send $$10 to $cause.')
>>> t.substitute(village='Nottingham', cause='the ditch fund')
'Nottinghamfolk send $10 to the ditch fund.'
substitute() ਵਿਧੀ ਉਸ ਵੇਲੇ KeyError ਉਤਪੰਨ ਕਰਦੀ ਹੈ ਜਦੋਂ ਕਿਸੇ placeholder ਲਈ ਡਿਕਸ਼ਨਰੀ ਜਾਂ keyword argument ਵਿੱਚ ਮੁੱਲ ਨਾ ਦਿੱਤਾ ਗਿਆ ਹੋਵੇ। mail-merge ਕਿਸਮ ਦੀਆਂ ਐਪਲੀਕੇਸ਼ਨਾਂ ਲਈ ਵਰਤੋਂਕਾਰ ਦੁਆਰਾ ਦਿੱਤਾ ਡਾਟਾ ਅਧੂਰਾ ਹੋ ਸਕਦਾ ਹੈ, ਇਸ ਲਈ safe_substitute() ਵਿਧੀ ਹੋਰ ਉਚਿਤ ਹੋ ਸਕਦੀ ਹੈ --- ਜੇ ਡਾਟਾ ਗੈਰਹਾਜ਼ਰ ਹੋਵੇ ਤਾਂ ਇਹ placeholder ਨੂੰ ਬਦਲੇ ਬਿਨਾਂ ਛੱਡ ਦਿੰਦੀ ਹੈ:
>>> t = Template('Return the $item to $owner.')
>>> d = dict(item='unladen swallow')
>>> t.substitute(d)
Traceback (most recent call last):
...
KeyError: 'owner'
>>> t.safe_substitute(d)
'Return the unladen swallow to $owner.'
Template ਦੀਆਂ ਉਪ-ਕਲਾਸਾਂ ਇੱਕ ਕਸਟਮ delimiter ਨਿਰਧਾਰਤ ਕਰ ਸਕਦੀਆਂ ਹਨ। ਉਦਾਹਰਨ ਵਜੋਂ, ਕਿਸੇ ਫੋਟੋ ਬ੍ਰਾਊਜ਼ਰ ਲਈ batch renaming utility ਮੌਜੂਦਾ ਤਾਰੀਖ, ਚਿੱਤਰ ਕ੍ਰਮ ਸੰਖਿਆ ਜਾਂ ਫਾਈਲ ਫਾਰਮੈਟ ਵਰਗੇ placeholder ਲਈ percent ਚਿੰਨ੍ਹ ਵਰਤ ਸਕਦੀ ਹੈ:
>>> import time, os.path
>>> photofiles = ['img_1074.jpg', 'img_1076.jpg', 'img_1077.jpg']
>>> class BatchRename(Template):
... delimiter = '%'
...
>>> fmt = input('Enter rename style (%d-date %n-seqnum %f-format): ')
Enter rename style (%d-date %n-seqnum %f-format): Ashley_%n%f
>>> t = BatchRename(fmt)
>>> date = time.strftime('%d%b%y')
>>> for i, filename in enumerate(photofiles):
... base, ext = os.path.splitext(filename)
... newname = t.substitute(d=date, n=i, f=ext)
... print('{0} --> {1}'.format(filename, newname))
img_1074.jpg --> Ashley_0.jpg
img_1076.jpg --> Ashley_1.jpg
img_1077.jpg --> Ashley_2.jpg
ਟੈਂਪਲੇਟਿੰਗ ਦਾ ਇੱਕ ਹੋਰ ਉਪਯੋਗ ਪ੍ਰੋਗਰਾਮ ਦੀ ਲਾਜਿਕ ਨੂੰ ਵੱਖ-ਵੱਖ ਆਉਟਪੁੱਟ ਫਾਰਮੈਟਾਂ ਦੇ ਵੇਰਵਿਆਂ ਤੋਂ ਅਲੱਗ ਕਰਨਾ ਹੈ। ਇਸ ਨਾਲ XML ਫਾਈਲਾਂ, ਸਧਾਰਣ ਪਾਠ ਰਿਪੋਰਟਾਂ ਅਤੇ HTML ਵੈੱਬ ਰਿਪੋਰਟਾਂ ਲਈ ਕਸਟਮ ਟੈਂਪਲੇਟ ਵਰਤਣਾ ਸੰਭਵ ਬਣਦਾ ਹੈ।
11.3. ਬਾਈਨਰੀ ਡਾਟਾ ਰਿਕਾਰਡ ਲੇਆਉਟ ਨਾਲ ਕੰਮ ਕਰਨਾ¶
struct ਮੌਡਿਊਲ variable-length ਬਾਈਨਰੀ ਰਿਕਾਰਡ ਫਾਰਮੈਟਾਂ ਨਾਲ ਕੰਮ ਕਰਨ ਲਈ pack() ਅਤੇ unpack() ਫੰਕਸ਼ਨ ਪ੍ਰਦਾਨ ਕਰਦਾ ਹੈ। ਹੇਠਾਂ ਦਿੱਤੀ ਉਦਾਹਰਨ ਦਿਖਾਉਂਦੀ ਹੈ ਕਿ zipfile ਮੌਡਿਊਲ ਦੀ ਵਰਤੋਂ ਬਿਨਾਂ ZIP ਫਾਈਲ ਦੇ header ਜਾਣਕਾਰੀ ਵਿੱਚ ਕਿਵੇਂ ਲੂਪ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ। Pack ਕੋਡ "H" ਅਤੇ "I" ਕ੍ਰਮਵਾਰ ਦੋ ਅਤੇ ਚਾਰ ਬਾਈਟ ਦੇ unsigned ਨੰਬਰ ਦਰਸਾਉਂਦੇ ਹਨ। "<" ਇਹ ਦਰਸਾਉਂਦਾ ਹੈ ਕਿ ਇਹ standard size ਅਤੇ little-endian byte order ਵਿੱਚ ਹਨ:
import struct
with open('myfile.zip', 'rb') as f:
data = f.read()
start = 0
for i in range(3): # show the first 3 file headers
start += 14
fields = struct.unpack('<IIIHH', data[start:start+16])
crc32, comp_size, uncomp_size, filenamesize, extra_size = fields
start += 16
filename = data[start:start+filenamesize]
start += filenamesize
extra = data[start:start+extra_size]
print(filename, hex(crc32), comp_size, uncomp_size)
start += extra_size + comp_size # skip to the next header
11.4. ਮਲਟੀ-ਥ੍ਰੈਡਿੰਗ¶
ਥ੍ਰੈਡਿੰਗ ਉਹ ਤਕਨੀਕ ਹੈ ਜਿਸ ਨਾਲ ਉਹਨਾਂ ਕੰਮਾਂ ਨੂੰ ਵੱਖ ਕੀਤਾ ਜਾਂਦਾ ਹੈ ਜੋ ਲੜੀਵਾਰ ਤੌਰ 'ਤੇ ਇੱਕ-ਦੂਜੇ 'ਤੇ ਨਿਰਭਰ ਨਹੀਂ ਹੁੰਦੇ। ਥ੍ਰੈਡਾਂ ਦੀ ਵਰਤੋਂ ਉਹਨਾਂ ਐਪਲੀਕੇਸ਼ਨਾਂ ਦੀ ਪ੍ਰਤੀਕਿਰਿਆਸ਼ੀਲਤਾ ਵਧਾਉਣ ਲਈ ਕੀਤੀ ਜਾ ਸਕਦੀ ਹੈ ਜੋ ਵਰਤੋਂਕਾਰ ਇਨਪੁੱਟ ਸਵੀਕਾਰ ਕਰਦੀਆਂ ਹਨ ਜਦੋਂ ਕਿ ਹੋਰ ਕੰਮ ਪਿਛੋਕੜ ਵਿੱਚ ਚੱਲ ਰਹੇ ਹੁੰਦੇ ਹਨ। ਇੱਕ ਹੋਰ ਸੰਬੰਧਿਤ ਵਰਤੋਂ I/O ਨੂੰ ਕਿਸੇ ਹੋਰ ਥ੍ਰੈਡ ਵਿੱਚ ਹੋ ਰਹੀਆਂ ਗਣਨਾਵਾਂ ਦੇ ਸਮਾਂਤਰ ਚਲਾਉਣਾ ਹੈ।
ਹੇਠਾਂ ਦਿੱਤਾ ਕੋਡ ਦਰਸਾਉਂਦਾ ਹੈ ਕਿ ਉੱਚ-ਪੱਧਰੀ threading ਮੌਡਿਊਲ ਕਿਵੇਂ ਪਿਛੋਕੜ ਵਿੱਚ ਕੰਮ ਚਲਾ ਸਕਦਾ ਹੈ ਜਦੋਂ ਕਿ ਮੁੱਖ ਪ੍ਰੋਗਰਾਮ ਚੱਲਦਾ ਰਹਿੰਦਾ ਹੈ:
import threading, zipfile
class AsyncZip(threading.Thread):
def __init__(self, infile, outfile):
super().__init__()
self.infile = infile
self.outfile = outfile
def run(self):
with zipfile.ZipFile(self.outfile, 'w', zipfile.ZIP_DEFLATED) as f:
f.write(self.infile)
print('Finished background zip of:', self.infile)
background = AsyncZip('mydata.txt', 'myarchive.zip')
background.start()
print('The main program continues to run in foreground.')
background.join() # Wait for the background task to finish
print('Main program waited until background was done.')
ਮਲਟੀ-ਥ੍ਰੈਡਡ ਐਪਲੀਕੇਸ਼ਨਾਂ ਦੀ ਮੁੱਖ ਚੁਣੌਤੀ ਉਹਨਾਂ ਥ੍ਰੈਡਾਂ ਦਾ ਸਮਨਵਯ ਕਰਨਾ ਹੈ ਜੋ ਡਾਟਾ ਜਾਂ ਹੋਰ ਸਰੋਤ ਸਾਂਝੇ ਕਰਦੇ ਹਨ। ਇਸ ਲਈ threading ਮੌਡਿਊਲ ਕਈ ਸਿੰਕ੍ਰੋਨਾਈਜ਼ੇਸ਼ਨ ਸਾਧਨ ਪ੍ਰਦਾਨ ਕਰਦਾ ਹੈ, ਜਿਵੇਂ locks, events, condition variables ਅਤੇ semaphores।
ਹਾਲਾਂਕਿ ਇਹ ਸਾਧਨ ਸ਼ਕਤੀਸ਼ਾਲੀ ਹਨ, ਪਰ ਛੋਟੀਆਂ ਡਿਜ਼ਾਇਨ ਗਲਤੀਆਂ ਵੀ ਅਜਿਹੀਆਂ ਸਮੱਸਿਆਵਾਂ ਪੈਦਾ ਕਰ ਸਕਦੀਆਂ ਹਨ ਜਿਨ੍ਹਾਂ ਨੂੰ ਦੁਬਾਰਾ ਪੈਦਾ ਕਰਨਾ ਮੁਸ਼ਕਲ ਹੁੰਦਾ ਹੈ। ਇਸ ਲਈ ਕੰਮਾਂ ਦੇ ਸਮਨਵਯ ਲਈ ਪਸੰਦੀਦਾ ਤਰੀਕਾ ਇਹ ਹੈ ਕਿ ਕਿਸੇ ਸਰੋਤ ਤੱਕ ਸਾਰੀ ਪਹੁੰਚ ਇੱਕ ਹੀ ਥ੍ਰੈਡ ਵਿੱਚ ਕੇਂਦਰਿਤ ਕੀਤੀ ਜਾਵੇ ਅਤੇ ਫਿਰ queue ਮੌਡਿਊਲ ਰਾਹੀਂ ਹੋਰ ਥ੍ਰੈਡਾਂ ਤੋਂ ਬੇਨਤੀਆਂ ਭੇਜੀਆਂ ਜਾਣ। Queue ਆਬਜੈਕਟ ਵਰਤਣ ਵਾਲੀਆਂ ਐਪਲੀਕੇਸ਼ਨਾਂ ਨੂੰ ਡਿਜ਼ਾਇਨ ਕਰਨਾ ਆਸਾਨ, ਵਧੇਰੇ ਪੜ੍ਹਨਯੋਗ ਅਤੇ ਜ਼ਿਆਦਾ ਭਰੋਸੇਯੋਗ ਹੁੰਦਾ ਹੈ।
11.5. ਲੌਗਿੰਗ¶
logging ਮੌਡਿਊਲ ਇੱਕ ਪੂਰੀ ਤਰ੍ਹਾਂ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਵਾਲਾ ਅਤੇ ਲਚਕੀਲਾ ਲੌਗਿੰਗ ਸਿਸਟਮ ਪ੍ਰਦਾਨ ਕਰਦਾ ਹੈ। ਸਭ ਤੋਂ ਸਰਲ ਰੂਪ ਵਿੱਚ, ਲੌਗ ਸੁਨੇਹੇ ਕਿਸੇ ਫਾਈਲ ਜਾਂ sys.stderr ਨੂੰ ਭੇਜੇ ਜਾਂਦੇ ਹਨ:
import logging
logging.debug('Debugging information')
logging.info('Informational message')
logging.warning('Warning:config file %s not found', 'server.conf')
logging.error('Error occurred')
logging.critical('Critical error -- shutting down')
ਇਸ ਨਾਲ ਹੇਠਾਂ ਦਿੱਤਾ ਆਉਟਪੁੱਟ ਪ੍ਰਾਪਤ ਹੁੰਦਾ ਹੈ:
WARNING:root:Warning:config file server.conf not found
ERROR:root:Error occurred
CRITICAL:root:Critical error -- shutting down
ਮੂਲ ਰੂਪ ਵਿੱਚ informational ਅਤੇ debugging ਸੁਨੇਹਿਆਂ ਨੂੰ ਦਬਾ ਦਿੱਤਾ ਜਾਂਦਾ ਹੈ ਅਤੇ ਆਉਟਪੁੱਟ standard error ਵੱਲ ਭੇਜਿਆ ਜਾਂਦਾ ਹੈ। ਹੋਰ ਵਿਕਲਪਾਂ ਵਿੱਚ ਸੁਨੇਹਿਆਂ ਨੂੰ email, datagram, socket ਜਾਂ HTTP Server ਰਾਹੀਂ ਭੇਜਣਾ ਸ਼ਾਮਲ ਹੈ। ਨਵੇਂ filters ਸੁਨੇਹੇ ਦੀ ਤਰਜੀਹ ਦੇ ਆਧਾਰ 'ਤੇ ਵੱਖ-ਵੱਖ routing ਚੁਣ ਸਕਦੇ ਹਨ: DEBUG, INFO, WARNING, ERROR ਅਤੇ CRITICAL।
ਲੌਗਿੰਗ ਸਿਸਟਮ ਨੂੰ ਸਿੱਧੇ Python ਤੋਂ ਸੰਰਚਿਤ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ ਜਾਂ ਐਪਲੀਕੇਸ਼ਨ ਵਿੱਚ ਤਬਦੀਲੀ ਕੀਤੇ ਬਿਨਾਂ ਕਸਟਮ ਲੌਗਿੰਗ ਲਈ ਵਰਤੋਂਕਾਰ ਦੁਆਰਾ ਸੰਪਾਦਨਯੋਗ ਸੰਰਚਨਾ ਫਾਈਲ ਤੋਂ ਲੋਡ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ।
11.6. ਕਮਜ਼ੋਰ ਰੈਫਰੈਂਸ¶
Python ਸਵੈਚਾਲਿਤ ਮੈਮੋਰੀ ਪ੍ਰਬੰਧਨ ਕਰਦਾ ਹੈ (ਜ਼ਿਆਦਾਤਰ ਆਬਜੈਕਟਾਂ ਲਈ reference counting ਅਤੇ ਚੱਕਰਾਂ ਨੂੰ ਖਤਮ ਕਰਨ ਲਈ garbage collection)। ਕਿਸੇ ਆਬਜੈਕਟ ਦਾ ਆਖਰੀ ਰੈਫਰੈਂਸ ਹਟਾਏ ਜਾਣ ਤੋਂ ਥੋੜ੍ਹੀ ਦੇਰ ਬਾਅਦ ਉਸਦੀ ਮੈਮੋਰੀ ਮੁਕਤ ਕਰ ਦਿੱਤੀ ਜਾਂਦੀ ਹੈ।
ਇਹ ਤਰੀਕਾ ਜ਼ਿਆਦਾਤਰ ਐਪਲੀਕੇਸ਼ਨਾਂ ਲਈ ਵਧੀਆ ਕੰਮ ਕਰਦਾ ਹੈ, ਪਰ ਕਈ ਵਾਰ ਆਬਜੈਕਟਾਂ ਨੂੰ ਕੇਵਲ ਉਸ ਸਮੇਂ ਤੱਕ ਟ੍ਰੈਕ ਕਰਨ ਦੀ ਲੋੜ ਹੁੰਦੀ ਹੈ ਜਦੋਂ ਤੱਕ ਉਹ ਕਿਸੇ ਹੋਰ ਵੱਲੋਂ ਵਰਤੇ ਜਾ ਰਹੇ ਹੋਣ। ਦੁੱਖ ਦੀ ਗੱਲ ਹੈ ਕਿ ਉਹਨਾਂ ਨੂੰ ਟ੍ਰੈਕ ਕਰਨਾ ਹੀ ਇੱਕ ਰੈਫਰੈਂਸ ਬਣਾਉਂਦਾ ਹੈ ਜੋ ਉਹਨਾਂ ਨੂੰ ਸਥਾਈ ਬਣਾ ਦਿੰਦਾ ਹੈ। weakref ਮੌਡਿਊਲ ਬਿਨਾਂ ਰੈਫਰੈਂਸ ਬਣਾਏ ਆਬਜੈਕਟਾਂ ਨੂੰ ਟ੍ਰੈਕ ਕਰਨ ਲਈ ਸਾਧਨ ਪ੍ਰਦਾਨ ਕਰਦਾ ਹੈ। ਜਦੋਂ ਆਬਜੈਕਟ ਦੀ ਲੋੜ ਨਹੀਂ ਰਹਿੰਦੀ, ਤਾਂ ਉਹ weakref ਟੇਬਲ ਤੋਂ ਆਪਣੇ ਆਪ ਹਟਾ ਦਿੱਤਾ ਜਾਂਦਾ ਹੈ ਅਤੇ weakref ਆਬਜੈਕਟ ਲਈ callback ਚਲਾਇਆ ਜਾਂਦਾ ਹੈ। ਆਮ ਵਰਤੋਂ ਵਿੱਚ ਅਜਿਹੇ ਆਬਜੈਕਟਾਂ ਦੀ caching ਸ਼ਾਮਲ ਹੈ ਜਿਨ੍ਹਾਂ ਨੂੰ ਬਣਾਉਣਾ ਮਹਿੰਗਾ ਹੁੰਦਾ ਹੈ:
>>> import weakref, gc
>>> class A:...
def __init__(self, value):...
self.value = value...
def __repr__(self):...
return str(self.value)
...
>>> a = A(10) # ਇੱਕ ਰੈਫਰੈਂਸ ਬਣਾਓ
>>> d = weakref.WeakValueDictionary()
>>> d['primary'] = a # ਇੱਕ ਰੈਫਰੈਂਸ ਨਹੀਂ ਬਣਾਉਂਦਾ
>>> d['primary'] # ਜੇਕਰ ਆਬਜੈਕਟ ਅਜੇ ਵੀ ਮੌਜੂਦ ਹੈ ਤਾਂ ਇਸਨੂੰ ਪ੍ਰਾਪਤ ਕਰੋ
10
>>> del a # ਇੱਕ ਰੈਫਰੈਂਸ ਹਟਾਓ
>>> gc.collect() # ਤੁਰੰਤ ਗਾਰਬੇਜ ਕਲੈਕਸ਼ਨ ਚਲਾਓ
0
>>> d['primary'] # ਐਂਟਰੀ ਆਪਣੇ ਆਪ ਹਟ ਗਈ ਸੀ
Traceback (most recent call last):
ਫਾਈਲ "<stdin>", ਲਾਈਨ 1, ਵਿੱਚ <module>
d['primary'] # ਐਂਟਰੀ ਆਪਣੇ ਆਪ ਹਟਾ ਦਿੱਤੀ ਗਈ ਸੀ
ਫਾਈਲ "C:/python315/lib/weakref.py", ਲਾਈਨ 46, ਵਿੱਚ __getitem__
o = self.data[key]()
KeyError: 'primary'
11.7. ਸੂਚੀਆਂ ਨਾਲ ਕੰਮ ਕਰਨ ਲਈ ਸਾਧਨ¶
ਡਾਟਾ ਸੰਰਚਨਾ ਦੀਆਂ ਬਹੁਤ ਸਾਰੀਆਂ ਲੋੜਾਂ built-in list ਕਿਸਮ ਨਾਲ ਪੂਰੀਆਂ ਕੀਤੀਆਂ ਜਾ ਸਕਦੀਆਂ ਹਨ। ਹਾਲਾਂਕਿ, ਕਈ ਵਾਰ ਵੱਖ-ਵੱਖ ਕਾਰਗੁਜ਼ਾਰੀ ਸਮਝੌਤਿਆਂ ਵਾਲੀਆਂ ਵਿਕਲਪਿਕ implementations ਦੀ ਲੋੜ ਹੁੰਦੀ ਹੈ।
array ਮੌਡਿਊਲ ਇੱਕ array ਆਬਜੈਕਟ ਪ੍ਰਦਾਨ ਕਰਦਾ ਹੈ ਜੋ list ਵਰਗਾ ਹੁੰਦਾ ਹੈ, ਪਰ ਇਹ ਸਿਰਫ਼ ਇੱਕੋ ਕਿਸਮ ਦਾ ਡਾਟਾ ਸਟੋਰ ਕਰਦਾ ਹੈ ਅਤੇ ਉਸਨੂੰ ਹੋਰ ਸੰਖੇਪ ਰੂਪ ਵਿੱਚ ਸੰਭਾਲਦਾ ਹੈ। ਹੇਠਾਂ ਦਿੱਤੀ ਉਦਾਹਰਨ ਵਿੱਚ ਸੰਖਿਆਵਾਂ ਦੀ ਇੱਕ array ਦਿਖਾਈ ਗਈ ਹੈ ਜੋ Python int ਆਬਜੈਕਟਾਂ ਦੀ ਆਮ list ਵਿੱਚ ਪ੍ਰਤੀ ਐਂਟਰੀ 16 bytes ਦੀ ਬਜਾਏ ਦੋ-byte unsigned binary numbers (typecode "H") ਦੇ ਰੂਪ ਵਿੱਚ ਸਟੋਰ ਕੀਤੀ ਗਈ ਹੈ:
>>> from array import array
>>> a = array('H', [4000, 10, 700, 22222])
>>> sum(a)
26932
>>> a[1:3]
array('H', [10, 700])
collections ਮੌਡਿਊਲ ਇੱਕ deque ਆਬਜੈਕਟ ਪ੍ਰਦਾਨ ਕਰਦਾ ਹੈ ਜੋ list ਵਰਗਾ ਹੁੰਦਾ ਹੈ, ਪਰ ਇਸ ਵਿੱਚ ਖੱਬੇ ਪਾਸੇ ਤੋਂ append ਅਤੇ pop ਕਾਰਵਾਈਆਂ ਤੇਜ਼ ਹੁੰਦੀਆਂ ਹਨ, ਜਦਕਿ ਵਿਚਕਾਰ lookup ਕੁਝ ਹੌਲੀ ਹੁੰਦੀ ਹੈ। ਇਹ ਆਬਜੈਕਟ queues ਅਤੇ breadth-first tree searches ਨੂੰ ਲਾਗੂ ਕਰਨ ਲਈ ਬਹੁਤ ਉਚਿਤ ਹਨ:
>>> from collections import deque
>>> d = deque(["task1", "task2", "task3"])
>>> d.append("task4")
>>> print("Handling", d.popleft())
Handling task1
unsearched = deque([starting_node])
def breadth_first_search(unsearched):
node = unsearched.popleft()
for m in gen_moves(node):
if is_goal(m):
return m
unsearched.append(m)
ਵਿਕਲਪਿਕ list implementations ਤੋਂ ਇਲਾਵਾ, ਲਾਇਬ੍ਰੇਰੀ ਹੋਰ ਸਾਧਨ ਵੀ ਪ੍ਰਦਾਨ ਕਰਦੀ ਹੈ, ਜਿਵੇਂ ਕਿ bisect ਮੌਡਿਊਲ ਜੋ sorted lists ਨਾਲ ਕੰਮ ਕਰਨ ਲਈ ਫੰਕਸ਼ਨ ਪ੍ਰਦਾਨ ਕਰਦਾ ਹੈ:
>>> import bisect
>>> scores = [(100, 'perl'), (200, 'tcl'), (400, 'lua'), (500, 'python')]
>>> bisect.insort(scores, (300, 'ruby'))
>>> scores
[(100, 'perl'), (200, 'tcl'), (300, 'ruby'), (400, 'lua'), (500, 'python')]
heapq ਮੌਡਿਊਲ ਆਮ lists ਉੱਤੇ ਆਧਾਰਿਤ heaps ਨੂੰ ਲਾਗੂ ਕਰਨ ਲਈ ਫੰਕਸ਼ਨ ਪ੍ਰਦਾਨ ਕਰਦਾ ਹੈ। ਸਭ ਤੋਂ ਛੋਟੀ ਮੁੱਲ ਵਾਲੀ ਐਂਟਰੀ ਹਮੇਸ਼ਾਂ ਸਥਾਨ zero ਉੱਤੇ ਰੱਖੀ ਜਾਂਦੀ ਹੈ। ਇਹ ਉਹਨਾਂ ਐਪਲੀਕੇਸ਼ਨਾਂ ਲਈ ਲਾਭਦਾਇਕ ਹੈ ਜੋ ਵਾਰ-ਵਾਰ ਸਭ ਤੋਂ ਛੋਟੇ ਤੱਤ ਤੱਕ ਪਹੁੰਚ ਕਰਦੀਆਂ ਹਨ ਪਰ ਪੂਰੀ list ਨੂੰ sort ਨਹੀਂ ਕਰਨਾ ਚਾਹੁੰਦੀਆਂ:
>>> from heapq import heapify, heappop, heappush
>>> data = [1, 3, 5, 7, 9, 2, 4, 6, 8, 0]
>>> heapify(data) # rearrange the list into heap order
>>> heappush(data, -5) # add a new entry
>>> [heappop(data) for i in range(3)] # fetch the three smallest entries
[-5, 0, 1]
11.8. ਦਸ਼ਮਲਵ ਫਲੋਟਿੰਗ-ਪੌਇੰਟ ਅੰਕਗਣਿਤ¶
decimal ਮੌਡਿਊਲ ਦਸ਼ਮਲਵ ਫਲੋਟਿੰਗ-ਪੌਇੰਟ ਅੰਕਗਣਿਤ ਲਈ Decimal ਡਾਟਾ-ਟਾਈਪ ਪ੍ਰਦਾਨ ਕਰਦਾ ਹੈ। ਬਾਈਨਰੀ ਫਲੋਟਿੰਗ-ਪੌਇੰਟ ਦੀ built-in float implementation ਨਾਲ ਤੁਲਨਾ ਕਰਨ ਤੇ, ਇਹ ਕਲਾਸ ਖ਼ਾਸ ਤੌਰ 'ਤੇ ਹੇਠਾਂ ਦਿੱਤੀਆਂ ਸਥਿਤੀਆਂ ਵਿੱਚ ਲਾਭਦਾਇਕ ਹੈ
ਵਿੱਤੀ ਐਪਲੀਕੇਸ਼ਨਾਂ ਅਤੇ ਹੋਰ ਉਹ ਵਰਤੋਂ ਜਿਨ੍ਹਾਂ ਨੂੰ ਸਹੀ ਦਸ਼ਮਲਵ ਨੁਮਾਇੰਦਗੀ ਦੀ ਲੋੜ ਹੁੰਦੀ ਹੈ,
ਸ਼ੁੱਧਤਾ ਉੱਤੇ ਨਿਯੰਤਰਣ,
ਕਾਨੂੰਨੀ ਜਾਂ ਨਿਯਮਕ ਲੋੜਾਂ ਨੂੰ ਪੂਰਾ ਕਰਨ ਲਈ rounding ਉੱਤੇ ਨਿਯੰਤਰਣ,
ਮਹੱਤਵਪੂਰਨ ਦਸ਼ਮਲਵ ਅੰਕਾਂ ਦੀ ਨਿਗਰਾਨੀ, ਜਾਂ
ਅਜਿਹੀਆਂ ਐਪਲੀਕੇਸ਼ਨਾਂ ਜਿੱਥੇ ਵਰਤੋਂਕਾਰ ਉਮੀਦ ਕਰਦਾ ਹੈ ਕਿ ਨਤੀਜੇ ਹੱਥ ਨਾਲ ਕੀਤੀਆਂ ਗਣਨਾਵਾਂ ਨਾਲ ਮੇਲ ਖਾਣ।
ਉਦਾਹਰਨ ਲਈ, 70 ਸੈਂਟ ਦੇ ਫ਼ੋਨ ਚਾਰਜ ਉੱਤੇ 5% ਟੈਕਸ ਦੀ ਗਣਨਾ ਕਰਨ ਨਾਲ ਦਸ਼ਮਲਵ ਫਲੋਟਿੰਗ-ਪੌਇੰਟ ਅਤੇ ਬਾਈਨਰੀ ਫਲੋਟਿੰਗ-ਪੌਇੰਟ ਵਿੱਚ ਵੱਖ-ਵੱਖ ਨਤੀਜੇ ਮਿਲਦੇ ਹਨ। ਜੇ ਨਤੀਜਿਆਂ ਨੂੰ ਸਭ ਤੋਂ ਨੇੜਲੇ ਸੈਂਟ ਤੱਕ round ਕੀਤਾ ਜਾਵੇ ਤਾਂ ਇਹ ਫਰਕ ਮਹੱਤਵਪੂਰਨ ਬਣ ਜਾਂਦਾ ਹੈ:
>>> from decimal import *
>>> round(Decimal('0.70') * Decimal('1.05'), 2)
Decimal('0.74')
>>> round(.70 * 1.05, 2)
0.73
Decimal ਨਤੀਜਾ ਅੰਤ ਵਾਲੇ zero ਨੂੰ ਸੰਭਾਲ ਕੇ ਰੱਖਦਾ ਹੈ ਅਤੇ ਦੋ-ਦਸ਼ਮਲਵ-ਸਥਾਨ ਵਾਲੇ ਗੁਣਾਂਕਾਂ ਤੋਂ ਆਪਣੇ ਆਪ ਚਾਰ-ਸਥਾਨੀ ਮਹੱਤਤਾ ਦਾ ਅਨੁਮਾਨ ਲਗਾਉਂਦਾ ਹੈ। Decimal ਹੱਥ ਨਾਲ ਕੀਤੀ ਗਈ ਗਣਿਤ ਨੂੰ ਦੁਹਰਾਉਂਦਾ ਹੈ ਅਤੇ ਉਹਨਾਂ ਸਮੱਸਿਆਵਾਂ ਤੋਂ ਬਚਾਉਂਦਾ ਹੈ ਜੋ ਉਸ ਵੇਲੇ ਪੈਦਾ ਹੁੰਦੀਆਂ ਹਨ ਜਦੋਂ ਬਾਈਨਰੀ ਫਲੋਟਿੰਗ-ਪੌਇੰਟ ਦਸ਼ਮਲਵ ਮਾਤਰਾਵਾਂ ਨੂੰ ਸਹੀ ਤਰ੍ਹਾਂ ਦਰਸਾ ਨਹੀਂ ਸਕਦਾ।
ਸਹੀ ਨੁਮਾਇੰਦਗੀ Decimal ਕਲਾਸ ਨੂੰ modulo ਗਣਨਾਵਾਂ ਅਤੇ ਸਮਾਨਤਾ ਟੈਸਟ ਕਰਨ ਯੋਗ ਬਣਾਉਂਦੀ ਹੈ, ਜੋ ਬਾਈਨਰੀ ਫਲੋਟਿੰਗ-ਪੌਇੰਟ ਲਈ ਉਚਿਤ ਨਹੀਂ ਹੁੰਦੇ:
>>> Decimal('1.00') % Decimal('.10')
Decimal('0.00')
>>> 1.00 % 0.10
0.09999999999999995
>>> sum([Decimal('0.1')]*10) == Decimal('1.0')
True
>>> 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 == 1.0
False
decimal ਮੌਡਿਊਲ ਲੋੜ ਅਨੁਸਾਰ ਜਿੰਨੀ ਮਰਜ਼ੀ ਸ਼ੁੱਧਤਾ ਨਾਲ ਅੰਕਗਣਿਤ ਪ੍ਰਦਾਨ ਕਰਦਾ ਹੈ:
>>> getcontext().prec = 36
>>> Decimal(1) / Decimal(7)
Decimal('0.142857142857142857142857142857142857')