1時間で覚える?Python



Pythonをインストールする


まず、まだPythonをインストールしていない人は 日本Pythonユーザ会のページの左端のリストから「ダウンロード」を選び、 「日本語環境用インストーラ(Win32)」のページから「python-2.5.msi 日本語環境用インストーラ(Win32)」 をダウンロードしてインストールしましょう。



動かしてみる


スタートメニューにPythonのアイコンができていると思います。

Idle(Python GUI)」と書かれているものを起動しましょう。

下の様な画面が出るはずです。

とりあえず、画面に出力する方法を覚えましょう。

「>>>」の右に「print "Hello World!"」と書いて改行キーを押すと、画面には下のように表示されるはずです。

>>> print "Hello World!"
Hello World!

「1行ごとにインタラクティブに実行するんじゃなくて、まとめて実行したいんだが…」と言う人は、FileメニューからNew Windowを選びましょう。

「.py」で終わる名前で保存するとPythonスクリプトであると認識されてオートインデントや色付けが行われるようになるので、まずは保存しましょう。

実行はRun→Run Moduleです。

F5キーでもOKです。

保存せずに実行しようとすると、保存するかどうかの確認ダイアログが出ます。

Pythonでもすべてのものはオブジェクトです。

printは勝手に見やすく整形してしまいますが、そうではない表示をさせたければreprを使いましょう。

>>> print "Hello\nWorld!"
Hello
World!
>>> print repr("Hello\nWorld!")
'Hello\nWorld!'

なお、二重引用符と一重引用符("〜"と'〜')に区別はありません

エスケープの無効化は「r"〜"」を使います。

生(raw)です。

足し算や掛け算を試してみましょう。

文字列の結合はピリオド(「.」)ではなくてプラスです。

Perlとは違います。

また、セミコロン「;」を挟むことで同じ行に複数の命令を書くことができます。

最後の行の例で「print 〜,」という構文が使われていますが、これは「改行しないprint」です。

間にスペースを挟んでくれるのでデバッグ出力なんかに便利ですね。

>>> print 1+2
3
>>> print "a"+"b"
ab
>>> print "abc"*3
abcabcabc
>>> print "hello",  ; print "world!"
hello world!

「スペースとか改行とか余計なことをするな!」という方は標準出力に直接書き込んでください。

ファイルと同様です。

>>> import sys
>>> sys.stdout.write("aaa\n")
aaa
>>> fo=file(r"c:\filename", "w")
>>> fo.write("aaa\n")
>>> fo.close()


基本的なデータ型とそのメソッド


基本的なデータ型はtype関数で何なのかを調べられます。

>>> type(1)
<type 'int'>
>>> type("hoge")
<type 'str'>
Pythonではすべてのものがオブジェクトなのでもちろん整数1もオブジェクトです。

「1.__add__(2)」は浮動小数点数と紛らわしいので構文エラーになりますが、 「(1).__add__(2)」とやれば3が返って来ます。



listとtuple(タプル)


配列のようなものはlistとtuple(タプル)の2種類があります。

最近の言語ではほぼ常識かと思いますが、添え字は0から始まります。

昔の言語のことは忘れてください。

以下で「配列」といった場合はリストでもタプルでも同様だという意味です。

>>> tpl=(1, 2, 3)
>>> tpl[0]
1
>>> lst=[1, 2, 3]
>>> lst[0]
1
リストとタプルの目立った違いは要素を変更できるかどうかにあります。

>>> lst[0]=0
(著者注:エラーは発生しない)
>>> tpl[0]=0

Traceback (most recent call last):
  File "", line 1, in -toplevel-
    tpl[0]=0
TypeError: object doesn't support item assignment

配列の添え字に負の値を使うと後ろから数えた位置になります。

コロン(「:」)で区切ると範囲を示すことができます。

「〜以上、〜未満」という範囲です。

>>> "abcde"[2]
'c'
>>> "abcde"[-2]
'd'
>>> "abcde"[1:3]
'bc'
>>> "abcde"[-2:]
'de'

任意のオブジェクトはstr(object)で文字列化ができます。

これは「__str__」というメソッドの呼び出しの別名です。

>>> str([1, 2, 3])
'[1, 2, 3]'
>>> [1,2,3].__str__()
'[1, 2, 3]'

なおint(object)とfloat(object)もあります。

__int__および__float__の別名です。

(しかし文字列はこれらのメソッドを持っていません。

実はコンストラクタの引数なんです。

まぁ見かけ上は同じなので意識する必要性はないかもしれませんが。

) __str__は、print文で表示する際に内部で呼び出されています。

配列はfor文を使って以下のようにできます。

>>> for name in ["Taro", "Jiro", "Saburo"]:
	print name, "is happy!"

	
Taro is happy!
Jiro is happy!
Saburo is happy!

「10回繰り返す」などの場合は「for i in range(10):」とします。

range(n)は0以上n未満の整数が入ったリストを返します。

近いうちにイテレータが返るようになってパフォーマンスが向上するでしょう。

なお、配列の長さはlen(object)で取得します。

__len__メソッド呼び出しの別名です。



辞書(dictionary)とそのメソッド


その他の構造としてはやっぱりハッシュでしょう。

Python界では辞書(dictionary)と呼ばれています。

キーには任意の「変更不可能(immutable)なオブジェクト」が入ります。

変更不可能な変数(定数)という意味ではありません。

まぁ細かいことはわからなくても実害はないでしょう。

とりあえず文字列、整数、実数、タプルの他に自分で定義したクラスやそのインスタンスもキーとして使用できます。

(リストは変更可能(mutable)なのでキーに出来ません。

タプルの存在意義はここにあります。

) タプルをキーにするだけで、疎な行列のメモリ節約なんかも簡単に出来てしまいます。

dict.has_key(key)で辞書がそのキーを持っているかどうかがわかります。

キーの一覧はdict.keys()で得られます。

dict[key]というアクセスの仕方をしてキーが存在しない場合はKeyErrorが発生します。

キーがない場合のデフォルトの値を指定したいならばdict.get(key, default)です。



制御構造


すでにforは出てきましたが、Pythonでは「同じ高さのインデントが続く範囲」をブロックとしてみなします。

そのため、他の多くの言語と違って、ブロックの終わりをあらわす文字列は何もありません。

ifやwhileの使い方はこうです。

if condition:
    something
elif condition:
    something
else:
    something

while condition:
    something
else:
    something
コロン(「:」)を忘れないように気をつけましょう。

whileやforはbreakやcontinueが使えます。

whileとforのelse節はbreakされずにループが完結した場合に呼ばれます。

for p in primes:
	if x % p == 0:
		break
else:
	print x, "is prime number!" # 素数
また、これはRubyやSchemeの経験のある人にはとても重要な情報ですが、 if, while, forなどは文なので値を持ちません

0, 0.0, 空文字列などは偽です

でも最新のPythonにはTrueとFalseがあるのでそれを使うといいとおもいます。



関数の定義


関数の定義はdefです。

def add(x, y):
    return x + y

def sayHello():
    print "Hello!"

やっぱりインデントの前にはコロンがあります。

ここで注意しないといけない点は2つ。

returnしないと値が返りません

RubyやPerlでは最後に評価したものが返ったかと思いますが、 Pythonでreturnしていない場合は「None」というオブジェクトが返ります。

returnし忘れて変数にNoneが入ってしまうのはよくあるミスですが、 逆にreturnし忘れでNone以外のものが入ることはないのでバグの早期発見ができるとも考えられます。

考え方次第です。

もう一つの注意点は、Pythonで関数を呼ぶときにはかならず括弧「()」が付く」ということです。

引数が無くてもです。

上の例だと、a=sayHello()は「Hello!]と表示してaの値はNoneになりますが、 a=sayHelloならばaの値がsayHelloと同じ関数オブジェクトになります。

次からはa()だけで挨拶をしてくれます。

>>> def sayHello():
	print "hello!"

	
>>> sayHello()
hello!
>>> a=sayHello()
hello!
>>> print repr(a)
None
>>> a=sayHello
>>> print repr(a)
<function sayHello at 0x00BEA3F0>
>>> a()
hello!


クラスの定義


クラスも定義しましょう。

class MyClass:
    def __init__(self, x):
        self.value = x
    def printValue(self):
        print self.value
    def incValue(self, diff):
        self.value += diff


>>> i=MyClass(5)
>>> i.printValue()
5
>>> i.incValue(10)
>>> i.printValue()
15

Pythonではインスタンスの作成にJavaのnewのような特別な構文はありません。

関数の呼び出しもインスタンスの作成も構文上は同じです。

クラスはインスタンスを返す関数だと考えていいのではないでしょうか。

Pythonではクラスのコンストラクタは__init__です。

C++のようにクラスと同名のメソッドでもなく、Delphiのように任意でもありません。

また、引数の違う__init__を複数定義することもできません。

こう言うと「じゃぁ引数の違うコンストラクタを複数作りたい場合にどうするんだ」といわれるかもしれませんね。

一つしかコンストラクタが無いのは確かに一見非常に不便そうに見えます。

しかし、Pythonは関数に引数を渡す方法が尋常でなく柔軟なのでそのデメリットをカバーできるのです。

>>> def foo(x=1, y=2):
	return x+y

>>> foo(x=5)
7
>>> foo(y=5)
6

>>> def foo(*args):
	return args

>>> foo(1, 2, 3, 4, 5)
(1, 2, 3, 4, 5)

>>> def foo(**args):
	return args

>>> foo(x=1, y=2, z=3)
{'y': 2, 'x': 1, 'z': 3}

一つ目の例では引数のデフォルトの値を指定しています。

呼び出し時に値を指定されなかった変数にはデフォルトの値が代入されます。

二つ目の例では、引数をリストに入れています。

例えば「与えられた引数の平均を取る」といった不定個数の引数を取る場合にいいかもしれません。

でもリストを引数に渡せばいいだけのような気もします。

筆者はあまり使ってません。

三つ目の例では、引数として与えられた名前と値のセットを辞書として取得しています。

これが一番強力です。

C++/Javaのような引数の型の相違で複数のコンストラクタに振り分けられるタイプと異なり、 自分で振り分けるコードを書かないといけませんが、 その代わりに単なるswitchではない柔軟な振り分け方ができます

コンストラクタの話から余談が長くなりましたが、話を元に戻しますと メソッドの第一引数と渡されている値(selfという変数で受け取っている値)が インスタンス自身への参照です。

つまり、インスタンス変数はself.valueという形でアクセスできます。

クラス変数はクラスの名前を用いてMyClass.classvarというようにアクセスします。

なお任意の時点で動的に生成できます

>>> class MyClass:
	pass

>>> myInstance=MyClass()
>>> MyClass.value=1
>>> myInstance.value
1

スコープの話が出たのでグローバル変数について。

関数内でなにも宣言されずにいきなり代入が行われた場合、 そのスコープでローカル変数が作成されます。

「global var」と宣言してから代入するとグローバル変数になります。

なお、ある変数を参照した時にローカルの名前空間で見つからなければ外側へ外側へと探しに行きます。

上の例で「myInstance.value」を参照していますが、インスタンス変数にvalueが見つからなかったのでクラス変数を参照しているわけですね。

名前空間周りのイントロスペクションとしては、 locals()でその場所のローカル名前空間を取得でき、 object.__dict__でそのオブジェクトの名前空間を、 dir(object)でそのオブジェクトからたどる事のできる変数名の一覧を取得できます。

>>> MyClass.__dict__
{'__module__': '__main__', '__doc__': None, 'value': 1}
>>> myInstance.__dict__
{}
>>> dir(myInstance)
['__doc__', '__module__', 'value']
>>>
>>> locals()
{'__builtins__': <module '__builtin__' (built-in)>,
 'myInstance': <__main__.MyClass instance at 0x00A26F80>,
 'MyClass': <class __main__.MyClass at 0x009E9D20>, 
 '__name__': '__main__', '__doc__': None}

なお基本的にメンバ変数はpublicです。

また、Rubyのように大文字で始まる変数は変更できない…なんてことはありません。

Javaと違って多重継承もできますし、 言語としてはけっこう「厳しくない」と言えるでしょう。

そうそう、Rubyを普段お使いの方は既存のクラスに動的にメソッドを追加しようとして、 クラスの定義を上書きしてしまうかもしれません。

Pythonではclass MyClassと一度定義した後に同じclass節が再び現れると メンバの追加ではなく、クラス定義の上書きになります。

Pythonで動的にメソッドを追加するのはこうです。

>>> class MyClass:
	pass

>>> def sayHello(self, target):
	print "Hello, %s!" % target

	
>>> MyClass.sayHello=sayHello
>>> myInstance=MyClass()
>>> myInstance.sayHello("Bob")
Hello, Bob!

ようは動的にメンバ変数を追加するのもメソッドを追加するのも同じです。

というかメソッドは関数として呼び出すことのできるオブジェクトがメンバ変数に入っているのだと考えて構わないのではないでしょうか。

関数なのかそうじゃないのか、という区別は他の言語ほど厳しくありません。

__call__メソッドを実装した任意のクラスはのインスタンスは関数として呼び出すことができます

>>> class Counter:
	def __init__(self):
		self.value=0
	def __call__(self):
		self.value+=1
		print self.value

		
>>> c=Counter()
>>> c()
1
>>> c()
2
>>> c()
3


文字列フォーマット操作


PythonではCのprintfのようなことが出来ます。

詳しいことは文字列フォーマット操作

>>> "%d..%d" % (1,20)
'1..20'
>>> "%2d, %.2f, %03d" % (1,2,3)
' 1, 2.00, 003'
特に辞書を受け取る機能と名前空間を取得するメソッドlocals()を組み合わせれば、 出現する順序や回数を考慮することなく変数名で表示すべきオブジェクトを指定できます。

>>> boy = "Taro"
>>> girl = "Hanako"
>>> "%(boy)s loves %(girl)s, but %(girl)s don't like %(boy)s." % (locals())
"Taro loves Hanako, but Hanako don't like Taro."


正規表現


正規表現は、Perl5のものとほぼ同様です。

一部追加機能があります。

PerlやRubyを使っている人にとっておそらく一番戸惑う点は、 正規表現専用の構文は存在しないという所でしょう。

正規表現はあくまでモジュールの1つとして提供されているだけです。

その為、まず正規表現を使うためには import reとやって正規表現モジュールをインポートする必要があります。

詳しいことは 正規表現モジュールの内容

モジュールをインポートした後は、正規表現をコンパイルしたり、それを使って検索をしたりします。

正規表現のコンパイルは元から計算量の高い処理なので同じ正規表現を何回も使うときなどは 最初にコンパイルしたものを使いまわしたほうが高速です。

詳しくは後で。

>>> import re
>>> print re.search("(<\w+>)", "aaa")
None
>>> print re.search("(<\w+>)", "  <br> <hr> <table>")
<_sre.SRE_Match object at 0x00C1F5A0>

と、こんな風に、正規表現にマッチする部分が見つかればマッチオブジェクトが、 見つからなければNoneが返ってきます。

Noneは偽でマッチオブジェクトは真なのでそのままifの条件式部分に使えます。

上の例では2回同じ正規表現を使っています。

これでは正規表現のコンパイルという比較的重たい処理がが2回行われてしまいます。

そういう場合にはre.compileを使って最初に正規表現をコンパイルしておくなんてことも出来ます。

>>> rexp=re.compile("(<\w+>)")
>>> print rexp.search("  <br> <hr> <table>")
<_sre.SRE_Match object at 0x00C29E60>

startでマッチした部分の開始位置、spanでマッチした範囲、groupでマッチした文字列が取れます。

groupの引数によって丸括弧で囲われた部分を取得できたりします。

詳しいことはライブラリリファレンスを読んでください。

findallを使えばマッチした部分のリストを取得できます。

>>> matchObj=rexp.search("  <br> <hr> <table>")
>>> matchObj.start()
2
>>> matchObj.span()
(2, 6)
>>> matchObj.group()
'<br>'
>>> print rexp.findall("  <br> <hr> <table>")
['<br>', '<hr>', '<table>']
>>> rexp=re.compile("(<(\w)\w+>)")
>>> print rexp.findall("  <br> <hr> <table>")
[('<br>', 'b'), ('<hr>', 'h'), ('<table>', 't')]

それから、正規表現の中に改行やコメントを入れて見やすく整形したりもできるようですが、 著者はそんなことをしないとわからない規模の正規表現を使ったことがないのでサンプルは書けません。

置換はsubです。

いくつ置換するかを引数で指定できます。

指定しなければすべて置換します。

>>> print rexp.sub("tag", "  <br> <hr> <table>")
  tag tag tag
>>> print rexp.sub("tag", "  <br> <hr> <table>", 1)
  tag <hr> <table>


ファイル入出力


いよいよ最後の章です。

ファイルの入出力をしましょう。

とりあえずファイルを1行ずつ読みこみ、 別のファイルに書き出す方法は最新のPythonではこう書けます。

fo=file(r"c:\outputFile.txt", "w")

for line in file(r"c:\tmp.py"):
    fo.write(line)

fo.close()

使っているPythonが古い、もしくは上の書き方に嫌悪感を感じる場合はこうです。

fi=open(r"c:\tmp.py")
fo=open(r"c:\outputFile.txt", "w")

for line in fi.readlines():
    fo.write(line)

fi.close()
fo.close()

1つ目の例では入力ファイルをクローズしていませんが、 参照を保持していないので、使い終わるとガベージコレクトされ、そのときに自動的にクローズされているわけです。

とりあえず引数はsys.argvで参照できるのでcat(引数に与えられたファイルの中身を表示)はこう書けます。

import sys

for filename in sys.argv[1:]:
    print file(filename).read()

これでは引数に何も与えなかったときに標準入力を返しませんが、Pythonでcatを作るモチベーションがわかないので勘弁してください。

ちなみに標準入力はsys.stdinです。