プログラマのためのPython入門

このドキュメントは

こちらのサイトのクローンです。

以前、非常に有用な Python 入門サイトがあったのですが、しばらくしたら、サイトが削除されており、非常に残念な思いをしたことがありました。なので、個人保管用として、保存しております。

このサイトは、私個人が、自宅と、会社で同じ情報を閲覧することを目的とし、WWWに公開しています。


PythonプログラミングプログラマのためのPython入門

このドキュメントの目的

他言語で作業している同僚プログラマに自分が Python で記述したプログラム
引き継いでもらうための手ほどきを主な目的とする。

プログラムについての理解はあるものとし、 Python 独特の部分を中心に解説する。

筆者の主観で考えて、一般的にあまり問題にならないであろう細かい点については言及しない。

今すぐ使えて楽に整形できるエディタとしてはてなダイアリーがあったので利用する。

とっかかり

Python 開発環境の導入(Windows)

http://www.python.jp/Zope/download/pythoncoreWindowsインストーラ(msi)を実行してインストール

最新のもので OK だが目的によってはバージョン 2.5, 2.4 が対応していないこともあるので注意。

拡張子 py, pyw を python.exe に関連付けしてくれるので以後はスクリプトダブルクリックしたり、

コマンドプロンプトからスクリプトファイル名を入力するとそのまま実行される。

Python スクリプトの記述

Python の基本はユニコードである。しかし現在扱っているテキストはまだ Shift JIS が多い。

Python のコード中に日本語文字列を記述するときには先頭に以下の1行を置いておく。

# coding: shift_jis

Windows で作業する場合はこの行が必ずファイルの先頭行に来るようにする。

ファイル内容を解説したコメントなどを数行置いてその下に記述するというようなことは出来ない。

以下は悪い例。

#========================================================

# hoge.py  by uyamae
# This is simple sample of Python script.
#========================================================
# coding: shift_jis

行の中の半角の # 以降はコメントとなる。

コメントにだけ日本語を使う場合でも前述の # coding: shift_jis は必須である。


Python は、文の終わりのセミコロンが不要。ただし、セミコロンをつけてもかまわない。

基本的に1行がひとつの文となる。セミコロンをつけると1行に二つ以上の文を置くことが出来る。

逆に、行の最後に半角の \ をおくと改行が無視され複数の行にわたってひとつの文を置くことが出来る。

print "a"

print "b";
print "c"; print "d"
print "e" \
+"f"

今後の予定

PythonプログラミングプログラマのためのPython入門(2)

Python 実行環境の補足

コマンドラインから python.exe を実行するとインタラクティブモードで起動する。

>>> というプロンプトから直接 Python の文を入力して結果を表示できる。

複数行にわたると python.exe が解釈した場合、二行目以降ではプロンプトが ... に変わる。

インタラクティブモードを終了する場合は >>> のプロンプトで Ctrl+Z を入力して Enter.

C:\python>python
Python 2.5 (r25:51908, Sep 19 2006, 09:52:17) [MSC v.1310 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> print 0
0

>>> print """test
... string"""
test
string
>>> ^Z

C:\python>

Python でクラスや関数の使い方が分からない場合は属性*1を表示する dir が使える。 dir変数にも使える。

関数の使い方を知りたい場合には help が使える。

>>> f=open("sample.txt")
>>> dir(f)
['__class__', '__delattr__', '__doc__', '__enter__', '__exit__', '__getattribute__', '__hash__', '__init__',
 '__iter__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', 'close', 'closed',
 'encoding', 'fileno', 'flush', 'isatty', 'mode', 'name', 'newlines', 'next', 'read', 'readinto', 'readline',
 'readlines', 'seek', 'softspace', 'tell', 'truncate', 'write', 'writelines', 'xreadlines']
>>> help(f.write)
Help on built-in function write:

write(...)
    write(str) -> None.  Write string str to file.

    Note that due to buffering, flush() or close() may be needed before
    the file on disk reflects the data written.
>>>

文字列・配列連想配列

文字列

Python で文字列を作成する場合にはシングルクォート、ダブルクォート、または三連クォートで文字列をくくる。

三連クォートの文字列は、改行を含むことが出来る。三連クォートに使うのはシングルクォートでもダブルクォートでもかまわないが当然対になっている必要がある。

print 'single quat'
print "double quat"
print """triple

quat"""
single quat
double quat
triple
quat

※補足 Python の print は末尾に改行を付与する。改行したくない場合は文字列の後にカンマをつける。

print 'text 1'

print 'text 2\n'
print 'text 3',
print 'text 4'
text 1
text 2

text 3 text 4

Perl とは違ってシングルクォートとダブルクォートに違いは無く、シングルクォート中でも半角 \ によるエスケープは有効*2

Perl のシングルクォートの文字列に相当する(エスケープを無視する)ものとして、半角 r を文字列に付与する方法がある。

この方法はシングルクォート、ダブルクォート、そして三連クォートでも有効である。

print 'single\tquat'
print "double\tquat"

print """triple\tdouble
quat"""
print r'single\tquat'
print r"double\tquat"

print r"""triple\tdouble
quat"""
single	quat
double	quat
triple	double
quat
single\tquat
double\tquat
triple\tdouble
quat

Python で C の printf 相当のことをする場合には、文字列フォーマットを使用する。

利用できる書式変換は C とだいたい同じである*3

文字列フォーマットの構文は printf とは異なる。以下の C のコードと Python のコードが同じ文字列を出力する。

printf("%d %u %.1f %s\n", 1, 2, 3, "ダー");
print "%d %u %.1f %s" % (1, 2, 3, "ダー")

Python の文字列は、加算と乗算が可能*4。加算は文字列の連結、乗算は文字列を繰り返して連結する。

配列

Python配列と呼べそうなものにはリストとタプルの2つがある。

リストは1次元の可変長配列として扱える。しかし、自動的に拡張はしない。

リストを作成するときは、要素をカンマで区切り [ ] でくくる。

それぞれの要素に型はなく、リストの要素としてリストを含むことも出来る。

a=[0, 'a', [1, 'b']]
print a[0]
print a[1]
print a[2]
print a[2][0]
print a[2][1]
0
a
[1, 'b']
1
b

タプルもリストとだいたい同じだが、要素が変更できない。タプルは要素をカンマで区切り ( ) でくくる。

a=[0, 'a', [1, 'b']]
a[1]='b'   # OK

t=(0, 'a', [1, 'b'])
b[1]='b'   # エラー
b[2][0]=0  # これは OK

リスト、タプルの要素数を知るためには組み込み関数 len を使用する。

>>> a=[0, 'a', [1, 'b']]
>>> print len(a)
3

リスト、タプルの添え字は 0 から始まる。また、負の数も利用できる。

負の数を指定した場合、末尾から数えてアクセスできる。-1 を指定すると一番最後の要素にアクセスできる。

>>> a[0, 'a', [1, 'b']]

>>> print a[-1]
[1, 'b']

リスト、タプルの一部を取り出すために、スライスが利用できる。

スライスの構文は、リスト、タプルの添え字の部分にコロンで区切った二つの値を指定する形になる。

コロンの前の数字はスライスに含まれる範囲の先頭インデックスである。

コロンの後ろの数字はスライスに含まれる範囲の最後の要素の次のインデックスである。

>>> a=[0, 1, 2, 3, 4]
>>> a[1:4]
[1, 2, 3]
>>> a[-1:-4]
[]
>>> a[-4:-1]
[1, 2, 3]

二つの値はそれぞれ省略可能で、前の値を省略すると 0 として扱われ、

後ろの値を省略すると指定の位置より後ろ全てがスライスの範囲に含まれる。

>>> a[:3]
[0, 1, 2]

>>> a[3:]
[3, 4]
>>> a[-1:]
[4]
>>> a[:-1]
[0, 1, 2, 3]
>>> a[:]
[0, 1, 2, 3, 4]

スライスでは、リストからは新たなリスト、タプルからは新たなタプルが得られる。

それぞれはもとの配列のある範囲を要素とした新たなオブジェクトになる。

つまりリストからスライスされた新たなリストを変更しても元のリストは影響を受けない。


文字列もリストと同じような要素アクセスができる。

たとえば以下のようにして部分文字列を作ることが出来る

>>> s="test string"
>>> print s[-5:]
tring

文字列オブジェクト[開始インデックス:終了インデックス]
str = "ABCDE"

slice = str[1:3]    # "BC"

連想配列

Python には Perl連想配列に似た辞書がある。

辞書は、文字列など*5を添え字とした配列のようなものである。

辞書の添え字をキーと呼ぶ。辞書を作成するときには、キーと値をコロンで対応付けた要素を

カンマで区切ってならべて { } でくくる。

辞書は代入操作では自動的に拡張されるが、値を参照するだけの場合は自動的に拡張されない。

d={'one':1, 'two':2, 'three':3}

print d['one']     # 1 が表示される
d['four']=4        # キー'four'とそれに対応する値 4 が辞書に追加される
print d['five']    # エラー

辞書にあるキーが存在するかどうかを調べたい場合には、関数 has_key が利用できる。

>>> d={'one':1, 'two':2, 'three':3}
>>> d.has_key('one')
True
>>> d.has_key('four')
False

また、関数 keys, values, items でそれぞれ辞書に含まれるキーのリスト、値のリスト、

キーと値の対を含むタプルのリストが得られる。

>>> d={'one':1, 'two':2, 'three':3}
>>> d.keys()
['three', 'two', 'one']
>>> d.values()
[3, 2, 1]
>>> d.items()
[('three', 3), ('two', 2), ('one', 1)]

今後の予定

*1C++ のクラスのメンバ変数とメンバ関数を合わせたもの、あるいは Java のメソッドとフィールドをあわせたものと思ってください

*2:また C/C++ とは異なり 'a' は「 a という文字」ではなく「a」一文字の文字列である。

*3:筆者が今までに C と同じ感覚で使用して困ったことがない程度には同じです

*4:加算に見える書き方と乗算に見える書き方が可能というほうがより正確

*5ハッシュ可能なオブジェクト。タプルも使えるみたいです。

PythonプログラミングプログラマのためのPython入門(3)

ブロック・フロー制御・変数のスコープ

ブロック

C/C++Perl ではブロックは { } でくくるが、

Python ではインデントでブロックを決める。

同じインデントの連続した行がひとつのブロックとなる。

if cond:
    ret_code=1  #┬この2行が同じブロック
    print "ok"      #┘
else:
    ret_code=2  #┬この2行が同じブロック
    print "NG"     #┘

Python で一般的なインデントは半角スペース 4 つだが、

タブや任意の数の半角スペースでもかまわない。

ただし、コード中でインデントを混在させることは出来ない。

最初のインデントが半角スペース 4 つであれば、それ以降の

すべてのインデントはこれに従う必要がある。

インデントが2段ならば半角スペース 8 つ、3段ならば 12 個となる。

ブロック中には空白文字しか含まない行をはさむことが出来る。

if ret_code>0:
    print "ok"                         #                          ┬ if ret_code>0 のブロック
    if ret_code==1:                   #                          |

        print "ret_code is 1."         # if ret_code==1 のブロック|
    else:                              #                          |
        print "ret_code is not 1."     # else のブロック          |

# コメントをおいても空白行とみなされる #                          |
    print ret_code                     #                          ┘

フロー制御

Python では、if-elif-else、while、for が使える。

if-elif-else

if の構文は以下の通り。

if 条件1:
    条件1が真の場合の処理
elif 条件2:
    条件2が真の場合の処理
else:
    すべての条件に当てはまらない場合の処理

C/C++ のように条件を ( ) でくくる必要はなく、

条件の後にコロンを付与する。

if 文の最後のブロックの終わりは、

次の行のインデントで見分ける。

if cond:
    print 0  # if cond のブロック
print 1      # if cond のブロックではない
while

while の構文は以下の通り。

while 条件:
    条件が真の場合に繰り返す処理

while を途中で抜けたい場合には break が使える。

for

for は Perl の foreach に近い。

for 変数 in イテレータ:
    各変数に対する処理

イテレータは次々と要素を提供するオブジェクトである。

リストはイテレータとして使われる機会が非常に多い。

また、辞書の各要素を処理する場合も多い。

>>> a = [0, 1, 2]

>>> for x in a:
...     print x
...
0
1
2
>>> d = {"a":0, "b":1, "c":2}
>>> for v in d.values():
...     print v
...
0
1
2

C/C++ の for 文のような使い方をしたい場合は、

range() を使用する。 range は 0 から始まり、

指定された数の要素を含むリストを返す*1

>>> for x in range(3):
...     print x
...
0
1
2

変数のスコープ

Python変数は宣言の必要は無く、値を代入した時点で作成される。

if や while, for のブロック中で作成した変数には

そのブロック以降でもアクセスできる。

しかし、すでに存在している変数と同名のブロックローカル

変数は作成できない*2

if True:
	x = 0
print x  # OK

y = 0
if True:
	y = 1
print y  # 1 を出力

今後の予定

*1:始めの数やいくつずつ増えるかを指定することもできる

*2:ブロックローカル変数というのが無い

プログラミングPythonプログラマのための Python 入門(4)

ファイルアクセス

ファイルを開くときには組み込み関数 open を使用する。

開くときにはモードを指定できる。省略時はテキスト読み込みモードになる。

open はファイルオブジェクトを返し、開く以外のファイル操作は

ファイルオブジェクト関数を利用する。

f=open("readme.txt")        # テキスト読み込み
print f.readline()          # 一行読み込んで表示

print f.tell()              # 現在の読み込み位置を取得して表示
f.seek(0, 0)                # ファイルの先頭に戻る
f.close()                   # ファイルを閉じる

f=open("readme.txt", "wb")  # バイナリ書き込みモード

f.write("test text\n")      # 文字列を書き込む
f.close()                   # ファイルを閉じる

補足:モジュールの利用

Python では標準ライブラリなどをモジュールとして提供している。

モジュールを利用するためには import する。

import の形態には以下のようなものがある

import sys                      # sys モジュールを利用可能にする
from os import path             # os モジュールから path を取り込む

from csv import *               # csv モジュールに含まれる全てを取り込む
import StringIO as sio          # StringIO モジュールに sio という別名をつけて利用可能にする
# 以上の import の結果以下のような利用が可能になる

p=path.join("dir", "file.csv")  # os.path.join に左の形式でアクセスできる
r=reader(open(p))               # csv.reader にモジュール名の csv を省略してアクセスできる
buf = sio.StringIO()            # StringIO.StringIO に左の形式でアクセスできる
sys.exit(0)                     # sys モジュールの関数に左の形式でアクセスできる

補足:ポリモーフィズム&ファイル風オブジェクト

C++Java のオーバーライドと違って、(C++ で言うところの)シグネチャ*1が一致すれば

関数は利用可能である(継承などは必要ない)。

変数の型が無いので最低限関数名と引数の数が合致すれば良い。

StringIO モジュールの StringIO はファイル風オブジェクトを返す。

このファイル風オブジェクトはファイルと同じインターフェースを持ち、

メモリ上にその内容を保持する。

import sys
from StringIO import StringIO

# 関数定義
def copy(src, dst, tmp):
    src=open(src)
    for text in src:
        tmp.write(text)
    src.close()
    tmp.seek(0, 0)
    dst=open(dst, "w")
    for text in tmp:
        dst.write(">%s"%text)
    dst.close()

# StringIO を利用
buf=StringIO()
copy(in_file, out_file1, buf)
# 読み書き両用で開いたファイルを利用
buf=open(tmp_file, "w+")
copy(in_file, out_file2, buf)
buf.close()

というようにメモリ上に置く一時ファイルといった使い方が出来る。

また上記コードの tmp は読み書き両用で開いたファイルオブジェクトと容易に

交換が可能である。

コマンドプロンプトからの実行(プログラム引数アクセス)

コマンドプロンプトから実行した場合の引数は、sys モジュールのリスト argv に格納されている。

argv[0] には実行しているスクリプトファイル名が入り、 argv[1] 以降に引数が含まれる。

また、__name__ という変数にはモジュール名が含まれる。コマンドプロンプトから呼び出された

スクリプト中ではこの内容が "__main__" になり、これを利用して以下のようなコードがよく書かれる。

*2

# coding: shift_jis
# test.py
# 関数定義
def func(x):
    print x*x

# このモジュールがコマンドプロンプトから直接呼び出された場合に以下を実行
if __name__=="__main__":
    import sys
    if len(sys.argv)>1:
        func(int(sys.argv[1]))
>pytohn test.py 2
4
>python
>>>import test
>>>test.func(2)
4

今後の予定

*1関数名と引数の型、数、戻り値の型の組み合わせによる関数を一意に識別するためのもの

*2関数定義、モジュールに関しては解説の順序が前後するが使い方はなんとなくわかってもらえることを期待します

プログラミングPythonプログラマのための Python 入門(5)

関数・クラス(1)

関数定義

Python関数を定義するときには def を使う。

def 関数名(引数,[引数, ...]):
    定義

引数

Python関数引数は通常のもののほかに、デフォルト値付き、任意引数リスト、

キーワード引数がある。通常の引数関数呼び出しで渡された値を順に受け取る。

def sum(a, b):
	print "%d+%d=%d"%(a,b,a+b)

sum(1, 2)

1+2=3

デフォルト値付き引数は、関数呼び出し時に省略可能で、その場合デフォルト値が使用される。

またデフォルト値付き引数は、関数呼び出し時に値の代入先引数を明示的に指定することができる。

代入先引数を明示的に指定する場合は、指定しないものより後ろにおく必要がある。

デフォルト値付き引数は、通常の引数より後ろにおく必要がある。

def func(a, b=0, c=1):
	print a, b, c

func(0, 1, 2)    # 普通に呼び出す

func(1)          # デフォルト値付き引数を省略
func(2, c=3)     # 値の代入先引数を明示的に指定

func(1, b=2, 3)  # こういう書き方は NG
0, 1, 2
1, 2, 1
2, 0, 3

任意引数リストは C の可変個引数関数のようなものだが python のリストとして

引数を受け取れるのでより扱いやすくなっている。

任意引数リストは引数の前に * (アスタリスク) をつけて宣言する。

任意引数リストは通常の引数デフォルト値付き引数より後ろにおく必要がある。

def func(a, b=0, *c):
	print a, b,
	for x in c:
		print x,
	print ""

func(0)             # デフォルト値付き引数省略、任意引数リスト無し

func(0, 1)          # 任意引数リスト無し
func(0, b=2)        # 代入先を明示的に指定
func(0, 1, 2, 3)    # a, b に対応する引数より後ろは任意引数リストに入る。

func(0, b=1, 2, 3)  # こういう書き方はできない
0, 0
0, 1
0, 2
0, 1, 2, 3

キーワード引数は、辞書版任意引数リストといえるものである。

キーワード引数引数の前に ** をつけて宣言する。

キーワード引数は通常の引数デフォルト値付き引数、任意引数リストより後ろにおく必要がある。

func(a, b=0, *c, **d):
	print a, b,
	for x in c:
		print x,
	for k, v in d.items():
		print k, v,
	print ""

func(0)                     # 省略できる部分を全て省略
func(0, 1, 2, 3, x=4, y=5)  # 2, 3 が任意引数リストに、x=4, y=5 がキーワード引数の辞書に入る。

func(0, 1, 2, 3, x=4, 5)    # キーワード引数のあとに明示的な指定の無い引数は渡せない。
func(0, 1, 2, 3, a=4, b=5)  # 他の引数の名前になっているものはキーワードとして使用できない。
0, 0
0, 1, 2, 3, x, 4, y, 5
戻り値

Python関数戻り値はひとつだが、タプルを利用して複数の引数を返すような書き方もできる。

def func(a, b)
	return a+b, a-b, a*b, a/b

a, s, m, d = func(8, 3)
print a, s, m, d
11, 5, 24, 2

この場合、関数 func の return で、カンマで列挙された値がタプルとしてまとめられて

関数戻り値となり、その戻り値は呼び出し側でカンマで列挙された変数に展開して代入される。

ジェネレータ

ジェネレータは関数と同様の形式で定義し、呼び出すことでイテレータを生成する。

具体的には、ジェネレータは内部で yield を使用している関数である。

yield は、関数の実行を一時中断して呼び出し元に値を返す。そして値が要求されたとき

続きから処理を再開する。

def add(numbers):
	sum = 0
	for x in numbers
		sum += x
		yield sum


for x in add([1,2,4,8,16]):
	print x
1
3
7
15
31

今後の予定

プログラミングPythonプログラマのための Python 入門(6)

一月も開いてしまうとは予想外でした。

書きかけテキストが消えたのが10%くらい、残りはモンスターハンターのせいです。

関数・クラス(2)

クラスとインスタンス

クラス、インスタンスは一般的なオブジェクト指向言語と同じ考え方(クラスは設計図であり、

インスタンスはそれを元に生成された個々の製品である、のような)で取り扱うことが出来る。


クラス定義

Python でクラスを定義するときの構文は以下の通り。

class クラス名(基本クラス):
    定義

基本クラスは省略可能だが、特別に指定したいクラスが無い場合には

クラス object を指定することが推奨されている。

「定義」の部分ではメソッドやクラスのアトリビュートを定義する。

メソッド

クラスのメソッドは C++ のクラスのメンバ関数に相当する。クラスのメソッドの定義は

通常の関数とほぼ同じだが、引数リストの先頭に特殊な引数 self を追加する必要がある。

self は C++ の this ポインタのようなもので、クラスメソッドに暗黙に渡され、

インスタンスごとのアトリビュートを保持する。

class Foo(object):
    def __init__(self, x):
        self.x = x
    def echo(self):
        print self.x

f = Foo(0)    # Foo.__init__ が呼び出される

f.echo()
0

上記のように、実際にクラスのメソッドを呼び出す場合には self を渡す必要はない。

上記のコードのクラス Foo のクラスメソッド __init__ は C++コンストラクタのように

インスタンスが生成されるときに呼び出される。

インスタンスアトリビュート

インスタンスアトリビュート(属性)は C++ のクラスのメンバ変数に近い。

しかし、前節のコードの __init__ に見られるように宣言は必要なく、

*1を渡すことで自動的に生成される。

また、後から任意にアトリビュートを追加することができる。

class Foo(object):
    def __init__(self, x):
        self.x = x
    
    def echo(self):
        print self.x, self.y

f = Foo(0)

# ここで f.echo を呼び出すとエラー
f.y = "abc"    # 合法
f.echo()
0 abc

ただしバグの元となるのでインスタンスの外側からアトリビュートを追加することは避けたほうが良い。

クラスのアトリビュート

クラス定義の、メソッド定義ではない場所で定義されたアトリビュート

クラスに属するアトリビュートとなる( C++ のクラスの static メンバ変数に近い)。

このアトリビュートにはクラス名.アトリビュートアクセスすることが出来る。

C++ の static メンバ変数と違い、クラスのメソッド内からアクセスする場合にも

クラス名を省略することは出来ない

class Foo(object):
    value=0
    def echo(self):
        print Foo.value    # Foo. を省略するとエラー

今後の予定

*1:実際にはオブジェクトの参照

PythonSQLPythonSQLiteMySQL

Pythonデータベースを扱いたくて、最初は MySQL を考えたのですが

導入部で躓いてお手軽な SQLite を選択し、いじり始めたのですが、

SHOW FIELDS が出来ないようなので、結局また MySQL にチャレンジ。

前に探したときにはなぜかたどり着けなかった MySQL のパッケージを今度は

いともたやすく発見できてしまったためインストールしてぼちぼちといじっています。

検索キーワードは MySQLdb で。


Pythonメモ

型の比較

import types
a = 'string'
if type(a) == types.StringType:
  print 'yes'
else:
  print 'no'

type()で型が取得できる。typesモジュールにはシステム定義型の値が用意されている。

文字列型
unicode型あるいはstr型であるかどうかは、basestringを使うと判定できる。
a = 'hello'
b = 150
c = u'漢字'
isinstance(a, basestring) → True
isinstance(b, basestring) → False
isinstance(c, basestring) → True
basestringは、ビルトイン関数として定義されているが、呼び出したり、インスタンス化することができない。


ジェネレーター関数(generator function), yield文


generator functionを定義するときに使う。逆に関数を定義するときにyield文を使うと、その関数はgenerator functionとなる。

generator functionを呼び出すとgeneratorと呼ばれるiteratorが返される(実際の型はgenerator型)。以降の操作は、このgeneratorのメソッドを呼び出して行う。コードの実行は、yield文が現れるまで行われる。


generator functionの中身はgeneratorのnext()メソッドを呼ばれたとき実行される。つまりgenerator functionが呼ばれた時点では中身は実行されない。

yieldが呼ばれたところで、実行が止まった形になる。遅延評価の形になる。generator functionのローカル変数はその間も保たれる。

ジェネレーター関数が使われるケース

呼び出す度にフィボナッチ数を1つずつ返すような場合。

ファイルからひとかたまりのデータを読み込み、その処理が終わったらまた次のひとかたまりのデータを読み込み処理したい場合、理想的にはデータの読み込みと、そのデータの処理を切り離して書けると嬉しい。こんな場合にジェネレーター関数が役に立つ。

8進数/16進数からの変換

int('10', 8) → 8
int('0a', 16) → 10

リスト操作

リストの要素をinsert

0番目の要素の前に'new'を入れる
mylist = ['a','b','c']
mylist.insert(0, 'new')

リストの要素を消す
del a[0]
del a[2:4]

配列を初期化する
ary = 38 * [None]
なんか効率悪そう。

リストの各要素に対し一括処理を行う

map()ビルトイン関数を使う。
numbers = [1,2,3,4,5]
map(str, numbers)
→['1','2','3','4','5']
map()は、str(x)をnumbersの各要素をxとして実行し結果をリストとして生成する。

ちょっと変わった処理をしたいなら、str()の代わりにラムダ関数を使う。
numbers = [1,2,3,4,5]
map(lambda x:x+1, numbers)
→numbers = [2,3,4,5,6]

実行ユーザーの取得

uidを取得するだけなら、
import os
print os.getuid()
ユーザー名を取得するなら
import pwd, os
print pwd.getpwuid(os.getuid())[0]

辞書の操作

便利なupdateメソッド
a = {1:'A', 2:'B'}
b = {2:'C', 3:'D'}
a.update(b)

a -> {1:'A', 2:'C', 3:'D'}


os.system()で使用されるPATHを変更する

os.system()は環境変数を参照するので、環境変数PATHを変更すれば良い。
import os
os.system('echo $PATH')
os.environ['PATH'] = ''
os.sytem('echo $PATH')


Unicode/日本語

str = unicode('EUC文字列', 'japanese.euc_jp')
for c in str:
  print type(c), c.encode('japanese.euc_jp')
この例では、ソースコードをEUCで書いたり、外部からのデータをEUC-JPで渡したりする場合を想定している。

変数strはunicode型の文字列で、unicode()を使って生成している。
unicode型の文字列では、漢字1文字も1文字として扱われる。出力時には、encode()メソッドを使う。ここではEUC-JPに変換して出力している。

% python gaku2.py
<type 'unicode'> E
<type 'unicode'> U
<type 'unicode'> C
<type 'unicode'> 文
<type 'unicode'> 字
<type 'unicode'> 列

unicode型だとはいっても、UTF-8なわけではない。unicode型をUTF-8で出力するには、str.encode('utf-8')としなければならない。


try〜finally

try:
  statement A
finally:
  statement X
statement Xは、tryの中で例外が発生した場合も、しなかった場合も実行される。
実行のタイミングは、例外がない場合はtry節処理の直後、例外が発生した場合は、
例外発生直後で、finally節を実行した後、もとの例外が再度発生させられる。


スタックの表示

import traceback

def foo(a):
  print traceback.print_stack()
で一応表示できる。詳細は、Python.orgのtracebackモジュールを参照。


メソッド呼び出し

Pythonメソッド呼び出し

時間関連

現在時刻を取得する
time.time()
-> 1037158902.56

実数で返ってくるので、丸めると良い。
now = int(time.time())

年月日や時刻を特定の形式で表示したい
time.strftime("%T", time.localtime(time.time()))

時刻を表す値を生成したい
int(time.mktime((year, month, day, 0, 0, 0, 0, 0, -1)))
mktimeは、9つの要素を持つtupleを引数に取る。デイライトセービングは無視してよければ最後の要素は-1。やはり値は実数なので丸めるのもよし。

<

文字列

文字列の置換
string.replace()を使う。

"//"を"/"にする。
import string
str = "/hello/world//from/Japan/"
newstr = string.replace(str, '//', '/')

文字列の連結
a = "hello"
b = "world"
c = a + " " + b
cは"hello world"となる。

文字列のフォーマット
first ='Gaku'
last = 'Ueda'
str = 'My name is %(first)s %(last)s.' % vars()
vars()は、現在のシンボルテーブルをdictionaryとして返す。
カッコ内の名称と変数名が関連づけられ、値割り当てができる。

クラス内であれば、vars(self)とすれば、メンバ参照ができる。
class abc:
  def __init__(self):
    self.member1 = "HELLO"
    self.member2 = "WORLD"
  def doSomething(self):
    print "%(member1)s and %(member2)s" % vars(self)

行末の改行を落とす
import string
line = string.rstrip(line)

文字コードの取得
a = "hello" b = ord(a[0]) 先頭の文字は、文字列a[0]でアクセスできる。組み込み関数ord()で文字コードに変換できる。 逆に文字コードから文字を得るにはchr()を使う。 chr(b + 1)


ファイル

Windowsでファイルを一気に読み込む。
fp = open(filename, 'rb')
data = fp.read()
'r'の代わりに'rb'としていしないとWindowsでは、バイナリファイルを一気に読み込むことはできない。UNIXの場合には特に必要はない。

ファイルの末尾から128バイト読み込む
fp = open(filename, 'r')
fp.seek(-128, 2)
bytes = fp.read(128)
seekの第2引数の2は、ファイルの末尾をオフセットとする。-128でそこから128バイト戻す。

リネーム: os.rename()を使う
import os
os.rename(newname, oldname)

存在チェック: os.access()
import os
os.access('/etc/rc', os.F_OK)

標準入力から1行ずつ読み込む
import sys
while 1:
  line = sys.stdin.readline()
  if not line:
    break
  sys.stdout.write(line)
lineには改行文字も含まれる。

特定のパターンのファイル名の取得
import glob
files = glob.glob('dat/2003*')
for f in files:
  print f
とすると、filesは、['dat/20030811', 'dat/2003/0812']といったような結果となる。

ファイルへの書き込み
f = open('filename', 'w')
f.write("hello\n")
f.close()

複数のプロセスから1つのファイルに書き込む
import fcntl
import sys, time

while 1:
  file = open('/tmp/locktest', 'a')
  fcntl.lockf(file.fileno(), fcntl.LOCK_EX)
  file.write("from %s" % sys.argv[1])
  time.sleep(1)
  fcntl.lockf(file.fileno(), fcntl.LOCK_UN)
  file.close()


演算

整数切り上げ
import math

f = 3.1415
n = int(math.ceil(f))
mathモジュールのceilメソッドで切り上げができる。結果はfloatのままなので、int()で整数化する。

os.system()のPATHの変更


os.environ['PATH'] = "/sbin:/usr/bin"
os.sytem('ifconfig')

main()の書き方


def main():
  ...
  ...

if __name__ == '__main__':
  main()



ファイルやディレクトリ(フォルダ)の有無を調べる

指定したパスに、ファイルやディレクトリ(フォルダ)が存在するかを調べる方法です。

ファイルやディレクトリを区別しないで調べる場合は、os.path.exists(path)を使用します。

import os.path
os.path.exists(path)
import os.path
os.path.exists("C:\Python25")
# => True
os.path.exists("C:\Python25\python.exe")
# => True

ファイルが存在するかを調べる場合には、os.path.isfile(path)を使用します。

import os.path
os.path.isfile(path)
import os.path
os.path.isfile("C:\Python25")
# => False
os.path.isfile("C:\Python25\python.exe")
# => True

ディレクトリ(フォルダ)が存在するかを調べる場合には、os.path.isdir(path)を使用します。

import os.path
os.path.isdir(path)
import os.path
os.path.isdir("C:\Python25")
# => True
os.path.isdir("C:\Python25\python.exe")
# => False

現在のディレクトリパスを取得するには

import os
curdir = os.getcwd()

利用環境に依存せず、ディレクトリパスを結合するには、

import os
dirpath = 'C:/TEMP'
zettaipath = os.path.join(dirpath,"note.txt")

関連リンク : Python ライブラリリファレンス 6.2 os.path -- 共通のパス名操作