Friday, November 28, 2008

Python 講習会 資料

http://www.unixuser.org/~euske/doc/python/tutorial0917.html

Python 講習会 資料

Version 1.0 (2004年 9月)

対象: ある程度プログラミングの経験がある Java あるいは Perl のユーザ。


概要

  • インタプリタ言語。覚えることは最小限。もとは教育用。
  • Java と Perl の中間? プロトタイプに最適。
  • オープンソース by Guido van Rossum、コミュニティで開発。
  • 高い互換性 - UNIX、Windows、MacOS で動作。
    (Linux 上で開発した cdb を使った検索プログラムや、 スレッド使用の http サーバなどが Windows、MacOSX でも無修正で動いた。)
  • 読みやすいコード、オブジェクト指向、安定動作、豊富なライブラリ。
  • 対話型重視の環境 (オンラインヘルプ、簡易IDE付)
  • 最新バージョンは Python ???. (2004年9月時点では 2.3.4 だったが、現在はもっと上)。
  • ホームページ: http://www.python.org/
  • Python用 IDE 一覧: http://c2.com/cgi/wiki?PythonIde (オープン:7、商用:3、Eclipseプラグイン:1)
  • Python Quick Reference: http://rgruet.free.fr/PQR2.3.html

ソースコード

  • インデントによってブロックを決定する。
  • # はコメント (行末まで)
    #!/usr/bin/env python

    a = 1
    b = 2
    c = a + b

    if c == 3:
    print "correct"
    else:
    print "wrong"

式と演算

  • Python の型:
    • 真理値型 … FalseTrue [2.3以降、それ以前は 0 と 1 で代用]
    • 整数 … 3
    • 実数 … 3.14159
    • 複素数 … 1+2j
    • 文字列 … "abc"
    • Unicode 文字列 … u"日本語"
    • リスト (配列)[1, 2, "z", [3,4]]
    • 辞書 (ハッシュ){"a":1, "b":2}
    • None型 (null)None
    • オブジェクト, 関数
    • Perl と違う: 数値型と文字列型は区別される。 3+"5" → エラー
  • 数値演算
    • C, Java とほぼ同じ: +, -, *, /, %, (), **
    • 三項演算子 ? : はない。
  • 代入文
    • 変数を宣言する必要はない。
    • x = 2
    • y += 1 (y++, y--はない)
    • (a,b) = (b,a) 多重代入

文字列型と Unicode 文字列型

  • 文字列型はただのバイト列 (日本語を認識しない)
  • 文字列定数:
    • 'abc'
    • "abc"
    • """abc
      def"""
      (改行を含められる)
    • \ でエスケープ: '\n', '\020', '\x1a', "I'm \"quoted\"."
  • 演算:
    • "abc" + "def" * 3 → "abcdefdefdef"
    • 切り出し: a = "0 p 1 y 2 t 3 h 4 o 5 n 6"
      • a[0]"p"
      • a[-1]"n"
      • a[2:4]"th"
      • a[1:]"ython"
      • a[:-3]"pyt"
      • a[2:-1]"tho"
    • 変更は不可能 (ハッシュのキーに使えるように)
    • "abc" in s (包含の判定)
    • s.strip() → 先頭と末尾の空白・改行を削除した文字列が新たに返される。 (chomp)
    • s.replace("a", "b") → "a" を "b" に置換した文字列が新たに返される。
    • 正規表現は別の枠組みが必要 (→ 後述)
    • %演算子 (sprintf):
      "x=%d, y=%d" % (x,y) → "x=4, y=5"
  • 数値←→文字列の変換:
    • int("123") → 123 / str(123) → "123"
    • chr(65) → "A" / ord("A") → 65 (文字型と文字列型を区別しない)
  • Unicode型
    • 定数は u"abc"u"あいうえお" のように書く。
    • 内部表現は Unicode を使い、コーデック (codec) によって 入出力時に Unicode型と文字列型とを相互変換する。
      (日本語codec は http://www.python.jp/Zope/download で配布、 Python2.4 から日中韓国語の codec が標準装備)
    • 文字列型との相互変換: s.encode("shift_jis") → Shift JIS で表現したバイト列。
    • str() でも文字列に変換できる: EUC-JP がデフォルトなら、
      str(u"あ") → '\xa4\xa2' / unicode('\xa4\xa2') → u'あ'
    • ソースコードのエンコーディングは最初のコメントで判定される:
      #!/usr/bin/env python
      # encoding: shift_jis
      print u'この文字列定数はシフトJISとして解釈されます'

制御構造

  • if, for, while だけ。(break, continue)
  • 字下げが必要。
    if a == b:
    print "equal"
    else:
    print "not"

    n = 1
    while n < 100:
    print n
    n *= 2

    for i in [1,2,3,4,5,6,7,8,9,10]: Perl の foreach に相当する
    if i == 5:
    break
    print i
  • 比較演算子: ==, !=, <=, < , >=, >, in
  • Java と違うもの: &&, ||, ! → and, or, not
  • Java にないもの: in

入出力

  • ファイルオブジェクトを操作する:
    • fp = file("/etc/hosts", "r")
    • fp.read(n) → ファイル全部を文字列で返す。
    • fp.readline() → ファイル1行を返す。(終端は '')
    • fp.close()
    • fp2 = file("/tmp/x", "w")
    • fp2.write("write")
  • デバッグ用出力: print (改行する)
    • print x
    • print "x=", x, "y=", y
    • print >>fp, "write" (改行が入るので注意)
    • print "name=%s, age=%d" % (name, age)

例外処理

  • Perl と違う: ちょっとしたことでも頻繁に例外が出るのでキャッチしなければならない。
  • try: ~ except: でキャッチ。
    try:
    fp = file("/etc/nosuchafile")
    except IOError:
    print "cannot open"
  • raise で送出。
  • IndexError, KeyError, ValueError, IOError などがある。
  • 自作のクラスを例外として使用可。

リストと辞書

  • リスト (配列):
    • a = [1,2, "abc", 4]
    • b = [2, [3], [[4], []]]
    • a[0], a[-1], a[2:4], a[1:], a[:-3], a[2:-1] (文字列と同様)
    • a[:] (コピーされたリスト)
    • [1,2] + [3,4] * 2 → [1,2,3,4,3,4]
    • a.append(5) (末尾に要素 5 を追加)
    • a.extend([6,7]) (末尾に要素 6 と 7 を追加 - a.append([6,7]) とは異なる)
    • a.insert(0, 7) (先頭に要素 7 を追加)
    • del a[3] (3番目の要素を削除)
    • a.reverse() (反転、a は上書きされる)
    • a.sort() (ソート、a は上書きされる、自前の比較関数を書くやり方は → 後述)
    • x in y → x が y の要素に含まれているかどうか (線型探索)
    • range(10) → [0,1,2,3,4,5,6,7,8,9] (for で使用)
    • "a b c".split(" ") → ["a", "b", "c"]
    • ", ".join(["a", "b", "c"]) → "a, b, c"
  • 辞書 (ハッシュ)
    • d = {}
    • d = { "a":2, "b":4 }
    • d["a"] = 1
    • del d["a"]
    • "a" in d → "a" が d のキーに含まれているかどうか
    • d["x"] 該当するキーがない場合は KeyError 例外になる。
      try:
      x = d["x"]
      except KeyError:
      print "x is not found"
    • d.get("x", 0)
    • d.keys(), d.values()
    • 文字列以外の型でもキーにできる。(ただし変更不可能であること)

関数定義と呼び出し

  • 関数定義
    def func(x, y, z=0):
    return x*x+y*y+z*z
  • 呼び出し: func(3,4) → 25, func(3,4,5) → 50
  • 関数もオブジェクトである:
    def func(): ...
    print func(3,4,5)
    a = func
    print a(3,4,5)

    def loaddata(): ...
    def savedata(): ...
    def exitit(): ...
    menu = {"load":loaddata, "save":savedata, "exit":exitit}
    f = menu[choice]
    f()

    def mycompare(a,b):
    return cmp(len(a), len(b))
    a = ["abc", "de", "x", "yyyy"]
    a.sort(mycompare)

オブジェクト指向

  • Person オブジェクトの定義:
    class Person:

    # コンストラクタ: Person(name,age)
    def __init__(self, name, age):
    self.name = name
    self.age = age
    return

    def __repr__(self):
    return '' % (self.name, self.age)

    def display(self, out):
    out.write("Name: %s\n" % (self.name))
    out.write("Age: %d\n" % (self.age))
    return

    obj = Person("Shinyama", 29)
    print obj
    obj.age = 30
    obj.display(fp)
  • Java と違う: self が必要! (Java の this に相当する)
  • obj.method(a,b,c)method の第一引数 selfobj が渡される。
  • コンストラクタ: __init__(self)
  • 文字表現: __repr__(self) デバッグに便利

リスト操作いろいろ

  • 内包表現
    • a = [ n*n for n in range(5) ] → a = [1, 4, 9, 16, 25]
    • ", ".join([ "%s='%s'" % (k, d[k]) for k in d.keys() ])
  • イテレータ (リストのように扱えるがメモリ消費しない)
    • 整数: xrange(1000000)
    • 辞書: dic.iterkeys(), dic.itervalues()
    • ファイル: fp.xreadlines()

ライブラリ (モジュール) を使う

  • モジュールもオブジェクト: 関数や変数を格納した、単なる「でっかいクラス (構造体)」でしかない。
    アクセスする文法はクラスと一緒。
  • importfrom:
    import math
    print math.log(2)
    print math.pi

    from math import log
    print log(2)

    (from math import log はじつはこれと同じ)
    import math
    log = math.log

    (正規表現を使う)
    import re
    pat = re.compile("([a-zA-Z]+)=([0-9]+)")
    m = pat.search("a=123")
    print m.group(1), "=", m.group(2)

    (dbファイルを使う)
    import dbm
    mydb = dbm.open("mydb", "n")
    mydb["abc"] = "xyz"
    mydb["123"] = "456"
    mydb.close()
  • dbm、(g)zip、csv、base64、popen
  • http (クライアント/サーバ), ftp, smtp, pop3, imap, ssl 関連
  • htmlパーサ、xmldom、xmlrpc、email 処理

ライブラリ (モジュール) を作る

  • ファイル名 mylog.pymylog というモジュール名をもつ:
    #!/usr/bin/env python

    import math

    def log2(x):
    return math.log(x) / math.log(2)

    if __name__ == "__main__":
    print "log2(10)=", log2(10)
  • 使い方 :
    import mylog
    print mylog.log2(10)
    from mylog import log2
    print log2(10)
  • モジュール中のすべての文は実行され、def で関数定義される。
  • mylog.py が直接実行された場合、if __name__ == "__main__": の中が実行される。
  • ディレクトリもまた構造体と同じ扱い。mylibs/mylog.py 中にある log2 という関数 (または変数) は mylibs.mylog.log2 という名前でアクセスできる。
  • モジュール探索時に環境変数 PYTHONPATH をさがす。

すてきな機能

  • 補完機能 (tab)
  • オンラインヘルプ
    >>> import urllib
    >>> help(urllib)
    ...
    >>> help(urllib.urlopen)
    ...
  • pickle - オブジェクトを文字列表現に変換、ファイルに保存できる。
  • Tkinter - プラットフォーム独立の GUI
    import Tkinter

    def action1():
    print "boo!"
    b = Tkinter.Button()
    b["text"] = "Hit Me"
    b["command"] = action1
    b.pack()
    Tkinter.mainloop()
  • Jython - Java で動く Python 実装。Java のライブラリが使える。じつは CPython より速い
    from java.applet import Applet

    class HelloWorld(Applet):
    def paint(self, g):
    g.drawString("Hello from Jython!", 20, 30)
  • IronPython - .NET 上の実装。これも CPython より速い

結論

  • web クローラ: 100~500行
  • 形態素解析器: 150行
  • sample.py
  • Total Cost of Development: Python + Java <>

No comments: