11. íì¤ ë¼ì´ë¸ë¬ë¦¬ ëë¬ë³´ê¸° â 2ë¶Â¶
ì´ ë ë²ì§¸ ëë¬ë³´ê¸°ë ì 문 íë¡ê·¸ëë° ì구 ì¬íì ì§ìíë ê³ ê¸ ëª¨ëì ë¤ë£¨ê³ ììµëë¤. ì´ë¬í 모ëì ìì ì¤í¬ë¦½í¸ììë ê±°ì ì¬ì©ëì§ ììµëë¤.
11.1. ì¶ë ¥ í¬ë§¤í ¶
reprlib 모ëì í¬ê±°ë ê¹ê² ì¤ì²©ë 컨í
ì´ëì ì¶ì½ ë ëì¤íë ì´ë¥¼ ìí´ ì»¤ì¤í°ë§ì´ì¦ë repr() ì ë²ì ì ì ê³µí©ëë¤:
>>> import reprlib
>>> reprlib.repr(set('supercalifragilisticexpialidocious'))
"{'a', 'c', 'd', 'e', 'f', 'g', ...}"
pprint 모ëì ì¸í°í리í°ê° ì½ì ì ìë ë°©ìì¼ë¡ ë´ì¥ ê°ì²´ë ì¬ì©ì ì ì ê°ì²´ë¥¼ ì¸ìíë ê²ì ë³´ë¤ ì êµíê² ì ì´í ì ìê² í©ëë¤. ê²°ê³¼ê° í ì¤ë³´ë¤ 길면 âìì í린í°âê° ì¤ ë°ê¿ê³¼ ë¤ì¬ì°ê¸°ë¥¼ ì¶ê°íì¬ ë°ì´í° 구조를 ë³´ë¤ ëª
ííê² ëíë
ëë¤:
>>> 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() # ê´ë¡ì 매íì ì»ìµëë¤
>>> 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 í´ëì¤ë¥¼ í¬í¨íê³ ìëë°, ìµì¢
ì¬ì©ìê° í¸ì§í기ì ì ì í ë¨ìí 문ë²ì ê°ê³ ììµëë¤. ë°ë¼ì ì¬ì©ìë ìì© íë¡ê·¸ë¨ì ë³ê²½íì§ ìê³ ë ìì© íë¡ê·¸ë¨ì 커ì¤í°ë§ì´ì¦í ì ììµëë¤.
íìì $ ì ì í¨í íì´ì¬ ìë³ì (ìì«ìì ë°ì¤)ë¡ ë§ë¤ì´ì§ ì리íìì ì´ë¦ì ì¬ì©í©ëë¤. ì¤ê´í¸ë¥¼ ì¬ì©íì¬ ì리íìì를 ëë¬ì¸ë©´ 공백ìì´ ìì«ìê° ë¤ë°ë¥´ëë¡ í ì ììµëë¤. $$ ì ì°ë©´ íëì ì´ì¤ì¼ì´í ë $ 를 ë§ëëë¤:
>>> 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 를 ì¼ì¼íµëë¤. ë©ì¼ ë³í© ì¤íì¼ ìì© íë¡ê·¸ë¨ì ê²½ì° ì¬ì©ìê° ì ê³µí ë°ì´í°ê° ë¶ìì í ì ìì¼ë©° safe_substitute() ë©ìëê° ë ì ì í ì ììµëë¤. ë°ì´í°ê° ëë½ ë ê²½ì° ì리íìì를 ë³ê²½íì§ ììµëë¤:
>>> 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 ìë¸ í´ëì¤ë ì¬ì©ì ì ì 구ë¶ì를 ì§ì í ì ììµëë¤. ì를 ë¤ì´ ì¬ì§ ë¸ë¼ì°ì 를 ìí ì¼ê´ ì´ë¦ ë°ê¾¸ê¸° ì í¸ë¦¬í°ë íì¬ ë ì§, ì´ë¯¸ì§ ìíì¤ ë²í¸ ëë íì¼ íìê³¼ ê°ì ì리íììì ë°±ë¶ì¨ 기í¸ë¥¼ ì¬ì©íëë¡ ì íí ì ììµëë¤:
>>> 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 모ëì ê°ë³ ê¸¸ì´ ë°ì´ë리 ë ì½ë íìì¼ë¡ ìì
í기 ìí pack() ê³¼ unpack() í¨ì를 ì ê³µí©ëë¤. ë¤ì ìì ë zipfile 모ëì ì¬ì©íì§ ìê³ ZIP íì¼ì í¤ë ì 보를 루ííë ë²ì ë³´ì¬ì¤ëë¤. í© ì½ë "H" ì "I" ë ê°ê° 2ë°ì´í¸ì 4ë°ì´í¸ì ë¶í¸ ìë ì«ì를 ëíë
ëë¤. "<" ë íì¤ í¬ê¸°ì´ë©´ì 리í ìëì ë°ì´í¸ ìì를 ê°ì§ì ëíë
ëë¤:
import struct
with open('myfile.zip', 'rb') as f:
data = f.read()
start = 0
for i in range(3): # ì²ì 3ê°ì íì¼ í¤ë를 ë³´ì¬ì¤ëë¤
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 # ë¤ì í¤ëë¡ ê±´ëëëë¤
11.4. ë¤ì¤ ì¤ë ë©Â¶
ì¤ë ë©ì ì°¨ë¡ë¡ ì¢ ìëì§ ìë ìì ì ë¶ë¦¬íë 기ì ì ëë¤. ì¤ë ëë ë¤ë¥¸ ìì ì´ ë°±ê·¸ë¼ì´ëìì ì¤íëë ëì ì¬ì©ì ì ë ¥ì ë°ë ìì© íë¡ê·¸ë¨ì ìëµì í¥ìíë ë° ì¬ì©í ì ììµëë¤. ê´ë ¨ë ì¬ì© ì¬ë¡ë ë¤ë¥¸ ì¤ë ëì ê³ì°ê³¼ ë³ë ¬ë¡ I/O를 ì¤ííë ê²½ì°ì ëë¤.
ë¤ì ì½ëë ë©ì¸ íë¡ê·¸ë¨ì´ ê³ì ì¤íëë ëì ê³ ìì¤ threading 모ëì´ ë°±ê·¸ë¼ì´ëìì ìì
ì ì´ë»ê² ìíí ì ìëì§ ë³´ì¬ì¤ëë¤:
import threading, zipfile
class AsyncZip(threading.Thread):
def __init__(self, infile, outfile):
threading.Thread.__init__(self)
self.infile = infile
self.outfile = outfile
def run(self):
f = zipfile.ZipFile(self.outfile, 'w', zipfile.ZIP_DEFLATED)
f.write(self.infile)
f.close()
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() # 백그ë¼ì´ë ìì
ì´ ëë ëê¹ì§ 기ë¤ë¦½ëë¤
print('Main program waited until background was done.')
ë¤ì¤ ì¤ë ë ìì© íë¡ê·¸ë¨ì ê°ì¥ í° ë¬¸ì ì ì ë°ì´í° ëë ë¤ë¥¸ ììì ê³µì íë ì¤ë ë를 ì¡°ì íë ê²ì ëë¤. ì´ë¥¼ ìí´ threading 모ëì ë¡, ì´ë²¤í¸, ì¡°ê±´ ë³ì ë° ì¸ë§í¬ì´ë¥¼ ë¹ë¡¯í ë§ì ìì ë기í 기본 ìì를 ì ê³µí©ëë¤.
ì´ë¬í ë구ë ê°ë ¥íì§ë§, ì¬ìí ì¤ê³ ì¤ë¥ë¡ ì¸í´ ì¬íí기 ì´ë ¤ì´ 문ì ê° ë°ìí ì ììµëë¤. ë°ë¼ì, ìì
ì¡°ì ì ëí ì í¸ëë ì ê·¼ ë°©ìì ììì ëí 모ë ì¡ì¸ì¤ë¥¼ ë¨ì¼ ì¤ë ëì ì§ì¤ìí¨ ë¤ì 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
기본ì ì¼ë¡ ì ë³´ ë° ëë²ê¹
ë©ìì§ë íìëì§ ìê³ ì¶ë ¥ì íì¤ ìë¬ë¡ ë³´ë´ì§ëë¤. ë¤ë¥¸ ì¶ë ¥ ìµì
ìë ì ì ë©ì¼, ë°ì´í° ê·¸ë¨, ìì¼ ëë HTTP ìë²ë¥¼ íµí ë©ìì§ ë¼ì°í
ì´ í¬í¨ë©ëë¤. ìë¡ì´ íí°ë ë©ìì§ ì°ì ììì ë°ë¼ ë¤ë¥¸ ë¼ì°í
ì ì íí ì ììµëë¤: DEBUG, INFO, WARNING, ERROR , ê·¸ë¦¬ê³ CRITICAL.
ë¡ê¹ ìì¤í ì íì´ì¬ìì ì§ì 구ì±íê±°ë, ìì© íë¡ê·¸ë¨ì ë³ê²½íì§ ìê³ ì¬ì©ì ì ì ë¡ê¹ ì ìí´ ì¬ì©ìê° í¸ì§í ì ìë ì¤ì íì¼ìì ë¡ë í ì ììµëë¤.
11.6. ì½í 참조¶
íì´ì¬ì ìë ë©ëª¨ë¦¬ ê´ë¦¬ (ëë¶ë¶ ê°ì²´ì ëí 참조 íì ì¶ì ë° ìíì ì ê±°í기 ìí ê°ë¹ì§ ìê±°)를 ìíí©ëë¤. ë©ëª¨ë¦¬ë ë§ì§ë§ ì°¸ì¡°ê° ì ê±°ë ì§íì í´ì ë©ëë¤.
ì´ ì ê·¼ë²ì ëë¶ë¶ì ìì© íë¡ê·¸ë¨ìì ì ìëíì§ë§, ëë¡ë ë¤ë¥¸ ê²ë¤ì ìí´ ì¬ì©ëë ëììë§ ê°ì²´ë¥¼ ì¶ì í´ì¼ í íìê° ììµëë¤. ë¶ííê²ë, ë¨ì§ ê·¸ê²ë¤ì ì¶ì íë ê²ë§ì¼ë¡ë ê·¸ë¤ì ì구ì ì¼ë¡ ë§ëë 참조를 ë§ëëë¤. weakref 모ëì 참조를 ë§ë¤ì§ ìê³ ê°ì²´ë¥¼ ì¶ì í ì ìë ë구를 ì ê³µí©ëë¤. ê°ì²´ê° ë íìíì§ ìì¼ë©´ weakref í
ì´ë¸ìì ê°ì²´ê° ìëì¼ë¡ ì ê±°ëê³ weakref ê°ì²´ì ëí ì½ë°±ì´ í¸ë¦¬ê±°ë©ëë¤. ì¼ë°ì ì¸ ìì©ìë ë§ëë ë° ë¹ì©ì´ ë§ì´ ëë ê°ì²´ ìºì±ì´ í¬í¨ë©ëë¤:
>>> import weakref, gc
>>> class A:
... def __init__(self, value):
... self.value = value
... def __repr__(self):
... return str(self.value)
...
>>> a = A(10) # create a reference
>>> d = weakref.WeakValueDictionary()
>>> d['primary'] = a # does not create a reference
>>> d['primary'] # fetch the object if it is still alive
10
>>> del a # remove the one reference
>>> gc.collect() # run garbage collection right away
0
>>> d['primary'] # entry was automatically removed
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
d['primary'] # entry was automatically removed
File "C:/python314/lib/weakref.py", line 46, in __getitem__
o = self.data[key]()
KeyError: 'primary'
11.7. 리ì¤í¸ ìì ë구¶
ë´ì¥ 리ì¤í¸ íì¼ë¡ ë§ì ë°ì´í° 구조 ì구를 충족ìí¬ ì ììµëë¤. ê·¸ë¬ë ëë¡ë ë¤ë¥¸ ì±ë¥ ìì¶© ê´ê³ê° ìë ëìì 구íì´ íìí ìë ììµëë¤.
array 모ëì array ê°ì²´ë¥¼ ì ê³µí©ëë¤. ì´ ê°ì²´ë ë±ì§ì ì¸ ë°ì´í°ë§ì ì ì¥íê³ ë³´ë¤ ì¡°ë°íê² ì ì¥íë 리ì¤í¸ì ê°ìµëë¤. ë¤ì ìì ë íì´ì¬ int ê°ì²´ì ì¼ë° 리ì¤í¸ì ê²½ì°ì²ë¼ íëª©ë¹ 16ë°ì´í¸ë¥¼ ì¬ì©íë ëì ì, 2ë°ì´í¸ì ë¶í¸ ìë ì´ì§ ì«ì (í ì½ë "H")ë¡ ì ì¥ë ì«ì ë°°ì´ì ë³´ì¬ì¤ëë¤:
>>> from array import array
>>> a = array('H', [4000, 10, 700, 22222])
>>> sum(a)
26932
>>> a[1:3]
array('H', [10, 700])
collections 모ëì deque ê°ì²´ë¥¼ ì ê³µí©ëë¤. ì´ ê°ì²´ë ì¼ìª½ìì ë ë¹ ë¥´ê² ì¶ê°/ííì§ë§ ì¤ê°ììì ì¡°íë ë ëë ¤ì§ ë¦¬ì¤í¸ì ê°ìµëë¤. ì´ ê°ì²´ë ëê¸°ì´ ë° ëì´ ì°ì í¸ë¦¬ ê²ìì 구ííë ë° ì í©í©ëë¤:
>>> 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)
ëìì 리ì¤í¸ 구í ì¸ìë ë¼ì´ë¸ë¬ë¦¬ë ì ë ¬ë 리ì¤í¸ë¥¼ ì¡°ìíë í¨ìë¤ì´ ìë bisect 모ëê³¼ ê°ì ë¤ë¥¸ ë구를 ì ê³µí©ëë¤:
>>> 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 모ëì ì¼ë° 리ì¤í¸ë¥¼ 기ë°ì¼ë¡ íì 구ííë í¨ì를 ì ê³µí©ëë¤. ê°ì¥ ê°ì´ ìì í목ì íì ìì¹ 0ì ì ì§ë©ëë¤. ì´ê²ì ê°ì¥ ìì ììì ë°ë³µì ì¼ë¡ ì¡ì¸ì¤íì§ë§, ì ì²´ ëª©ë¡ ì ë ¬ì ì¤ííì§ ìì¼ë ¤ë ìì©ì ì ì©í©ëë¤:
>>> from heapq import heapify, heappop, heappush
>>> data = [1, 3, 5, 7, 9, 2, 4, 6, 8, 0]
>>> heapify(data) # 리ì¤í¸ë¥¼ í ììë¡ ì¬ë°°ì¹í©ëë¤
>>> heappush(data, -5) # ì í목ì ì¶ê°í©ëë¤
>>> [heappop(data) for i in range(3)] # ê°ì¥ ìì ì¸ ê°ì í목ì ê°ì ¸ìµëë¤
[-5, 0, 1]
11.8. 10ì§ ë¶ë ììì ì°ì ¶
decimal 모ëì 10ì§ ë¶ë ììì ì°ì ì ìí Decimal ë°ì´í°íì ì ê³µí©ëë¤. ë´ì¥ float ì´ì§ ë¶ë ììì 구íê³¼ ë¹êµí ë, í´ëì¤ë í¹í ë¤ìê³¼ ê°ì ê²ë¤ì ì ì©í©ëë¤
ì íí 10ì§ì ííì´ íìí ê¸ìµ ìì© ë° ê¸°í ì©ë,
ì ë°ë ì ì´,
ë²ì ëë ê·ì ì구 ì¬íì 충족íë ë°ì¬ë¦¼ ì ì´,
ì í¨ì«ì ì¶ì , ëë
ì¬ì©ìê° ê²°ê³¼ê° ìì¼ë¡ ê³ì°í ê²ê³¼ ì¼ì¹ í ê²ì¼ë¡ 기ëíë ìì©.
ì를 ë¤ì´, 70ì¼í¸ ì í ìê¸ì ëí´ 5% ì¸ê¸ì ê³ì°íë©´, ìì§ ë¶ë ììì ë° ì´ì§ ë¶ë ììì ì ë¤ë¥¸ ê²°ê³¼ê° ëíë©ëë¤. 결과를 ê°ì¥ ê°ê¹ì´ ì¼í¸ë¡ ë°ì¬ë¦¼íë©´ ì°¨ì´ê° ëë¬ë©ëë¤:
>>> from decimal import *
>>> round(Decimal('0.70') * Decimal('1.05'), 2)
Decimal('0.74')
>>> round(.70 * 1.05, 2)
0.73
Decimal ê²°ê³¼ë ëì ë¶ë 0ì ì ì§íë©°, ë ê°ì ì í¨ì«ì를 ê°ì§ í¼ì¹ìë¡ë¶í° ë¤ ì리ì ì í¨ì«ì를 ìëì¼ë¡ ì¶ë¡ í©ëë¤. Decimalì ìì¼ë¡ í ìíì ì¬ííê³ ì´ì§ ë¶ë ììì ì´ ìì§ì를 ì ííê² ííí ì ìì ë ë°ìí ì ìë 문ì 를 í¼í©ëë¤.
ì íí ííì Decimal í´ëì¤ê° ì´ì§ ë¶ë ììì ì ì í©íì§ ìì 모ëë¡ ê³ì°ê³¼ ëë±ì± ê²ì¬ë¥¼ ìíí ì ìëë¡ í©ëë¤:
>>> 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')