What’s New In Python 3.3を
       ざっと眺める
     Kyoto.py	 Python勉強会	 in	 高槻
お前、誰よ

おのうえ(@_likr)

JR高槻からバスで30分ぐらいのとこで大学院生

PythonとかOCamlとかGPGPUが好き
最近はC++とかPHPおいしいです(^q^)状態

京都人ではない
概要

もうすぐPython3.3がリリース

Python3への移行猶予期間を経て
本格的な言語アップデートが再開

Python3.3で新しくなることについて
おのうえの独断と偏見で紹介
Python3を取り巻く事情
Python3

2008年12月3日にPython 3.0.0がリリース

2系と後方互換性がなく多くのプログラムで要修正

サードパーティ製ライブラリの対応が未完全

Python3のススメ - Python京都勉強会
http://www.slideshare.net/naoina/python-kyoto-study
おのうえが最近使った
Python3対応ライブラリ
numpy      matplotlib

PyCUDA     SQLAlchemy

PyOpenCL   pip

PyOpenGL   Sphinx

Mako       IPython
私感

Python3に対応したライブラリは増えてきた

リポジトリの最新版を試したりが必要

3系にしか入ってない機能がたまに欲しくなる

自分が書くコードの寿命をのばしたいなら
Python3事情を理解しておくと吉
Python3.3

PEP 3003 -- Python Language Moratorium

  Python3.1のリリース後2年は構文、
  セマンティクス、ビルトインを変更しない

  ∼ 2011年6月

構文等の変更を含んだ新バージョン
Release Schedule


3.3.0 candidate 1 - 2012年8月25日(イマココ)

3.3.0 candidate 2 - 2012年9月7日

3.3.0 final - 2012年9月22日
新しい構文
1. yield from
yield from

 1 def generator():                 1 def subgenerator():
 2     yield 'start'                2     yield 1
 3
 4     yield 1             これまでは    3
                                    4
                                          yield 2
                                          yield 3
 5     yield 2                      5     yield 4
 6     yield 3                      6     yield 5
 7     yield 4                      7
 8     yield 5                      8
 9                                  9 def generator():
10                                 10     yield 'start'
11 for v in generator():           11
12     print(v)                    12     for v in subgenerator():
                                   13         yield v
                                   14
                                   15
                                   16 for v in generator():
                                   17     print(v)
yield from

 1 def generator():                       1 def subgenerator():
 2     yield 'start'                      2     yield 1
 3
 4     yield 1             Python3.3では    3
                                          4
                                                yield 2
                                                yield 3
 5     yield 2                            5     yield 4
 6     yield 3                            6     yield 5
 7     yield 4                            7
 8     yield 5                            8
 9                                        9 def generator():
10                                       10     yield 'start'
11 for v in generator():                 11
12     print(v)                          12     yield from subgenerator()
                                         13
                                         14
                                         15 for v in generator():
                                         16     print(v)


       generatorを部品化しやすくるする構文
値をsendする場合
                                  1   def subgenerator(value):
                                  2       while True:
                                  3           x = yield value
 1   def generator():
                                  4           if x is not None:
 2       value = yield 'start'
                                  5               value += x
 3       while True:
                                  6
 4           x = yield value
                                  7
 5           if x is not None:
                                  8   def generator():
 6               value += x
                                  9       value = yield 'start'
 7
                                 10       for v in subgenerator(value):
 8
                                 11           yield v
 9   g = generator()
                                 12
10   print(next(g))
                                 13
11   print(g.send(1))
                                 14   g = generator()
12   print(g.send(2))
                                 15   print(next(g))
13   print(g.send(3))
                                 16   print(g.send(1))
                                 17   print(g.send(2))
                                 18   print(g.send(3))


start                            start
1                                1
3                                1
6                                1
値をsendする場合
                   1   def subgenerator(value):
                   2       while True:
                   3           x = yield value

sendに対応するyieldは
                   4           if x is not None:
                   5               value += x
                   6
                   7
    ここじゃなくて        8
                   9
                       def generator():
                           value = yield 'start'
                  10       for v in subgenerator(value):
                  11           yield v
                  12
                  13
            ここ    14
                  15
                       g = generator()
                       print(next(g))
                  16   print(g.send(1))
                  17   print(g.send(2))
                  18   print(g.send(3))


                  start
                  1
                  1
                  1
値をsendする場合
                                  1   def subgenerator(value):
                                  2       while True:
                                  3           x = yield value
 1   def generator():
                                  4           if x is not None:
 2       value = yield 'start'
                                  5               value += x
 3       while True:
                                  6
 4           x = yield value
                                  7
 5           if x is not None:
                                  8   def generator():
 6               value += x
                                  9       value = yield 'start'
 7
                                 10       yield from subgenerator(value)
 8
                                 11
 9   g = generator()
                                 12
10   print(next(g))
                                 13   g = generator()
11   print(g.send(1))
                                 14   print(next(g))
12   print(g.send(2))
                                 15   print(g.send(1))
13   print(g.send(3))
                                 16   print(g.send(2))
                                 17   print(g.send(3))



start                            start
1                                1
3                                3
6                                6
詳しい話とか

PEP 380 -- Syntax for Delegating to a Subgenerator
http://www.python.org/dev/peps/pep-0380/

atsuoishimotoの日記
Python3 Advent Calendar 二十日目
PEP 380 -- Syntax for Delegating to a Subgenerator
http://d.hatena.ne.jp/atsuoishimoto/20111220
2. raise xxx from yyy
raise xxx from yyy
 1 class MyException(Exception):
 2     pass
 3
 4
 5 def f(value):
 6     try:
 7          value = int(value)
 8     except Exception:
 9          raise MyException()
10     return value
11
12
13 f('spam')

$ python3.3 hoge.py
Traceback (most recent call last):
  File "hoge.py", line 7, in f
    value = int(value)
ValueError: invalid literal for int() with base 10: 'spam'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "hoge.py", line 13, in <module>
    f('spam')
  File "hoge.py", line 9, in f
    raise MyException()
__main__.MyException
raise xxx from yyy
 1 class MyException(Exception):
 2     pass
 3
 4
 5 def f(value):
 6     try:
 7          value = int(value)
 8     except Exception:
 9          raise MyException() from None
10     return value
11
12
13 f('spam')

$ python3.3 hoge.py
Traceback (most recent call last):
  File "hoge2.py", line 13, in <module>
    f('spam')
  File "hoge2.py", line 9, in f
    raise MyException() from None
__main__.MyException




  内部例外の隠                             を簡略化できる
3. u’explicit string literals’
explicit unicode literals
      Python3で廃止されていた構文が3.3で復活

      2系との互換性を保ちやすくなる
                                          $ python2.7 test.py
1 # coding: utf-8                         <type 'str'>
2                                         <type 'unicode'>
3 from __future__ import print_function
4                                         $ python3.2 test.py
5 text = 'あいうえお'                            File "test.py", line 8
                                              utext = u'あいうえお'
6 print(type(text))
7                                                                       ^
8 utext = u'あいうえお'                        SyntaxError: invalid syntax

9 print(type(utext))                      $ python3.3 test.py
                                          <class 'str'>
                                          <class 'str'>
新しいモジュール
1. faulthandler
faulthandler

C実装のモジュールでのエラーなど
低レベルのデバッグをしやすくする

Segmentation faultの検出、タイムアウト処理など

インタプリタ実行時や環境変数でも設定可能
faulthandler
1   import ctypes
2
3   i = ctypes.c_int(42)
4   pi = ctypes.pointer(i)
5   print(pi[100000000])



$ python3.3 test.py
Segmentation fault: 11

$ python3.3 -X faulthandler test.py
Fatal Python error: Segmentation fault

Current thread 0x00007fff72875180:
  File "test.py", line 5 in <module>
Segmentation fault: 11

$ export PYTHONFAULTHANDLER=1

$ python3.3 test.py
Fatal Python error: Segmentation fault

Current thread 0x00007fff72875180:
  File "test.py", line 5 in <module>
Segmentation fault: 11
参考情報


2.5∼3.2用
http://pypi.python.org/pypi/faulthandler/

Python Insider JA
Python 3.3 で導入されるデバッグに役立つ faulthandler モジュール
http://blog-ja.python.org/2011/05/python-33-faulthandler.html
2. ipaddress
ipaddress
IPアドレスを扱うモジュール

v6対応
  1   import ipaddress
  2
  3   ip = ipaddress.ip_address('192.168.0.1')
  4   print(str(ip))
  5   print(int(ip))
  6
  7   ip2 = ipaddress.ip_address(int(ip + 5))
  8   print(str(ip2))


  $ python3.3 ip.py
  192.168.0.1
  3232235521
  192.168.0.6
3. venv
virtualenv

Python実行環境を仮想化する
サードパーティ製ライブラリ

システムに影響がないようにライブラリをイ
ンストールしたり、プロジェクト毎に実行環
境を切り替えるのに利用
venv


virtualenv相当の機能が標準に

$ python3.3 -m venv /path/to/new/virtual/environment

                               or

$ pyvenv /path/to/new/virtual/environment


$ source <venv>/bin/activate
あれはどうなった?
packaging

setuptools, Distribute, distutils, pipの機能を
まるっと統合して標準化

Python3.3の目玉機能の1つだったが
リリース見送り

Distutils2のインストールで代用可能?
その他
rangeオブジェクトの同値性
   1   a = range(5)
   2   b = range(5)
   3
   4   print(a == a)
   5   print(a == b)




   $ python2.7 range.py
   True
   True

   $ python3.2 range.py
   True
   False

   $ python3.3 range.py
   True
   True
IO/OSError例外の階層
 +-- EnvironmentError
    +-- IOError
        +-- io.BlockingIOError
        +-- io.UnsupportedOperation (also inherits from ValueError)
        +-- socket.error
            +-- socket.gaierror
            +-- socket.herror
            +-- socket.timeout
    +-- OSError
        +-- VMSError
        +-- WindowsError
    +-- mmap.error
 +-- select.error




 +-- OSError (replacing IOError, WindowsError, EnvironmentError, etc.)
    +-- io.BlockingIOError
    +-- io.UnsupportedOperation (also inherits from ValueError)
    +-- socket.gaierror
    +-- socket.herror
    +-- socket.timeout
list.copy / list.clear
dict, setなど他のcollectionとの互換性のため
   1   def copy_collection(c):
   2       return c.copy()
   3
   4
   5   def clear_collection(c):
   6       c.clear()
   7
   8
   9   l = [1, 2, 3]
  10   d = {'spam': 'ham'}
  11   s = {1, 2, 3}
  12
  13   l2 = copy_collection(l)
  14   clear_collection(l)
  15
  16   d2 = copy_collection(d)
  17   clear_collection(d)
  18
  19   s2 = copy_collection(s)
  20   clear_collection(s)
__qualname__

1 class A:
2     class B:
3          def f(self):
4              pass
5
6
7 print(A.B.f.__name__)
8 print(A.B.f.__qualname__)



$ python3.3 qname.py
f
A.B.f
raw bytes literals


 >>> rb'n'
 b'n'

 >>> br'n'
 b'n'
実行効率の向上

unicode strings

  Djangoによるベンチマークでメモリ消費量が
  3.2と比較して2∼3倍、2.7と比較してやや減

attribute dictionaries

  インスタンス生成を頻繁に行う場合効率化
標準モジュールの改善
decimalの高速化


10進浮動小数点数モジュールdecimalが
C実装により高速化

ベンチマークで10∼100倍程度の高速化
gc.callbacks
 1 import gc
 2
 3
 4 def callback(phase, info):
 5     if phase == 'start':
 6         print('gc start')
 7         print(info)
 8     elif phase == 'stop':
 9         print('gc stop')
10         print(info)
11
12
13 gc.callbacks.append(callback)



$ python3.3 gccallback.py
gc start
{'generation': 2, 'collected': 0, 'uncollectable': 0}
gc stop
{'generation': 2, 'collected': 0, 'uncollectable': 0}
math.log2
             専用関数により精度と速度の改善
 1   import timeit
 2   import math
 3
 4   count = 1000000
 5   x = 10000000
 6
 7   print('log2: {}'.format(math.log2(x)))
 8   print('log : {}'.format(math.log(x, 2)))
 9
10   t = timeit.Timer(stmt='math.log2({})'.format(x), setup='import math')
11   print('log2 time: {}'.format(t.timeit(number=count)))
12
13   t = timeit.Timer(stmt='math.log({}, 2)'.format(x), setup='import math')
14   print('log time: {}'.format(t.timeit(number=count)))



$ python3.3 log2.py
log2: 23.253496664211536
log : 23.25349666421154
log2 time: 0.5322510170008172
log time: 0.9232373659979203
shutil.disk_usage


1 import shutil
2
3 print(shutil.disk_usage('/'))




$ python3.3 diskusage.py
usage(total=250140434432, used=214666657792, free=35211632640)
shutil.get_terminal_size
1 import shutil
2
3 terminal_size = shutil.get_terminal_size()
4
5 print('n'.join(('*' * terminal_size.columns,) * terminal_size.lines))
まとめ
詳しくはwebで



What’s New In Python 3.3
http://docs.python.org/dev/whatsnew/3.3.html

What's New In Python 3.3をざっと眺める