「」に属する記事(最新5件のみ展開表示)

メイン

2007年01月21日

PythonとJavaScriptの微妙な違い

だいありー

なんかささださんと話がかみ合っていない気配がするので、 とりあえずこちらが知っているPythonの話をまとめてみます。

Pythonの場合、関数内で代入が行われる変数はローカル変数です。 すでに外のスコープに変数があろうがそんなことはお構いなしにローカル変数です。 例外は、変数をglobal宣言した場合で、この場合だけグローバル変数になります。

>>> def func1():
	global a
	a = 1 # グローバル変数への代入になっている
	b = 2
	print locals()

	
>>> func1()
{'b': 2} # ローカル変数はbだけ
>>> a
1 # aはグローバル変数なのでアクセスできる
>>> def func2():
	a = 1
	global a
	
SyntaxError: name 'a' is assigned to before global declaration (, line 1)
それでもって、一つの関数内で同じ名前でグローバル変数とローカル変数を作ったら、 グローバル変数がローカル変数で隠されている状態になるのが自然だと僕は思ったわけです。
>>> def func2():
	c = 1 # ローカル変数作成
	globals()["c"] = 2 # グローバル変数作成
	print c

	
>>> func2()
1 # ローカルのcは1
>>> c
2 # グローバルのcは2
でもって、ささださんの挙げたJavaScriptの例も、 "a"になるのが自然だな、でも違うのか、と思って試してみたらやっぱり"a"になったので、 「うむむ、これは何か話がかみ合ってないぞ?」と思った次第。
function test() {
  var foo = "a";
  function inner() {
    foo = "b";
    var foo = "c";
  }
  inner();
  return foo;
}
document.write(test());
PythonでもJavaScriptと同じように"a"が返ります。
>>> def test():
	foo = "a"
	def inner():
		globals()["foo"] = "b"
		foo = "c"
	inner()
	return foo

>>> test()
'a'
ささださんが何を不自然だと感じたのか詳しいことはわからないですけど、 もし"b"が返ると思ったのだったらどういうことか考えてみると…。 きっと僕の脳内では
  • JavaScriptの"x = 1"はグローバル変数のxを作成して1で初期化する命令
  • グローバルスコープとは、トップレベルのスコープ
という認識になっていて、
  • 「foo = "b";」によってグローバル変数がいじられようが何だろうが、 関数testのローカル変数が影響を受けるはずがない
  • 「var foo = "c";」はローカル変数だから関数の外に影響を及ぼすはずがない。
と感じるのでしょう。 一方、"b"が返るべきだと感じる人は
  • JavaScriptの"var x"は変数xの有効範囲を関数内に限定する命令
  • varの付いていないのは限定されていない変数
  • 限定されていないってのはつまり、1枚外側のスコープってこと
という認識になっているのでしょう。 そういう実装の言語もありだと思います。 で、その場合
  • 「var foo = "c";」はローカル変数だから関数の外に影響を及ぼすはずがない。
  • でも「foo = "b";」は普通の変数なんだから、「var foo = "a";」と同じスコープ。
  • あれ?"a"って返ってくるぞ?
となるんじゃないでしょうか。

と勝手に憶測。

でもなんだかんだ考えた結果、JavaScriptもPythonと同じように 「varでスコープを限定したいのなら、最初の代入の時までに宣言しなければシンタックスエラー」 というようになればいいんじゃないかと思えてきました。 というわけで「え、エラー出すべきなの?」は撤回。


= うっ、これは後に代入された方が返るのか…。 これは気持ちが悪い…。当然"b"が返ると思ったのに…。
function inner() {
  var foo = "b";
  foo = "c";
  document.write(foo);
}
inner();
Pythonなら代入の順序にかかわらず"b"が返ります。
>>> def test():
	globals()["foo"] = "c"
	foo = "b"
	print foo
	foo = "b"
	globals()["foo"] = "c"
	print foo

	
>>> test()
b
b

ふうむ。 Core JavaScript 1.5 Guide:Variables - MDC: 「JavaScript の変数に関して独特なこととして、後に宣言される変数を例外を発生させることなく参照できるということもあります。」 っていう実装なのか。 仮に関数の冒頭でfoo = 1と書いてあっても、 もしかすると関数の最後にvar fooと書いてあるかも知れないから 全部読むまではグローバル変数かどうかわからないわけか。 一方Pythonはfoo = 1が出てきた時点でローカル変数に決定、 仮に後からglobal fooが出てきても構文エラー、と。 global fooが先に出てきたらfooはグローバル変数に決定、と。

Python流の方がいいと思うけど、 JavaScript流の方がインタプリタの実装が楽そうな気配。

2006年10月08日

ブログにコードを貼り付ける方法.js alpha0.2(Firefox only)

ブログにコードを貼り付ける方法.js alpha0.1の続編。コード中の<, >, &をエスケープしてPREタグで囲い、後ろにimgタグを貼り、onLoadからJavaScriptで書かれた関数を呼び出すことで、画面には適切な長さで折り返して見やすく表示しつつ、JavaScriptで生成されたcopyボタンを押すとソースコードがクリップボードにコピーされます。この時はもちろん、&lt;が<に戻された状態でコピーされます。

クリップボードにコピーするコードは最速インターフェース研究会 :: Firefoxでテキストをクリップボードにコピーする方法から、ソースコードを新しいウィンドウで開くコードはKazuho@Cybozu Labs: Ajax な HTML ページのソースコードを表示するから流用しました。

サンプル。

print "very loooooooooooooooooooooooooooooooooooooooooooong striiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiing & <html> tag"
コードは下記。

追記:"aaa".replace("a", "b")では最初のaしか置換されないんですねぇ。 "aaa".replace(/a/ig, "A")に変更しました。

続きを読む "ブログにコードを貼り付ける方法.js alpha0.2(Firefox only)" »

2006年10月07日

ブログにコードを貼り付ける方法.js alpha0.1

codearea.png←これを押すとTEXTAREAに変わる。

__ i d e a * i d e a - ブログにコードを貼り付ける方法で悩むの巻。最近僕も1行が長いソースコードを貼り付ける(例: Just Another Python Hacker, その3Just Another Ruby/Python Hacker,)のに、わざわざ改行してみたりtextareaを使ってみたり、と色々試行錯誤していたのですが、結局満足のいくできにならず。それならJavaScriptで、と思って試作したのが上のサンプルです。

最初のコードを<を&lt;に置換したりせずに直接貼り付けられないかと思ったのですが、preの中に貼り付けると、innerHTMLで取得した際に<br/>が<br>に置き換わるという現象が発生。それならとtextareaの中に貼り付けてみると、<の&lt;への変換も自動的に行われてラッキーと思ったのも束の間、IEで見ると改行が消えて1行になっていて使い物にならず…。むずかしいですねぇ。

やっぱり、手元で適当なツールで<のエスケープを行ってpreタグで貼り付けるのが一番なのかも知れませんね。textareaの中ならタグをエスケープしないでいいので楽かと思いきや、結局</textarea>が含まれている場合にはエスケープしなければ行けませんから。

後は、今はimgのonLoadで始動して、imgのaltをオリジナルのデータを保管する目的で使っていますが、もうちょっと何とかしたいですねー。

ソースコードは下記。 codearea.png←これを押すとTEXTAREAに変わる。

2006年09月30日

対応づけられたサイトの切り替えをするブックマークレット

Pythonドキュメントの日英マッピングをするGreaseMonkeyの続編。enjamapper。 これをブックマークしておいて、 http://www.python.org/doc/2.4/* か http://www.python.jp/doc/release/* のどちらかで実行すると、もう片方のサイトにジャンプします。

実行されると即ジャンプするブックマークレットにすることで、HTMLを書き換えないでよくなるので、ターゲットのHTMLに対する依存性がなくなりました。サイトの対応付けの設定を書き換えるだけで、ファイルの配置が同じサイト間ならPythonのドキュメントに限らずジャンプできます。

サイトの対応付けをカスタマイズしたい場合や、僕のサイトに誰かが進入してスクリプトを有害な物に差し替えてしまう危険性を避けたい場合は enjamapper.js をダウンロードして自分の好きなところにおいてください。

使い方の具体例。 例えばPythonドキュメントの和訳中に 「positional arguments」はどう訳すのだろうと思ったとします。まず、Googleのsite:オプションを利用して「positional arguments site:http://www.python.org/doc/2.4/」と検索します。そうすると英文Pythonドキュメント中の「6.21.1.3 What are positional arguments for?」という項目がヒットします。これを開いて、enjamapperブックマークを実行すると、これに対応する日本語のページ「6.21.1.3 固定引数とは何か」にジャンプします。「positional arguments」は「固定引数」と訳せば他のドキュメントと統一できるということがわかりました。

ソースコードは以下。

続きを読む "対応づけられたサイトの切り替えをするブックマークレット" »

Pythonドキュメントの日英マッピングをするGreaseMonkey

追記:これを改良して作った対応づけられたサイトの切り替えをするブックマークレットの方が便利かも知れません。


pyenjamapper。Firefoxを使っていて、GreaseMonkeyをインストールしていれば、このリンクをクリックするだけでインストールしてください。そうすると 2.2 Non-essential Built-in Functionsなどの英文ドキュメントのナビゲータの所に「Japanese」というリンクが表示されます。クリックすると日本語の2.2 非必須組み込み関数 (Non-essential Built-in Functions)へ飛びます。こちらにはEnglishというリンクが追加されていて、クリックすると英語の方のドキュメントに飛びます。

他のブラウザの人でもブックマークレットとして使えるかも。…でも、ブックマークレットにするなら「押したらリンク追加」より「押したらジャンプ」の方がいいですね。

以下ソースコード。

続きを読む "Pythonドキュメントの日英マッピングをするGreaseMonkey" »

古い記事タイトル一覧

凡例{ ●: 単一エントリーへのリンク, □: そこから最新記事までを一覧表示, ■: そこから最新記事までをwindow.openで開く}(comming soon)

2006年06月13日
 ■ □ By 西尾泰和 at 2006-06-13 16:26:57
2006年05月30日
 ■ □ By 西尾泰和 at 2006-05-30 15:42:22
2006年05月17日
 ■ □ By 西尾泰和 at 2006-05-17 20:48:42
2006年03月31日
 ■ □ By 西尾泰和 at 2006-03-31 23:32:53