Logo address

Python と Javascript

目次

Python 使いのための Javascript に関するノート

Python と Javascript はシンタックスの上で大きな違いがあるが、内面ではこの二つはよく似ている。

Python から Javascript への変換規則

String and Array

このテーブルは単なる僕のメモ
全く不十分である

* Python Javasript comment
look inside dir(m) ? m: module,object
type(o) typeof(o) o: object
no value None undefined
null
論理値 True, False true, false
print print x document.writeln(x) x: object
creation a = 3*[] a = new Array(3)
size len(a) a.lengh a: sequence
first element a[0] a[0] a: sequence
last element a[-1] a[a.length - 1] a: sequence
slice a[n:m]
a[n:]
a.slice(n,m)
a.slice(n)
a: sequence

文字列

* Python Javasript comment
find s in a a.find(s)
a.index(s) # raise error
a.index(s)
a.find(s)
a: string
rfind s in a a.rfind(s)
a.rindex(s) # raise error
a.rindex(s) a: string
replace p by r s.replace(p,r[,n]) s.replace(p,r[,f]) p,r: string, n: count, f: flag
p は s の中の部分文字列

正規表現

このテーブルは単なる僕のメモ
全く不十分である

* Python Javasript comment
準備 import re 不要
compile c = re.compile(p[,f]) c = new RegExp(p[,f]) p: pattern, f: flag
match c.match(s)
re.match(p,s)
s.match(c)
s.match(p)
p: pattern
replace c.sub(r,s)
re.sub(p,r,s)

s.replace(e,r)
p: pattern
e: re, r: string
注1: patterm と書いたのは文字列を使う正規表現の表記法
注2: re と書いたのは / / を使う正規表現の表記法 (文字列だと正規表現としては扱われない。参照)
注3: match は Python と Javascript で戻り値が異なる。Python は位置情報を、Javascript は文字列情報を返す。

match の振る舞いは Python と Javascript でかなり違う。例えば
Python:

	re.match("b","abc")	# return None
Javascript:
	"abc".match("b")	// return "b"
実は Javascript の match は Python の search に近い。
Python:
	m = re.search("b","abc")	# match
	m.group()	# return "b"
Javascript の match も Python の search も共にマッチした全てのグループの情報を返すが、Javascript の match はグループの情報を文字列の配列として返す。他方 Python の search は位置情報の配列を返す。Python に於いてはマッチした文字列情報は group() メソッドで得られる。
Javascript の s.match(p)[n] は Python の re.search(p).group(n) と考えて良い。

Python の厳格さに比べて Javascript はプラクティカルな簡便さを追求している。それを示す代表的な例は、
Python:

	re.search("","abc")	# match
	re.search(None,"abc")	# error
Javascript:
	"abc".match("")		// match
	"abc".match(null)	// null
長さ 0 の文字列はどのような文字列の部分文字列となり得る。他方「存在しないものは探せない」ので、Javascript の「ありませんでした」は使いやすい。(論理式の中で使う事を想定せよ。)

配列

* Python Javasript comment
初期化 a = []
a = [None]*3
a = new Array()
a = new Array(3)
代入 a[n] = v a[n] = v n: integer(>=0), v: value
サイズ len(a) a.length
要素の追加 a = a + [v]
a.append(v)
a.push(v) v: value
ソート a.sort() a.sort()

辞書

Javascript では配列のインデックスに文字列を使える。これは実際には辞書である。
正しくは文字列だけではなく、Python と同様に任意の object が使える。

* Python Javasript comment
初期化 d = {} d = new Array()
割り付け d[o] = v d[o] = v o: object, v: value
サイズ len(d) d.length

誤解を受けやすい問題

ここでは Python になじんだプログラマの頭の中が "???..." となりそうな問題を扱う。

Javascript の undefined

Python では変数は必ず初期化して使うものと想定されている。暗黙の初期値は存在しない。 (この点は Javascript も同様である) 初期化すべき値がない場合には
x=None
のように、"None" を割り当てておく。Python の None に相当する Javascript の定数は null である。

Javascript はブラウザの中で使用される。現実はブラウザの Javascript の実装状態が均一ではない。あるブラウザが、ある変数 foo を持っていても、他のブラウザでは持っていない事がある。変数 foo を持っていない場合にだけ、何かを行いたい場合にはどうするか?

仮に Python で(無理に)変数が定義済みである事を知りたいなら注1、次のような関数 defined() を定義すればよい。
Python:

def defined(s):
  try:
    eval(s)
  except:
    return False
  return True
if not defined("foo"):
  # do something
Javascript では未実装の変数を認識するニーズがあるのだから簡単に行えるようになっている。
Javascript: Javascript では 変数 foo が定義されていない時に
if(foo == undefined){
  alert("undefined");
}
としても alert("undefined") は実行されない。この if 文の論理式はエラーなのである。正しくは
if(typeof(foo) == "undefined"){
  // do something
}
とする。

Javascript の typeof は一種のマクロ関数的な振る舞いをするのだね。普通の関数であれば、未定義の変数を引数に与えたらその関数の実行はできないのだから。typeof はその意味で関数ではない。

そう言えば僕は屢々誤解のために混乱したものだ。デバッグの時に

	alert(foo)
のようにやる。foo が定義されているのか否かがこれで分かると思って... そして頭の中は "???" だ。この場合には
	alert(typeof(foo))
としなくてはならない。

注1: 「無理に」と言ったのは、Python では未定義の変数を参照すれば実行時に分かるので、判定の必要は無いと考えているからである。

配列、辞書

x in a

ここでは
	x in a
について考える。
python:
a=["alice","bob","carol"]
for x in a:
  print x
出力

alice
bob
carol

Javascript:

a=new Array("alice","bob","carol");
for(x in a){
  document.writeln(x)
}
出力
0
1
2
ちなみに上の変数 a の下で Python では
	"alice" in a
True であるが、Javascript では false で、
	1 in a
は Python では False であるが、Javascript では true である。

この例を見る限り Javascript はいかにも奇怪であるが、次の例を見ると納得できるであろう。

a=new Array();
a["alice"]=16;
a["bob"]=20;
for(x in a)
  document.writeln(x)
これは
alice
bob
true
を出力する。Python では連想配列は辞書を使う。
a={}
a["alice"]=16;
a["bob"]=20;
for x in a:
  print x
print "alice" in a

alice
bob
True
を出力。つまり Javascript で「配列」と称せられるものは Python の辞書であると解釈できる。

役に立つ関数

属性やメソッドの一覧

Python の dir(o) (o: object) は o に属する全ての名前の一覧を表示する。実に有り難い。Javascript ではどうするか? 次のような関数を作れば良いだろう。(もっとも dir(o) 程のことはできないが...)
function names(s){
  var n,x,t,w,a;
  a = new Array();
  for(x in s){
    a.push(x);
  }
  a.sort();
  t = "";
  for(n = 0; n < a.length; n++)
    t += a[n] + "\n";
  // NG: alert(t) ; because the out put is big and therefore "OK" button is hidden.
  // so we must show the t in other windows.
  w = open("","Names","width=400,scrollbars=yes,resizable=yes");
  cont = "<html><head><title>Names</title></head><body><pre>";
  cont += t;
  cont += "</pre></body></html>";
  w.document.write(cont);
  w.focus();
  w.document.close();
}
names(window.document);
実行してみれば分かるように、残念ながらメソッドの名前までは表示されない。サポートされているメソッドの名前の一覧を得るにはどうしたら良いであろうか?

Reference