皆さんは経験豊富な PHP 開発者として、Python を学ぶ必要のある人でしょうか?この記事では、PHP でおなじみの概念 (変数、リスト、関数など) を Python でこれに相当する概念と対比させながら、PHP 開発者の視点から Python 開発の世界を紹介します。

Thomas Myer, Principal, Triple Dog Dare Media

author Thomas Myer はオースチンを拠点に活動するコンサルタントであり、著作者であり、講演者です。彼は Triple Dog Dare Media を運営しており、また Twitter では @myerman としてツイートしています。



2010年 2月 09日

おそらく皆さんは PHP 開発者として、この 5 年 (あるいはもっと長き) にわたり、アプリケーションを作成してきており、eコマース・システム、単純なコンテンツ管理システム、Twitter や Facebook との統合、そして大量のカスタム・ユーティリティーなど、考えられるほとんどすべてのものを作成してきたかもしれません。また皆さんは、単純な表示を行うページから、他の誰かが作成した何万行にもなるカスタム・アプリケーションに至るまで、大量のコードの保守もしてきたかもしれません。

よく使われる頭字語

  • Ajax: Asynchronous JavaScript + XML
  • XML: Extensible Markup Language

皆さんはそのように長い時間 PHP を扱ってきたため、別の言語に乗り換えることなど考えられないかもしれません。しかし皆さんはまた、プログラミング言語による開発の世界では立ち止まることが必ず破滅につながることも知っています。何はさておき、新しい言語の学習は外国への旅行と似ています。新しいものを目にし、初めてのものを食べ、異なる文化を楽しみ、さまざまな人々と刺激に満ちた会話をし、素敵なものに目をとめ、そして我が家に戻り、普段身の回りにあるものを改めて評価するのです。

Python を少しばかり紹介するこの記事では、読者が Python というプログラミング言語についてまったく知らないものとします。そのため、この記事の内容の一部は少し基本的すぎると思えるかもしれません。ここでは Python と PHP との比較対照に焦点を絞ります。これは一方の言語が他方よりも優れているからではなく、既に知っていることを振り返りながら新しいことを学んだ方が、大抵の場合は容易であるという単純な事実からです。

この記事の目標はシンプルです。皆さんが Python に関する実用的な知識を素早く身に付け、皆さん自身で深く掘り下げられるようにすることです。運が良ければ、皆さんが慣れ親しんだものと Python が大きく異なってはいないことを理解できるはずです。旅行の喩えを続けるなら、皆さんは遠い外国の地に行くわけではなく、誰もが皆さんと同じ言語を話す隣の国に行くだけなのです。

Python とは何か?

Python は「汎用的な高級プログラミング言語」と分類されています。Python は信じられないほど簡潔で読みやすいことで最もよく知られており、空白とインデントが実際に意味を持つ、数少ない言語の 1 つです。Python を作成する中心となった Guido Van Rossum は、相変わらず Python コミュニティーで非常にアクティブに活動しており、「慈悲深き終身独裁者 (Benevolent Dictator for Life)」という冗談めかした呼び方をされています。

Python の良い点の 1 つは柔軟でコンパクトなことです。Python は数あるプログラミング手法のうち、オブジェクト指向プログラミング、構造化プログラミング、アスペクト指向プログラミング、そして関数型プログラミングをサポートしています。Python は小さなコア部分と大規模な拡張ライブラリー・セットで設計されているため、極めてコンパクトかつ柔軟な言語になっています。

構文の点から見ると、Python は非常に簡潔であり、そのシンプルさはほとんど修道院や禅のようです。Python を学んだ PHP 開発者は、Python では構文規則がしっかり決められていることに安心感を覚え、Python のこうした方針を非常に気に入るか、あるいは構文が非常に制限されていると感じるかのいずれかの反応を示すことでしょう。すべては皆さんの見方次第です。Python コミュニティーは明らかに、気の利いた複雑さよりも美しさと単純さに価値を置くという、独特の美的感覚を貫いています。「複数の方法がある」という Perl の伝統を経験してきた (私のような) PHP 開発者は、「1 つの明らかな方法以外はあってはならない」とする Python のまったく逆の哲学に直面することになります。

実際、Python コミュニティーでは、推奨スタイルに従っているコードを Pythonic という言葉で表現します。コードが Pythonic であると言った場合、そのコードが Python のイディオムを適切に使用しているか、あるいは Python 言語を自然に使いこなしていることを指します。この記事は Pythonista (または Pythoneer) になることを目標にするわけではなく、今後継続して Python を学ぼうとする場合に知っておくべきことについて説明します。何かをするために PHP らしい方法や Perl らしい方法があるのと同様に、Python を使うということは、最終的には Python 言語で考え始める必要があるということです。

もう 1 つ、簡単な注意点を挙げておきます。この記事の執筆時点で Python は V3.0 までリリースされていましたが、この記事では Python V2.6 に焦点を絞ります。Python V3.0 はそれ以前のバージョンとは後方互換性がなく、また最もよく使われているバージョンは V2.6 のようです。もちろん、皆さんは必要に応じて、どのバージョンでも使用することができます。


Python はどのように PHP と異なるのか?

一般的に言えば、PHP は Web 開発用の言語です。確かに、PHP にはコマンドライン・インターフェースがあり、さらには組み込みアプリケーションの開発に PHP を使うことすらできますが、ほとんどの場合、PHP は Web 開発用です。対照的に、Python は Web 開発にも使用できる、汎用のスクリプト言語です。この点で ― そして次のように言うと怒鳴られるのを承知していますが — Python は PHP よりも Perl に近い言語です。(そうは言っても、実際には他のすべての点で Python は PHP と大きく異なってはいませんが、話を先に進めることにしましょう。)

PHP の構文にはドル記号 ($) や波括弧 ({}) が乱雑に入り乱れていますが、Python はもっと簡潔ですっきりとしています。PHP には switchdo...while による構成体がありますが、Python にはありません。PHP には三項演算子 (foo?bar:baz) や、膨大すぎて手に負えない数々の関数 (しかも関数名には多種多様な命名規則が適用されています) がありますが、Python はもっと整理されています。PHP には配列型があり、単純なリストとしても、辞書またはハッシュとしても機能しますが、Python では両者を区別します。

また Python には、可変性と不変性の概念があります。例えばタプルは不変リストです。タプルを作成すると、そのタプルを後で変更することはできません。この概念は慣れるまで少し時間がかかりますが、これは誤りを避けるための優れた方法です。当然、タプルを変更するための唯一の方法は、タプルをコピーする方法です。そのため、皆さんが不変オブジェクトに対して大量の変更を加えていることに気付いた場合には、その手法を再検討する必要があります。

先ほど触れたように、Python ではインデントが意味を持ちます。Python を使い始めた最初の数日間は、このことを痛切に思い知らされるはずです。Python ではまた、PHP で見られるような、位置で決まる標準的な引数を使った関数やメソッドではなく、キーワード・ベースの引数を持つ関数やメソッドを作成することができます。オブジェクト指向の純粋主義者にとっては、Python の持つ真のオブジェクト指向や「ファーストクラス」のクラスや関数を使える喜びがあります。普段、英語以外の言語を使っている人であれば、Python が国際化と Unicode を強力にサポートしている点をとても気に入ることでしょう。また、Python のマルチスレッド機能も素晴らしいと感じることと思います。私が元々 Python に魅力を感じた点の 1 つがマルチスレッド機能でした。

以上のように違いを挙げましたが、PHP と Python は多くの点で似ています。変数の作成、ループ処理、条件分岐の使い方、関数の作成など、皆さんは特に問題なく行えるはずです。さらには再利用可能なモジュールの作成でさえ、それほど苦労しないはずです。どちらの言語のユーザー・コミュニティーも活発で熱心です。PHP のインストール・ベースは Python よりもはるかに大きなものですが、それは何よりも PHP がサーバーのホスティングによく使われており、また PHP が Web 重視であるために他なりません。

これで前置きは十分です。次のセクションでは実際の例に移りましょう。


Python を扱う

リスト 1 は出発点としての基本的な Python スクリプトです。

リスト 1. 単純な Python スクリプト
for i in range(20):
	print(i)

リスト 2 はリスト 1 による当然の結果です。

リスト 2. リスト 1 の結果
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

先に進む前に、いくつかのことを調べてみましょう。まず変数です。

変数

見るとわかるように、変数であることを表す特別な文字はありません。変数 i は単純に i であり、まったく特別な文字ではありません。コード・ブロックや文の終わりを表す特別な文字 (セミコロンや波括弧など) もなく、for 文の行にコロン (:) があるのみです。また、インデントは Python に対し、for ループに属しているものを伝えることにも注意してください。例えばリスト 3 のコードは、ループ内の各数字の後にテキストが出力されます。

リスト 3. 各ループに文を追加する
for i in range(20):
	print(i)
	print('all done?')

対照的に、リスト 4 のコードはループの最後にテキストを出力します。

リスト 4. ループの後にテキストを追加する
for i in range(20):
	print(i)

print('all done!')

ところで、私はこうしたものを最初に見た時、狂気の沙汰かと思いました。何と、改行とインデントに任せればコードが構造化されるばかりではなく、実行もしてくれるのです。私を信じて欲しいのですが、しばらくすると皆さんも慣れるはずです (ただし私は、文の終わりで必ず例のセミコロン・キーに触れようとしていることを認めざるを得ません)。皆さんが他の開発者と共に Python プロジェクトで作業を行う場合には、コードの読みやすさが大きなメリットであることに気付くはずです。「この賢い開発者は一体ここで何をしようとしたのだろう」と思うケースは大幅に減るはずです。

PHP では = 演算子を使って変数に値を代入します (リスト 5)。Python でも同じ演算子を使いますが、値にラベルを付けるという表現や、値を指すという表現をする場合があります。私にとっては単に代入しているにすぎないので、私はこの表現についてはそれほど気にしていません。

リスト 5. 変数を作成する
yorkie = 'Marlowe' #meet our Yorkie Marlowe!
mutt = 'Kafka'     #meet our mutt Kafka

print(mutt)  #prints Kafka

Python の変数の命名規則は PHP の場合と似ています。変数名に使用できるのは、文字、数字、そしてアンダーバー (_) のみです。同様に、変数名の最初の文字が数字であってはなりません。Python の変数名では大/小文字が区別され、また Python の特定のキーワードを変数名として使うことはできません (例えば、if、else、while、def、or、and、not、in、is などは、そのごく一部です)。この点には特に大きな驚きはありません。

Python では、ストリングに関してさまざまな操作が可能です。リスト 6 の操作の大部分は皆さんにもおなじみのはずです。

リスト 6. ストリングに関する一般的な操作
yorkie = 'Marlowe'
mutt = 'Kafka'

ylen = len(yorkie) #length of variable yorkie
print(ylen) #prints 7
print(len(yorkie)) #does the same thing
len(yorkie) #also does the same thing, print is implicit

print(yorkie.lower()) #lower cases the string


print(yorkie.strip('aeiou')) #removes vowels from end of string

print(mutt.split('f')) #splits "Kafka" into ['Ka', 'ka']

print(mutt.count('a')) #prints 2, the number of a's in string

yorkie.replace('a','4')  #replace a's with 4's

条件分岐

for ループの使い方はわかったので、今度は条件分岐について説明しましょう。条件分岐は PHP の場合とほとんど同じであることに気付くと思います。条件分岐には、おなじみの if/else タイプの構造を使います (リスト 7)。

リスト 7. 単純な条件分岐テスト
yorkie = 'Marlowe'
mutt = 'Kafka'

if len(yorkie) > len(mutt):
	print('The yorkie wins!')
else:
	print('The mutt wins!')

if/elif/else を使用すると (elif は PHP の elseif に相当します)、もっと複雑な条件分岐テストも作成することができます (リスト 8)。

リスト 8. より複雑な条件分岐テスト
yorkie = 'Marlowe'
mutt = 'Kafka'

if len(yorkie) + len(mutt) > 15:
	print('The yorkie and the mutt win!')

elif len(yorkie) + len(mutt) > 10:
	print('Too close to tell!')
else:
	print('Nobody wins!')

ご覧のとおり、ここまでは特に驚くようなものもなく、どれもほとんど想定どおりのものです。今度は Python でのリストの処理方法を調べてみましょう。リストに関しては 2 つの言語の間に大きな違いがあることに気付くはずです。

リスト

一般的なタイプのリストの 1 つがタプルと呼ばれるものです。先ほど触れたように、タプルは不変です。一連の値と共にタプルをロードすると、そのタプルを変更することはできません。タプルには、数字、ストリング、変数を含めることができ、さらには他のタプルを含めることもできます。ご想像のとおり、タプルのインデックスは 0 から始まります。最後の項目にアクセスするためには -1 というインデックスを使います。また、タプルに対して実行できる関数も非常にたくさんあります (リスト 9)。

リスト 9. タプル
items = (1, mutt, 'Honda', (1,2,3))

print items[1]  #prints Kafka
print items[-1] #prints (1,2,3)

items2 = items[0:2]  #items2 now contains (1, 'Kafka') thanks to slice operation

'Honda' in items #returns TRUE
len(items) #returns 4
items.index('Kafka') #returns 1, because second item matches this index location

リストはタプルと似ていますが、可変である点がタプルとは異なります。リストを作成すると、そのリストに対して値の追加、削除、更新をすることができます。リストの場合には丸括弧 (()) ではなく、角括弧 ([]) を使います (リスト 10)。

リスト 10. リスト
groceries = ['ham','spam','eggs']
len(groceries) #returns 3
print groceries[1] #prints spam

for x in groceries:
	print x.upper() #prints HAM SPAM EGGS
	
groceries[2] = 'bacon'
groceries #list is now ['ham','spam','bacon']

groceries.append('eggs')
groceries #list is now ['ham', 'spam', 'bacon', 'eggs']

groceries.sort() 
groceries #list is now ['bacon', 'eggs', 'ham', 'spam']

辞書は連想配列やハッシュと似ています。辞書はキーと値のペアを使用して情報の保存と取得を行います。しかし角括弧や丸括弧の代わりに波括弧を使います。リストと同様、辞書は可変です。つまり辞書に対して値の追加、削除、更新をすることができます (リスト 11)。

リスト 11. 辞書
colorvalues = {'red' : 1, 'blue' : 2, 'green' : 3, 'yellow' : 4, 'orange' : 5}

colorvalues #prints {'blue': 2, 'orange': 5, 'green': 3, 'yellow': 4, 'red': 1}

colorvalues['blue'] #prints 2

colorvalues.keys() #retrieves all keys as a list: 
				   #['blue', 'orange', 'green', 'yellow', 'red']
colorvalues.pop('blue') #prints 2 and removes the blue key/value pair

colorvalues #after pop, we have: 
			#{'orange': 5, 'green': 3, 'yellow': 4, 'red': 1}

単純なスクリプトを Python で作成する

ここまでで Python を少し理解できたので、単純な Python スクリプトを作成してみましょう。ここで作成するスクリプトは、サーバーの /tmp ディレクトリーにある PHP のセッション・ファイルをいくつか読み取り、サマリー・レポートをログ・ファイルに書き込みます。このスクリプトでは、特定の関数用のモジュールをインポートする方法、ファイルの操作方法、そしてログ・ファイルに書き込む方法を学びます。また、収集した情報を追跡するための変数もいくつか設定します。

リスト 12 には、このスクリプトの全体を示してあります。エディターを開いて、このコードを貼り付け、そのファイルを tmp.py としてシステムのどこかに保存します。次に、そのファイルに対して chmod + x を実行し、実行可能ファイルにします (UNIX システム上で実行しているという前提です)。

リスト 12. tmp.py
#!/usr/bin/python

import os
from time import strftime

stamp = strftime("%Y-%m-%d %H:%M:%S")
logfile = '/path/to/your/logfile.log'
path = '/path/to/tmp/directory/'

files = os.listdir(path)
bytes = 0
numfiles = 0

for f in files:
	if f.startswith('sess_'):
		info = os.stat(path + f)
		numfiles += 1
		bytes += info[6]
		

if numfiles > 1:
	title = 'files'
else:
	title = 'file'


string = stamp + " -- " + str(numfiles) + " session " \
+ title +", " + str(bytes) + " bytes\n"

file = open(logfile,"a")
file.writelines(string)
file.close()

最初の行では、いわゆる「shebang 行」によって、Python インタープリターの場所を指定しています。私のシステムでは /usr/bin/python にインタープリターがあるため、このようにしていますが、この行は皆さんのシステムに合わせて変更してください。

次の 2 行では、作業を支援する特定のモジュールをインポートしています。このスクリプトがフォルダーやファイルを処理する必要があることを考えると、os モジュールをインポートする必要があります。os モジュールには、ファイルの一覧表示、ファイルの読み込み、フォルダーの処理などに役立つさまざまな関数やメソッドが含まれているからです。また、ここではログ・ファイルへの書き込みも行うため、エントリーにタイムスタンプを追加しておくのが妥当です。そこで、時間関数が必要です。すべての時間関数が必要なわけではないので、strftime 関数のみをインポートします。

次の 6 行では変数を設定します。最初の stamp という変数には日付のストリングを含めます。そのために strftime 関数を使用して、特定のフォーマットでタイムスタンプを作成します。この場合のタイムスタンプは 2010-01-03 12:43:03 というフォーマットです。

次に、logfile という変数を作成し、実際にログ・ファイル・メッセージを保存するファイルのパスを指定します (このファイルはまだ存在していなくても構いません)。ここでは簡単のため、ログ・ファイルを /logs フォルダーに置きますが、この場所はどこでも構いません。同様に、/tmp ディレクトリーへのパスを含む path という変数も必要です。パスは任意ですが、末尾がスラッシュ (/) で終わっている必要があります。

その次の 3 つの変数も同じように単純です。指定パスに存在するすべてのファイルとフォルダーを含む files リスト、そして bytesnumfiles という 2 つの変数です。この 2 つの変数はどちらも 0 に設定されます。スクリプトはファイルを処理するごとに、この 2 つの変数に値を追加します。

こうした前置きの後に、このスクリプトの核心、つまり files リストの各ファイルを処理する単純な for ループがあります。スクリプトはループを処理するごとにファイル名を評価します。ファイル名が sess_ で始まる場合には、スクリプトはそのファイルに対して os.stat() を実行し、そのファイルに関するデータ (ファイルの作成時刻、変更時刻、バイト数で表現したサイズなど) を取得し、numfiles カウンターの値を進め、このファイルのバイト数をその時点までの合計に加算します。

ループの実行が終わると、スクリプトは 1 よりも大きな値が numfiles に含まれているかどうかをチェックします。含まれている場合には、スクリプトは title という新しい変数を files という値に設定します。含まれていない場合には、title は単数形の file という値に設定されます。

このスクリプトの最後の部分は簡単です。string という最後の変数を作成し、この変数の中に 1 行のデータを格納します。このデータは stamp の値で始まり、(ストリングに変換された) numfiles と、(同じくストリングに変換された) bytes が続きます。行継続文字 (\) に注意してください。行継続文字を使うと、コードを次の行に続けることができます。これは読みやすいコードを作成するために知っておくと便利です。

次に、open() 関数を使ってログ・ファイルを追加モードで開き (ログ・ファイルには行を追加し続ける必要があります)、writelines() 関数を使ってログ・ファイルにストリングを追加し、close() 関数を使ってファイルを閉じます。

これで単純な Python スクリプトが作成できました。このスクリプトを使えば何でもできます。例えば、このスクリプトを 1 時間ごとに実行する cron ジョブを設定し、使用される PHP セッションの数が時刻によってどう変わるかを追跡することができます。また jQuery その他の JavaScript フレームワークを使ってこのスクリプトをフックし、Ajax を使用してログ・ファイルのフィードを作成することもできます (その場合には print コマンドを使ってデータを返す必要があります)。


まとめ

私達は開発者として、多くの時間を投資して特定の言語や手法に関する知識を得ようとしており、その結果として、ある言語が別の言語よりも優れているかどうか、という議論になることがあります。私はそうした議論の多くに加わったことがあり、皆さんのなかにも同じ経験をした人がいるはずです。そうした議論の大半は、昔からの「それならもっといい方法でできます」という何の役にも立たないお決まりの発言に陥りがちであると認めざるを得ません。

しかし、いったん別の言語を詳細に調べ始めると、ほとんどの言語には似たようなツールや哲学、手法があることに気付きます。プログラミング言語を初めて学習するときは難しいものですが、いずれかの言語で学んだことをこれから学ぶ言語に適用すれば、新しい言語の学習ははるかに容易になります。たとえ実際には使わないとしても、新しい言語を学ぶことで、皆さんの技術を向上する概念や手法に触れる機会を増やすことができます。

運がよければ、この記事を読んで少しばかり Python を理解できたことと思います。皆さんが学習を続け、この優れた言語を追求していくことを願っています。(結局のところ、PHP は「飯の種」なので) 皆さんが PHP の世界を去ることはないかもしれませんが Python を学び続けたとしても決して害になることはありません。

参考文献

学ぶために

製品や技術を入手するために

  • ActiveState Code を調べ、楽しめそうな Python コード・サンプルを見つけてください。
  • 皆さんの次期オープンソース開発プロジェクトを IBM ソフトウェアの試用版を使って革新してください。ダウンロード、あるいは DVD で入手することができます。
  • IBM 製品の評価版をダウンロードして、DB2、Lotus、Rational、Tivoli、WebSphere などが提供するアプリケーション開発ツールやミドルウェア製品を試してみてください。

議論するために

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Open source
ArticleID=473884
ArticleTitle=PHP 開発者のための Python の基本
publish-date=02092010