1. Python ことはじめ

Pythonって何?


Python(http://python.org/)は,1991年にGuido van Rossumによって作られたオープンソースのオブジェクト指向スクリプト言語です。スクリプト言語として日本ではPerlやRubyが有名ですが、欧米では古くから人気がある言語です。WindowsやMacOS X、Unix系OSはもちろん、携帯電話やNintendo DSなどの組み込み機器上でも動作します。

Pythonの特長として、読みやすさ、覚えやすさがあります。特に,読みやすさは言語的な特徴だけでなく、わかりやすいコードを書こうとする文化がコミュニティにも浸透しています。

ただし、インデントによりブロック構造を定義するなど、クセの強い言語です。言語規約によりコーディングルールを強制するために、見るだけでブロックの範囲を判断でき、きれいなコードが書けます。これは,他の言語にはあまり見られない特徴です。

Pythonが使われているサービスやプロダクトとして、YouTubeやBitTorrentが有名です。また、GoogleやYahoo、NASAでの実績もある言語です。Pythonの設計思想は、ECMAScript(JavaScript)やGroovy(Javaと親和性の高いスクリプト言語)に大きな影響を与えています。


インストール


インストールはPythonの公式サイト(http://python.org/download/)からお使いのOSに対応したインストーラをダウンロードしてインストールしてください。本稿では、Windows版のPython 2.5.2を使用します。

Pythonの標準ライブラリ以外にも、多くのライブラリやモジュールが公開されています。多くのサードパーティのライブラリはPython Package Index(pypi, http://pypi.python.org/)に公開されています。PerlのCPANやRubyのGemsに相当するサービスです。

easy_installというコマンドを使用するとモジュールの依存関係を解決して自動でインストールできるようになります。easy_installは次の手順でインストールします。まず、http://peak.telecommunity.com/dist/ez_setup.pyからez_setup.pyをダウンロードします。次に、下のコマンドを実行してインストールします。

 > python ez_setup.py

easy_installのセットアップが終了後、コマンドで「easy_install モジュール名」と入力するとモジュールを自動インストールできます。

初めてのPythonコード


制御構造

まず、図1の簡単なPythonコードを見てみましょう。これは、階乗を計算する関数を定義しています。Pythonを知らなくても図1のコードが何をしているか、想像できると思います。

図1 Pythonコード
def factorial(x):
    if x == 0:
        return 1
    else:
        return x * factorial(x - 1)


それでは、もう少し詳しく見てみましょう。まず目につくのは、JavaやJavaScriptなどでブロック構造を定義するブレス({})がありません。その代わりにPythonではインデントによりブロック構造を表します。インデントは通常スペース4個が使用されます。インデントでブロック構造を表すことには賛否両論がありますが、慣れればとても心地よいものです。

次に、Pythonでの関数の定義はdef文を使います。defの後に関数の名前を指定します。そのあとの「(」と「)」の間に引数を指定します。最後に「:」を書きます。:はそのあとにブロックが続くことのマークです。
factorial関数ではxを引数にとります。Javaと違ってPythonでは変数に型がありません。これは、RubyやPerlと同じです。そのため、変数xに型の指定がありません。

制御構造として、if文やfor文、while文があります。factorial関数の中ではif文を使っています。Javaと違ってif文の後の条件式を()で囲む必要はありません。()で囲んでも間違いではありませんが、Pythonらしくありません。

Pythonでのfor文はJava5で導入された拡張for文と似ています。図2はJavaで1から10までを足し合わせるコードです。このコードをPythonで書くと図3のように書けます。rangeは引数で指定した範囲内の整数の配列を作成する関数です。for文はinに続くコレクションから要素を一つづつとりだして、forの直後に指定した変数に代入します。

図2 Java5でのfor文
int[] array = {1,2,3,4,5,6,7,8,9,10};
int sum=0;
for (int i: array) {
    sum += i;
}

図3 Pythonでのfor文
sum = 0
for i in range(1, 11):
    sum += i


JavaのようにPythonでも例外処理ができます。次のように0除算するとZeroDivisionErrorが発生します。最初にTracebackと呼ばれる呼び出し履歴が表示され,そのあとにエラーメッセージが表示されます。

  >>> 1/0
  Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
  ZeroDivisionError: integer division or modulo by zero
  >>> 

次に例外を捕まえて処理してみましょう。例外を処理するためには,try節にコードを書きます。例外が発生するとexceptで処理します。Javaのtry 〜 catchはPythonではtry 〜 exceptになります。execpt節で例外クラスを指定すると,指定した例外クラスだけが補足されます。例外クラスを指定しないとすべての例外が補足されます。

>>> try:
  ...     1/0
  ... except ZeroDivisionError:
  ...     print "cannot divid by zero"
  ... 
  cannot divid by zero
>>> 



データ構造

Pythonでは、数字や文字列、配列、ハッシュテーブル(Pythonでは辞書と呼びます)が組み込みのデータ型として提供されています。

数字には整数、浮動小数点があります(図4)。整数はJavaと違って可変ビット長です。つまり、整数の大きさに制限がありません。メモリが許す限りの大きさの整数を扱うことができます。

図4 数字の表現
n1 = 32
n2 = 3.14


Pythonの文字列は現状2種類あります。通常の文字列とUnicode文字列です。Unicode文字列はJavaの文字列と同じです。通常の文字列は、単なるバイト列です。

文字列はダブルコーテンション(")、またはシングルコーテンション(')で囲みます(図5)。両者に違いはあいません。


図5 Pythonの文字列
str1 = "string in double  cautation"
str2 = 'string in double  cautation'


Python文字列のユニークな点は、文字列で"かけ算"ができることです。文字列に3をかけると(図6)、その文字列が3回繰り返されます(図7)。

図6 文字列でかけ算


str1 = "#string"
print str1 * 3

図7 文字列でかけ算したときの出力

> python test.py
#string#string#string
>

Pythonでのリストはarray = [1,2,3]のように表します。リストは角カッコで囲んで表現します。リストの中の要素はコンマで区切って定義します。リスト内の要素にはすべての型のオブジェクトを格納できます(図8)。もちろん、リストの中にリストを入れることもできます。リストの要素へアクセスする場合は,array[0]のようにインデックスでアクセスします。

図8 リスト
array = [1, 2, "string", [11, 12, "string in list"]]

リストはarray[0] = "new element"とすることで要素を変更したり追加したりすることができます。リストの親戚のタプルは、一度定義すると、要素を追加したり削除したりすることができません。タプルはmytuple = (1, 2, 3)のように中カッコで囲んで表現します。

Pythonでは様々なところで辞書が使われています。辞書はキーと値を持ったテーブルです。JavaのMapに相当します。辞書はtable = { "one": "1",  "two": "2", "three":"3"}のように表せます。辞書は波カッコ「{}」で囲んで表現します。各要素はコンマで区切ります。個々の要素はキーと値をコロンで区切ったものです。新たに要素を追加、または変更するにはtable["four"] = "4"のように記述します。辞書から指定したキーに対応する値を取り出すにはtable["three"]と書けば、キーがthreeの値が取得できます。

Pythonでもclassが使えます。安心してください。クラスは次のように定義します。classのあとにクラス名を定義します。別のクラスを拡張して新しいクラスを作成したい場合は,class MyClass(OtherBaseClass)のように記述します。Javaでは多重継承はできませんが,Pythonでは普通にできます。クラスの中にはdef文でメソッドを複数記述できます。メソッドの最初の引き数selfは,Javaのthisのようなものです。PythonはJavaと違い,selfを省略できません。Pythonではすべて明示的に指定する文化なのです。

__init__は少し特殊なメソッドで,コンストラクタです。__で始まり,__で終るメソッドはコンストラクタのように"特殊なメソッド"で,特別な意味を持っています。


  class MyClass:
      def __init__(self, arg1):
          self.arg1 = arg1
      
      def func1(self, n):
          for i in range(0, n):
              print self.arg1

クラスができたので,次のように利用してみましょう。オブジェクトの初期化にnewは必要ありません。「クラス名(引き数)」で初期化します。


  obj = MyClass("Hello")
  obj.func1(2)

関数ふたたび


最後に,関数についてもう一度見てみます。関数は「def 関数名(引数):」のように定義します。関数にはデフォルトの引数値を指定できます。下記の例では、func関数を呼び出すときにarg2やarg3を省略すると、それぞれ2と3が入力されたものとみなされます。つまり、func("arg1")のように引数を一つだけ指定した場合でも呼び出せます。

  def func(arg1, arg2 = 2, arg3 = 3):
     ....
 
関数呼び出しのもう一つの便利な機能に、キーワード引数があります。キーワード引数とは、引数に「key = value」のように記述することで、引数の順番に関係なく呼び出せます。上のfunc関数では,次のどの形式でも呼び出すことができます。引数の数が多く、ほとんどの引数がデフォルト引数値を持っていて、その一部だけを変更したい場合に便利な機能です。

   func("arg1")
   func("arg1", 2)
   func("arg1", 2, 3)
   func("arg1", arg3 = 3)
   func(arg3 = 3, arg1 = "arg1",)

対話モードで始めるPython

Pythonでの開発を心地よいものにする機能に,対話モードがあります。Pythonを引き数なしで実行すると,対話モードで起動します(図9)。対話モードでは,コマンドにPythonのコードを入力すると逐次実行されます。コードを入力すると即座に結果を参照できるので,Pythonの動作を簡単に確認できます。

図9 対話モードで起動
C:¥>python
ActivePython 2.5.1.1 (ActiveState Software Inc.) based on
Python 2.5.1 (r251:54863, May  1 2007, 17:47:05) [MSC v.1310 32 bit (Intel)] on
win32
Type "help", "copyright", "credits" or "license" for more information.
>>>

それでは,対話モードを使ってみましょう。対話モードで「1+1」と入力してリターンキーを押してください。図10のように,入力行の次の行に結果が出力されます。

図10 対話モードでの実行例
>>> 1+1
2
>>> 

次に,図1のコードを対話モードのpythonにコピー&ペーストして,動作を確認してみましょう。コードをコピーするとfactorial関数が使えるようになります。「factorial(10)」と入力すると,結果がすぐに表示されます(図11)。

図11 対話モードでの実行例
>>> def factorial(x):
...     if x == 0:
...         return 1
...     else:
...         return x * factorial(x - 1)
... 
>>> 
>>> factorial(10)
3628800
>>>

このように,コードを書きながら実行結果を確かめられるので,簡単にコードの実験,テストができます。

対話モードで,help()と入力してください。図12のようなヘルプユーティリティが起動します。keywordsと入力すると,Pythonのキーワードが一覧されます。Pythonのキーワードの1つである「if」を入力すると,ifの説明がコンソール上に表示されます。Pythonの標準モジュールの1つ「sys」と入力すると,sysモジュールのヘルプがコンソール上に表示されます。素早くヘルプを表示できるのは便利なのですが,残念ながら日本語では表示できません。

図12 helpコマンドの実行
>>> help()


Welcome to Python 2.5!  This is the online help utility.
[中略]
To get a list of available modules, keywords, or topics, type "modules",
"keywords", or "topics".  Each module also comes with a one-line summary
of what it does; to list the modules whose summaries contain a given word
such as "spam", type "modules spam".


help> keywords


Here is a list of the Python keywords.  Enter any keyword to get more help.


and                 elif                if                  print
as                  else                import              raise
assert              except              in                  return
break               exec                is                  try
class               finally             lambda              while
continue            for                 not                 with
def                 from                or                  yield
del                 global              pass                


help> if


Related help topics: TRUTHVALUE


help> 

Pythonの標準の対話モードは,基本的な機能しか提供していません。IPython(http://ipython.scipy.org/)を使うと,コマンドの履歴機能や変数名や関数名をタブキーで補完する機能など,便利な機能が提供されています。本格的にPythonを使う場合はインストールしておくことをお勧めします。

dir()でイントロスペクション


引き続き,対話モードで遊んでみましょう。
組み込み関数dir()は,指定したオブジェクトの属性名を一覧します。オブジェクトを何も指定しなければ現在のスコープにあるオブジェクトを一覧します。dir()はJavaでのリフレクション相当と考えてください。

まずは,Pythonを対話モードで起動して,dir()関数を引き数なしで実行します(図13)。__builtins__と__doc__, __name__という名前のオブジェクトが現在のスコープ上に存在しています。ここでは,__builtins__についてもう少し調べてみましょう。

図13 dir関数の実行
>>> dir()
['__builtins__', '__doc__', '__name__']
>>> 

Pythonは動的な型言語なので,変数を定義するときにJavaのように型を明示する必要はありません。ただし,Pythonのオブジェクト自体は型情報を持っています。まずは,__builtins__の型情報を調べてみます。オブジェクトの型名を表示する関数にtype()があります。早速調べてみると(図14),__builtins__はモジュールであることが分かります。


図14 __builtins__の型を表示>>> type(__builtins__)
<type 'module'>
>>> 

それでは,__builtins__の属性を調べてみます。dir()の引き数に__builtins__を指定して実行します(図15)。この__builtins__には組み込み関数が定義されています。

図15 __builtins__の属性
>>> dir(__builtins__)
['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'DeprecationWarning', 'EOFError',
[中略]
 'type', 'unichr', 'unicode', 'vars', 'xrange', 'zip']
>>>

モジュールやクラス,関数にはdocstringと呼ばれる文書を属性として設定できます。ヘルプユーティリティで表示されるヘルプ文書もdocstringから生成されています。JavaDoc相当と考えてもいいでしょう。「print  __builtins__.__doc__」と入力してください。組み込み関数のヘルプが表示されます。


名前空間


図12のようにPythonを対話モードで起動した直後は3つの属性しかありません。図11のようにfactorial関数をもう一度コピー&ペーストして,dir関数を実行します(図16)。今度は,factorialが現在のスコープに追加されています。

図16 関数を定義後,dir()関数を実行
>>> def factorial(x):
...     if x == 0:
...         return 1
...     else:
...         return x * factorial(x - 1)
... 
>>> dir()
['__builtins__', '__doc__', '__name__', 'factorial']
>>> 

factorial関数もオブジェクトの1つです。オブジェクトなので,属性を追加,参照できます(図17)。まずは,factorial関数の属性をdir関数で調べます(図17 ㈰)。次に,factorial関数にmyvarialble属性を追加しています(図17 ㈪)。factorial.myvariableで追加した属性にアクセスできるのがわかると思います(図17㈫)。

図17 factorial関数をしらべる
>>> dir(factorial)    ㈰
['__call__', '__class__', '__delattr__', '__dict__', '__doc__', '__get__', '__getattribute__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', 'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name']
>>> factorial.myvariable = "add my variable" ㈪
>>> dir(factorial) 
['__call__', '__class__', '__delattr__', '__dict__', '__doc__', '__get__', '__getattribute__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', 'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name', 'myvariable']
>>> factorial.myvariable ㈫
'add my variable'
>>> 

モジュールのインポート

Pythonでは,コードをモジュールとしてまとめて,外部のスクリプトやモジュールから読み込む機能があります。Javaのパッケージに相当します。

スクリプト内でモジュールを使うには,importを行ないます。システムの情報が格納されているsysモジュールをインポートしてみます(図18)。インポートすると,現在のスコープにsysが追加されす。モジュールもオブジェクトの一種です。インポートを行なうと,そのモジュールがメモリ上にロードされ,オブジェクトが生成されます。このオブジェクトはシングルトンです。次に,オブジェクトは参照できるように現在のスコープ属性に追加されます。

図18 import
>>> import sys
>>> dir()
['__builtins__', '__doc__', '__name__', 'sys']
>>> 

デフォルトでは,現在のスコープに追加される名前はモジュール名と同じです。インポートされるときの名前を変えるには,図19のようにasを使って記述します。ここでは,mysysという名前でインポートしてます。

図19 import
>>> import sys as mysys
>>> dir()
['__builtins__', '__doc__', '__name__', 'mysys']
>>> 

sysモジュールにはcopyrightと言う属性があります。プログラムからcopyrightという属性を何回か使いたい場合,毎回sys.copyrightと入力するのは煩雑です。
  from sys import copyright
のようにインポートすることでsysモジュールのcopyrightだけを現在のスコープの属性に追加します。メモリ上にはsysモジュールがロードされていて,現在のスコープでcopyrightと言う名前でsys.copyrightにアクセスできるようになっているだけです。

from sys import *

のように記述するとsysモジュールのすべての属性名が現在のスコープにコピーされます。同じ変数名を使っている場合,名前が衝突して上書きされてしまい,バグの素になりますので,気をつけてください

このように対話モードからオブジェクトを調べたり,コードを試すことで,とても心地よく開発ができます。初めての方はもちろん,Pythonを触ったことがある方も,イントロスペクションでもっと楽しくPythonを使ってみましょう。

Comments