ãŸããã
Mark Lutzã®Learning Pythonæ¬ãèªãã åŸãç§ã¯Pythonã«æ¬åœã«å€¢äžã«ãªããŸããã èšèªã¯ãšãŠãçŸãããèªåã®èããæžããŠè¡šçŸããã®ã¯æ¥œããã§ãã 倿°ã®ã€ã³ã¿ãŒããªã¿ãŒãšã³ã³ãã€ã©ãŒãæ¡åŒµæ©èœãã¢ãžã¥ãŒã«ãããã³ãã¬ãŒã ã¯ãŒã¯ã¯ãã³ãã¥ããã£ãŒãéåžžã«æŽ»çºã§ãããèšèªãéçºäžã§ããããšã瀺ããŠããŸãã èšèªãåŠã¶éçšã§ãç§ã¯æ
éã«ã°ãŒã°ã«ã§èª¿ã¹ãå€ãã®è³ªåããããçè§£ã§ããªããã¹ãŠã®æ§é ãçè§£ããããšããŸããã ããã«ã€ããŠã¯ãã®èšäºã§èª¬æããŸããããã®èšäºã¯åå¿è
ã®Pythonéçºè
ã察象ãšããŠããŸãã
çšèªã«ã€ããŠå°ã
ãããããåå¿è
ã®Pythonããã°ã©ããŒããã°ãã°æ··ä¹±ãããçšèªããå§ããŸãã
ãªã¹ãå
å
衚èšãŸãã¯ãªã¹ããžã§ãã¬ãŒã¿ãŒã¯ãªã¹ããè¿ããŸãã ãªã¹ããžã§ãã¬ãŒã¿ãŒãšåŒãžã§ãã¬ãŒã¿ãŒã¯åžžã«æ··åããŸããïŒãã ããåŒãžã§ãã¬ãŒã¿ãŒã¯ïŒïŒã åæããŸãããã·ã¢èªã§ã¯éåžžã«äŒŒãŠããŸãã åŒ-ãžã§ãã¬ãŒã¿ãŒã¯
ãžã§ãã¬ãŒã¿ãŒåŒ ããªã¹ãã§ã¯ãªãã€ãã¬ãŒã¿ãŒãè¿ãç¹å¥ãªåŒã§ãã æ¯èŒããŠã¿ãŸãããïŒ
f = (x for x in xrange(100))
ãããã¯2ã€ã®ãŸã£ããç°ãªãèšèšã§ãã æåã¯ãžã§ãã¬ãŒã¿ãŒïŒã€ãŸããã€ãã¬ãŒã¿ãŒïŒãè¿ãã2çªç®ã¯éåžžã®ãªã¹ãã§ãã
ãžã§ãã¬ãŒã¿ãŸãã¯ãžã§ãã¬ãŒã¿ã¯ãã€ãã¬ãŒã¿ãè¿ãç¹å¥ãªé¢æ°ã§ãã ãžã§ãã¬ãŒã¿ãŒãååŸããã«ã¯ãyieldãä»ããŠé¢æ°å€ãè¿ãå¿
èŠããããŸãã
def prime(lst): for i in lst: if i % 2 == 0: yield i >>> f = prime([1,2,3,4,5,6,7]) >>> list(f) [2, 4, 6] >>> next(f) Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration >>>
ãšããã§ãPython 3.3ã¯ãconstructããæ°ããyieldãå°å
¥ããŸããã yieldãšforã®å
±æã¯é »ç¹ã«äœ¿çšãããããã2ã€ã®æ§æèŠçŽ ãçµã¿åãããããšã«ããŸãã
def generator_range(first, last): for i in xrange(first, last): yield i def generator_range(first, last): yield from range(first, last)
ã³ã³ããã¹ããããŒãžã£ãŒãšã¯äœã§ããïŒ
ã³ã³ããã¹ããããŒãžã£ã¯ãwithã¹ããŒãã¡ã³ãã§å²ãŸããã³ãŒãã®ãããã¯ã§ããç¹å¥ãªæ§é ã§ãã withã¹ããŒãã¡ã³ãã¯ãã³ã³ããã¹ããããŒãžã£ãŒãããã³ã«ã䜿çšããŠãããã¯ãäœæããŸããããã«ã€ããŠã¯ããã®èšäºã®åŸåã§èª¬æããŸãã ãã®ãããã³ã«ã䜿çšããæãåçŽãªé¢æ°ã¯ãopenïŒïŒé¢æ°ã§ãã ãã¡ã€ã«ãéããã³ã«ãåºåããã£ã¹ã¯ã«ããã·ã¥ããããã«ãã¡ã€ã«ãéããå¿
èŠããããŸãïŒå®éãPythonã¯closeïŒïŒã¡ãœãããèªåçã«åŒã³åºããŸãããæç€ºçã«äœ¿çšããããšããå§ãããŸãïŒã äŸïŒ
fp = open("./file.txt", "w") fp.write("Hello, World") fp.close()
æ¯åcloseïŒïŒã¡ãœãããåŒã³åºããªãããã«ããããã«ãopenïŒïŒé¢æ°ã®ã³ã³ããã¹ããããŒãžã£ãŒã䜿çšã§ããŸããããã¯ããããã¯ãçµäºããåŸã«ãã¡ã€ã«ãèªåçã«éããŸãã
with open("./file.txt", "w") as fp: fp.write("Hello, World")
ããã§ã¯ãããŒã¿ããã¡ã€ã«ã«ããã·ã¥ãããã³ã«closeã¡ãœãããåŒã³åºãå¿
èŠã¯ãããŸããã ãããã£ãŠãã³ã³ããã¹ããããŒãžã£ã䜿çšããŠããããã¯ã«å
¥ãåãšçµäºããåŸã«ã¢ã¯ã·ã§ã³ãå®è¡ããŸãã ããããã³ã³ããã¹ããããŒãžã£ã®æ©èœã¯ããã§çµããã§ã¯ãããŸããã å€ãã®ããã°ã©ãã³ã°èšèªã§ã¯ããã®ãããªã¿ã¹ã¯ã«ãã¹ãã©ã¯ã¿ã䜿çšããŠããŸãã ãã ããPythonã§ã¯ããªããžã§ã¯ããä»ã®å Žæã§äœ¿çšãããå Žåããªããžã§ã¯ããžã®ãã¹ãŠã®åç
§ã䜿ãæããããå Žåã«ã®ã¿__del__ã¡ãœãããåŒã³åºãããããããã¹ãã©ã¯ã¿ãåŒã³åºãããä¿èšŒã¯ãããŸããã
In [4]: class Hello: ...: def __del__(self): ...: print 'destructor' ...: In [5]: f = Hello() In [6]: c = Hello() In [7]: e = Hello() In [8]: del e destructor In [9]: del c destructor In [10]: c = f In [11]: e = f In [12]: del f
ã³ã³ããã¹ããããŒãžã£ãŒã䜿çšããŠãã®åé¡ã解決ããŸãã
In [1]: class Hello: ...: def __del__(self): ...: print u'' ...: def __enter__(self): ...: print u' ' ...: def __exit__(self, exp_type, exp_value, traceback): ...: print u' ' ...: In [2]: f = Hello() In [3]: c = f In [4]: e = f In [5]: d = f In [6]: del d In [7]: del e In [8]: del c In [9]: del f
次ã«ãã³ã³ããã¹ããããŒãžã£ãåŒã³åºããŠã¿ãŸãã
In [10]: with Hello(): ....: print u' ' ....:
ã³ãŒãã®å®è¡åŸããããã¯ããã®çµäºãä¿èšŒãããŠããããšãããããŸããã
ã³ã³ããã¹ããããŒãžã£ãŒãããã³ã«
ç°¡åãªHelloã¯ã©ã¹ãäœæããŠãã³ã³ããã¹ããããŒãžã£ãããã³ã«ãç°¡åã«ç¢ºèªããŸããã ãããã³ã«ã«ã€ããŠè©³ããèŠãŠãããŸãããã ãªããžã§ã¯ããã³ã³ããã¹ããããŒãžã£ãŒã«ãªãã«ã¯ããã®ã¯ã©ã¹ã«__enter__ãš__exit__ã®2ã€ã®ã¡ãœãããå«ããå¿
èŠããããŸãã æåã®ã¡ãœããã¯ããããã¯ã«å
¥ãåã«å®è¡ãããŸãã ã¯ã©ã¹ã®çŸåšã®ã€ã³ã¹ã¿ã³ã¹ãã¡ãœããã«è¿ããŠãasã¹ããŒãã¡ã³ããä»ããŠã¢ã¯ã»ã¹ã§ããããã«ããããšãã§ããŸãã
__exit__ã¡ãœããã¯ãwithãããã¯ã®çµäºåŸã«å®è¡ãããexp_typeãexp_valueãexp_trã®3ã€ã®ãã©ã¡ãŒã¿ãŒãå«ãŸããŠããŸãã ã³ã³ããã¹ããããŒãžã£ã¯ãwithãããã¯ã§çºçããäŸå€ããã£ããã§ããŸãã å¿
èŠãªäŸå€ã®ã¿ããã£ããããããäžèŠãªäŸå€ãæå¶ã§ããŸãã
class Open(object): def __init__(self, file, flag): self.file = file self.flag = flag def __enter__(self): try: self.fp = open(self.file, self.flag) except IOError: self.fp = open(self.file, "w") return self.fp def __exit__(self, exp_type, exp_value, exp_tr): """ IOError """ if exp_type is IOError: self.fp.close()
倿°exp_typeã«ã¯ãçºçããäŸå€ã¯ã©ã¹ãå«ãŸããŸããexp_valueã¯äŸå€ã¡ãã»ãŒãžã§ãã ãã®äŸã§ã¯ããã¡ã€ã«ãéãã__ exit__ã¡ãœããã«Trueãè¿ãããšã§IOErroräŸå€ãæå¶ããŸãã ãããã¯å
ã®ä»ã®ãã¹ãŠã®äŸå€ã¯èš±å¯ãããŸãã ã³ãŒããçµäºããŠãããã¯ãçµäºãããšããã«ãçºçããäŸå€ã«é¢ä¿ãªãself.fp.closeïŒïŒã¡ãœãããåŒã³åºãããŸãã ãšããã§ãwithãããã¯å
ã§ã¯ãNameErrorãSyntaxErrorãªã©ã®äŸå€ãæå¶ããããšãã§ããŸããããããè¡ãã¹ãã§ã¯ãããŸããã
ã³ã³ããã¹ããããŒãžã£ãããã³ã«ã¯éåžžã«äœ¿ããããã§ãããäžè¬çãªã¿ã¹ã¯ã«ã¯ãæšæºã®Pythonã©ã€ãã©ãªã«ä»å±ããããã«ç°¡åãªã¡ãœããããããŸãã æ¬¡ã«ãcontextlibããã±ãŒãžãèŠãŠãã ããã
Contextlibããã±ãŒãž
åŸæ¥ã®æ¹æ³ãã€ãŸã__enter__ããã³__exit__ã¡ãœããã䜿çšããŠã¯ã©ã¹ãäœæããæ¹æ³ã§ã³ã³ããã¹ããããŒãžã£ãŒãäœæããããšã¯ãé£ããã¿ã¹ã¯ã®1ã€ã§ã¯ãããŸããã ããããäºçްãªã³ãŒãã®å Žåããã®ãããªã¯ã©ã¹ãæžãã«ã¯ãããã«å€§éšããå¿
èŠã§ãã ãã®ç®çã®ããã«ãcontextlibããã±ãŒãžã®äžéšã§ããcontextmanagerïŒïŒãã³ã¬ãŒã¿ãçºæãããŸããã contextmanagerïŒïŒãã³ã¬ãŒã¿ãŒã䜿çšããŠãéåžžã®é¢æ°ããã³ã³ããã¹ããããŒãžã£ãŒãäœæã§ããŸãã
import contextlib @contextlib.contextmanager def context(): print u' ' try: yield {} except RuntimeError, err: print 'error: ', err finally: print u' '
ã³ãŒãã®æ£åžžæ§ã確èªããŸãã
In [8]: with context() as fp: ...: print u'' ...:
ãããã¯å
ã§äŸå€ãçºçãããŠã¿ãŸãããã
In [14]: with context() as value: ....: raise RuntimeError, 'Error' ....: error: Error In [15]:
ãã®äŸãããããããã«ãã¯ã©ã¹ã䜿çšããå®è£
ã¯ãcontextmanagerïŒïŒãã³ã¬ãŒã¿ã䜿çšããå®è£
ãšæ©èœçã«å®è³ªçã«éãã¯ãããŸãããããã³ã¬ãŒã¿ã䜿çšãããšã³ãŒãã倧å¹
ã«ç°¡çŽ åãããŸãã
contextmanagerïŒïŒãã³ã¬ãŒã¿ã䜿çšããå¥ã®è峿·±ãäŸïŒ
import contextlib @contextlib.contextmanager def bold_text(): print '<b>' yield
çµæïŒ
<b>Hello, World</b>
ã«ããŒã®ãããã¯ã®ããã«èãããŸããïŒ
æåŸã«ããã¹ããããã³ã³ããã¹ãã«ã€ããŠèª¬æããŸãã ãã¹ããããã³ã³ããã¹ãã䜿çšãããšãè€æ°ã®ã³ã³ããã¹ããäžåºŠã«ç®¡çã§ããŸãã äŸïŒ
import contextlib @contextlib.contextmanager def context(name): print u' %s' % (name) yield name
çµæïŒ
æåã«ã³ã³ããã¹ããå
¥åããŸã
ã³ã³ããã¹ããå
¥åãã
æåã®2çªç®ã®ãããã¯å
ã³ã³ããã¹ãå€ç§
æåã«ã³ã³ããã¹ããã
ãã¹ãããã颿°ã䜿çšããªãåæ§ã®ã³ãŒãïŒ
first, second = context('first'), context('second') with first as first: with second as second: print u' %s %s' % (first, second)
ãã®ã³ãŒãã¯åã®ã³ãŒããšäŒŒãŠããŸãããç¶æ³ã«ãã£ãŠã¯åžæã©ããã«æ©èœããŸããã ã³ã³ããã¹ãïŒ 'first'ïŒããã³ã³ã³ããã¹ãïŒ 'second'ïŒãªããžã§ã¯ãã¯ãããã¯ã«å
¥ãåã«åŒã³åºãããããããããã®ãªããžã§ã¯ãã§çºçããäŸå€ããã£ããããããšã¯ã§ããŸããã åæããŠãæåã®ãªãã·ã§ã³ã¯ã¯ããã«ã³ã³ãã¯ãã§ãèŠãç®ããããã§ãã ããããPython 2.7ããã³3.1ã§ã¯ããã¹ãããã颿°ã¯å»æ¢ããããã¹ããããã³ã³ããã¹ãã®æ°ããæ§ææ§æã远å ãããŸããã
with context('first') as first, context('second') as second: print u' %s %s' % (first, second)
Python 2.7ããã³Python 3ã®rangeããã³xrange
Python 2.7ã®ç¯å²ã¯ãªã¹ããè¿ãããšãç¥ãããŠããŸãã 倧éã®ããŒã¿ãã¡ã¢ãªã«ä¿åããããšã¯å®çšçã§ã¯ãªãããšã«èª°ããåæãããšæãã®ã§ããªã¹ããšã»ãšãã©åãããã«åäœãããããã¹ãŠã®åºåèŠçŽ ãã¡ã¢ãªã«ä¿åããªãxrangeãªããžã§ã¯ããè¿ãxrange颿°ã䜿çšããŸãã ãããã倧ããªå€ã颿°ã«æž¡ããããšãã®Python 2.xã®xrangeã®åäœã«ã¯å°ãé©ããŠããŸããã äŸãèŠãŠã¿ãŸãããïŒ
>>> f = xrange(1000000000000000000000) Traceback (most recent call last): File "<stdin>", line 1, in <module> OverflowError: Python int too large to convert to C long >>>
Pythonã¯ãintãé·ãããŠãC longã«å€æã§ããªãããšã瀺ããŠããŸãã Python 2.xã«ã¯æŽæ°ã«é¢ããå¶éãããããšãããããŸãããsys.maxsize宿°ã調ã¹ãããšã§ããã確èªã§ããŸãã
>>> import sys >>> sys.maxsize 9223372036854775807 >>>
ããã¯æŽæ°ã®æå€§å€ã§ãïŒ
>>> import sys >>> sys.maxsize+1 9223372036854775808L >>>
Pythonã¯æ°å€ããããã«long intã«å€æããŸããã Python 2.xã®xrangeã倧ããªå€ã«å¯ŸããŠç°ãªãæ¯ãèããããŠãé©ããªãã§ãã ããã
Python 3.3ã§ã¯ãæŽæ°ã¯ç¡éã«å€§ãããªãå¯èœæ§ããããŸãããã§ãã¯ããŠã¿ãŸãããã
>>> import sys >>> sys.maxsize 9223372036854775807 >>> range(sys.maxsize+1) range(0, 9223372036854775808) >>>
long intãžã®å€æã¯è¡ãããŸããã§ããã å¥ã®äŸã次ã«ç€ºããŸãã
>>> import sys >>> sys.maxsize + 1 9223372036854775808 >>> f = sys.maxsize + 1 >>> type(f) <class 'int'> >>>
Python 2.7ã§
>>> import sys >>> type(sys.maxsize + 1) <type 'long'> >>>
ããã€ãã®ãã¶ã€ã³ã®æããã§ãªãåäœ
pythonã®ã·ã³ãã«ãã¯ããã®åŠç¿ã®å®¹æãã§ã¯ãªããèšèªèªäœã®ã·ã³ãã«ãã«ãããšèª°ããåæãããšæããŸãã Pythonã¯çŸãããæè»æ§ãããããªããžã§ã¯ãæåã®ã¹ã¿ã€ã«ã ãã§ãªããæ©èœçãªã¹ã¿ã€ã«ã§ãèšè¿°ã§ããŸãã ããããäžèŠå¥åŠã«èŠããäžéšã®æ§é ã®åäœã«ã€ããŠç¥ãå¿
èŠããããŸãã æåã«ãæåã®äŸãæ€èšããŸãã
>>> f = [[]] * 3 >>> f[0].append('a') >>> f[1].append('b') >>> f[2].append('c') >>>
ãã®æ§é ã®çµæã¯ã©ããªããŸããïŒ ãã¬ãŒãã³ã°ãåããŠããªãéçºè
ãçµæãå ±åããŸãïŒ[['a']ã[b ']ã[c']]ã ããããå®éã«ã¯æ¬¡ã®ããã«ãªããŸãã
>>> print f [['a', 'b', 'c'], ['a', 'b', 'c'], ['a', 'b', 'c']] >>>
åãªã¹ãã§çµæãéè€ããŠããã®ã¯ãªãã§ããïŒ å®éãä¹ç®æŒç®åã¯ãªã¹ãå
ã«åããªã¹ããžã®ãªã³ã¯ãäœæããŸãã ããã¯ãäŸã«å°ã远å ããããšã§ç°¡åã«ç¢ºèªã§ããŸãã
>>> c = [[], [], []] >>> hex(id(c[0])), hex(id(c[1])), hex(id(c[2])) ('0x104ede7e8', '0x104ede7a0', '0x104ede908') >>> >>> hex(id(f[0])), hex(id(f[1])), hex(id(f[2])) ('0x104ede710', '0x104ede710', '0x104ede710') >>>
æåã®ã±ãŒã¹ã§ã¯ãã¹ãŠãæ£åžžã§ããããªã¹ããžã®ãªã³ã¯ã¯ç°ãªããŸãã2çªç®ã®äŸã§ã¯ãåããªããžã§ã¯ããåç
§ããŸãã æåã®ãªã¹ãã®å€æŽã¯ãåŸç¶ã®ãªã¹ãã®å€æŽã䌎ãããšã«ãªããŸãã®ã§ã泚æããŠãã ããã
2çªç®ã®äŸã¯ãã§ã«ããã§æ€èšãããŸããããèšäºã«å«ããããšæããŸããã forã«ãŒããå®è¡ãã颿°ã§ããlambdaãèŠãŠãå颿°ãèŸæžã«å
¥ããŸãããïŒ
>>> tmp = {} >>> for i in range(10): ... tmp[i] = lambda: i >>> tmp[0]() 9 >>> tmp[1]() 9 >>>
ã©ã ã颿°å
ã§ã¯ã倿°iãéããããå¥ã®å€æ°iã®ã€ã³ã¹ã¿ã³ã¹ãã©ã ããããã¯ã«äœæãããŸã-forã«ãŒãå
ã®å€æ°iãžã®åç
§ã§ãã颿°ã§ãã forã«ãŒãã«ãŠã³ã¿ãŒãå€ãããã³ã«ããã¹ãŠã®ã©ã ã颿°ã®å€ãå€ããããããã¹ãŠã®é¢æ°ã§å€i-1ãååŸããŸãã ããã¯ãã©ã ã颿°ãæåã®ãã©ã¡ãŒã¿ãŒãšããŠæç€ºçã«ããã©ã«ãå€-i倿°ã«æž¡ãããšã§ç°¡åã«ä¿®æ£ã§ããŸãã
>>> tmp = {} >>> for i in range(10): ... tmp[i] = lambda i = i: i >>> tmp[0]() 0 >>> tmp[1]() 1 >>>