Cなんていうのは作る人が使うプログラミング言語だと思うんだ。
まぁまさにそうで、Linuxなんかを作ってるのはCですからね。
けど、それ単体の機能がほとんどないし、いろいろあって細かい部分の面倒まで見る必要がある。
まぁ、Win32 APIを使えば、高機能だしWindowsもかなり面倒を見てくれて楽だと思います。
JavaとかC#・VB.NETなんかはJava VM、.NET Frameworkが面倒を見てくれるので非常に便利。
まぁこの辺まで来ると使う人が使うプログラミング言語ですよね。
けどそれでもコンパイルするのめんどくさいというのはあるし、インタプリタのような環境はありがたいものです。
作るプログラムのほとんどはPerlであるというのはまぁその辺の加減です。
しかし、.NET Frameworkで動くインタプリタあったりいいねとかも思うわけだ。いやあるんですよ。
IronPythonですね。以前ちょっと話したことがあったと思うけど。
なんでこんなものがあるのかという話だが、
作者であるJim Huguninは、「CLI(.NET Frameworkなどのこと)の設計は動的言語との相性が悪い」という論文を発表したらしい。
それでそれを確かめるために作ったのが、IronPythonとなったわけなんだが、
実は、.NET Frameworkでは動的言語であるところのPythonが結構うまく動くと。そういう結果だったらしい。
もうなんかすごい高速だったらしい。まぁさすが.NET Framework、実用的な環境ですね。
まぁなんというか変な経緯でできてますけど、.NET Framework上で動く有名なインタプリタです。
IronRubyというのもあるらしいが、やはりIronPythonだと思う。
Pythonという新しい言語を勉強して使うことになるが、Pythonしたいというより.NETしたいわけで。
導入法ですがかなり簡単です。IronPythonからBinの方をダウンロード。
それで、展開したフォルダをC:\Program Files\IronPythonなどとします、そして、環境変数のPATHの最後に追加。
これで便利に使えます。
まぁしかしPythonというのはPerlの正反対とも言えるようなやつですね。
Perlは非常に下品だが、いろいろな書き方を便利に取り扱うことができる。自由なやつです。
一方、Pythonは、そんなにやり方はたくさんなくて、きれいなソースでしか書けないという、小さいやつです。
まぁPerlは本当にひどいからね。しかしそれがよいのではないかというのも確か。
さて、それで上のように導入したら、コマンドプロンプトを立ち上げてipyとする。
すればIronPythonの対話環境が立ち上がる。
print "Hello Python!"
まぁ見ればわかるが普通に動作する。別にIronPythonでなくてもこうなります。
さて、せっかくだからプログラム書いてみようか。Ctrl+Zで出ましょう。
それで、こんなtest.pyでも作る。
# encoding: utf-8
def main():
strs=["IronPythonやりたいね","その前に練習やるよ"]
strs.append("Python知らないけどね")
strs.insert(0,strs.pop())
i=0
for cur in strs:
i=i+1
say(cur,i)
say("というお話でした");
def say(str,times=1):
if times==1:
print str
else:
for i in range(times):
print "%s(%d)"%(str,i)
if __name__ == '__main__':
main()
なんてことない、Pythonですね。まぁ一応Linuxのpythonでも動いたし。
で、ipy test.pyとすれば動く。
#encoding:utf-8は使ってるエンコーディングに合わせて書く。これだけでうまく動く。
さて、サブルーチンはdef main():のように書くのだが、範囲はインデントで示す。
しかも、1行1文が普通。まぁ確かに;で区切って複数書けるし、いちいち終わりに;を打っても副作用はないけどね。
リストは[ ]で囲んで書く。
まぁさすがにオブジェクト指向プログラミング言語言うだけあって、リスト操作も便利。
だけど、Perlほど機能が豊富というわけではない。まぁやはり小さなもんです。
for cur in strs:のように繰り返しは書く。まぁforというがC#で言うforeachみたいなもんです。
それで使うのが、range関数。rangeは開始数値、終了数値(この数値を含まない)、増分で、
増分が1なら省略可、さらに開始数値が0なら省略可。
まぁPerlの範囲演算子に類似していて、リストを作るものらしい。
“%s(%d)”%(str,i)のような表現があるが、これはsprintfのような役目を果たす%演算子を使ったやつ。
(str,i)のようなものをタプルというのだが、タプルは変更不可能のリストと思えばいい。
それであてはめて表示すると。Perlみたいに”$str($i)”とか、Rubyみたいに”#{str}”とかはないと。
最後の2行は、モジュールとして読み込まれたときは、__name__にはモジュール名が入るけど、
このファイルから実行されたら”__main__”が入ってるので、そのときだけmainを実行すると。
まぁそういうことです。Pythonの詳しい勉強はまたすればいいよ。
実行速度だが、ipyの初期化に時間がかかるので遅く感じてしまうかな。
カレントディレクトリにtest.pyを置いてipyからこうすると速い。
import test
test.main()
まぁこれじゃあIronPython関係ないですね。
以前のlivehack.dllをIronPythonで扱ってみようかと思ったのよね。
いちいちC#で書くとめんどくさいから、気軽に動かせんもんかって。
# encoding:utf-8
import clr
clr.AddReferenceToFile('livehack.dll')
import System
from hidemaro import livehack
def main():
mylive=livehack(livehack.mode.Office)
arg=["",mylive]
mytimer = System.Threading.Timer(System.Threading.TimerCallback(tickdo),arg,0,100)
print "なんかキー押したら終わるよ"
System.Console.ReadKey(1)
mylive.remove()
def tickdo(obj):
str="IronPython時報が%s時%s分をお知らせします!!"%(now.ToString("HH"),now.ToString("mm"))
if str!=obj[0]:
obj[1].send(str)
obj[0]=str
if __name__ == "__main__":
main();
まぁ非常におもしろい。所々慣れてない部分があって詰まったが、納得のいくやり方だった。
.NETのライブラリを使う場合はその前にimport clrとする。
その上でDLLはclr.AddReferenceToFileで読み込む。clr.AddReference(“System.Windows.Forms”)とかいう風なやり方もある。
importには2つ使い方があって、import Systemとすれば、System名前空間以下はSystem.Stringのように使える。
一方でfrom hidemaro import livehackは、hidemaro.livehackを単にlivehackと使える。
from hidemaro import *とかできるけど、そんなことはしない。だって下品だから。
さて、Pythonでのコンストラクタは、newなしでクラス名をそのまま書く。なるほどね。
なんというかあとはC#とかと扱い一緒なんだよね。
Timerのコンストラクタの引数は、毎度実行するSystem.Threading.TimerCallback型のデリゲート、
毎度渡すオブジェクト、何ms後に開始するか、何ms間隔で実行するか。
デリゲートは普通にコンストラクタを動かして作るだけでいいし、
毎度渡すオブジェクトはいらんかったらNone(null相当)、必要だとしても結構適当に書いていい。
受け取る方もむちゃくちゃいい加減ですね。C#でこんなの書いたらコンパイル通らないよ。
ちなみにobjの型はIronPython.Runtime.Listですね。あれ?
いろいろ試してみたのだが、引数に.NET Frameworkの配列(System.Array)を渡すとき、
読み取り専用ならタプル、それ以外は、System.Array[T](list)の要領で変換する必要があると。
あと、配列の作成は、System.Array.CreateInstance(T,length)の要領でやる。
System.Array.CreateInstance(System.Int32,10)のように。
IronPythonでSystem.Int32と書くと変数でSystem.Type型なのね。
mylist=['Yamada','Taro']
import System
System.String.Join(' ',tuple(mylist))
arr=System.Array[System.String](mylist)
System.Array.Reverse(arr)
mylist=list(arr)
while len(mylist):
print mylist.pop()
やはり考え方があまりに違う言語同士相容れないところはあるのかもしれません。
もちろんSystem.Array[System.String]もforで回せますよ。IEnumerableだから当然ですね。
最後のはこんなこともできるんだよと書いただけ。
どうもコンストラクタを使えばいろいろ相互変換できるように工夫されてるみたい。すばらしい。
なおタプル、リストとSystem.Array[T],System.Collections.ArrayList,System.Collections.Generic.List[T]、
辞書型はSystem.Collections.Hashtable、System.Collections.Generic.Dictionary[T1,T2]に変換できる。
他にもいけるのはあるかもしれない。
しかしこういう点を除けばIronPythonは非常に便利だと思いますよ。
そもそもSystem.ArrayとPython・Perl・Ruby・PHPの配列なんかを比べちゃいけない。
むしろそのための方法がそれなりに整備されてるIronPythonに感謝するべきだろう。
さて、クラス作りとかやりたいなとか思うけど、これ以上長い記事を書くと夜が明けるので今日はここまで。
あと、カテゴリ名がPerl・PHP・Ruby・Pythonになったよ。長すぎる…