質問: { v: 3 }とは書けません。 JavaScriptでは書けるのに。 なんでなんでしょうか?
回答: まず前提として、javascriptにおけるa = { v: 3 } というのはjavascriptのオブジェクトに関係している一方、 pythonにおける a = { v: 3 } というのはpythonの辞書に関係しており、書き方は似ていますが別物です。 そのうえで質問者さんの問題を整理すると、 1. javascriptでは、**初出の文字v**に関して var a = { v: 3 }; を実行しても特にエラーが出ませんが、 2. pythonでは**未定義の変数v**に対して a = {v: 3} を実行すると、 NameError: name 'v' is not defined というエラーが発生する。これはなぜか?という質問だと把握しました。 ただ、pythonでも、can110さんが結果を書いているように ``` v = "keystr" # <=文字列なら何でもいいです。 a = {v: 3} w = 100 # <=整数でもOK b = {w: 50} ``` というように、**先に名前(変数)を定義しておけば**、javascriptと同じように書いてもエラーが出ません (なお、必ずエラーが出ないわけではなく、辞書のキーは、文字列やタプルなど「hashableなものでなければならない」という条件があります) なぜこのような違いが生じるかですが、**ぶっちゃけていうと、言語が異なるから**、ということになるでしょう。 でもこれだと回答にならないので、以下は推測を交えて説明します。 ### javascript:「オブジェクト」との関係、ラクに速くスクリプトを書けること javascriptにおけるa = {v: 3}というのは、オブジェクトに対するプロパティの定義です。 これは ``` var a = new Object(); a.v = 3; ``` というように、オブジェクトを作ってから、vというプロパティに値を代入する形でも書けます。 javascriptでオブジェクトのプロパティに使用できるのは、一定の条件に該当する識別値か、引用符で囲まれた文字列、もしくは数値に限られるようです。(間違っていたらすみません) そして、プロパティ位置に置かれた識別値や数値は、**引用符で囲まなくても、自動的に文字列として解釈**されるようです。(※「1st_key」のように先頭が数字になっているものや途中に空白があるもの等は引用符を省略できません) つまり{v: 3} と書くと {"v": 3} と書いたものとして解釈されます。 var v = "keystr" としたあとで var a = {v:3};としても aは{"keystr": 3} ではなく、 {"v": 3} になります。 javascriptでは、わざわざ引用符を書かなくてもプロパティ位置に指定されたものを文字列として扱うことで、引用符を書く手間をなくしている(と私は推測しています) たった「"」2回といえど、何行も書くとなると結構時間の無駄になりますよね? 引用符のペアをそろえていないとエラーになりますし、 ``` var myBox = new Object; myBox = {front: {color: {type: 'high', 'code': '#ffffff'}}}; ``` というように、プロパティを引用符なしで定義でき、 ``` c = myBox.front.color.code; ``` と引用符なしでプロパティにアクセスできるのは便利です。 (pythonで外部ライブラリを使わず普通に辞書を使うとなると ``` myBox = {"front": {"color": {"type": "high", "code": "#ffffff"}}} c = myBox["front"]["color"]["code"] ``` とする必要があります) ### python:プログラムとしての直感性・柔軟性 上の例では、pythonでは一度定義した変数であれば、任意に辞書のキーとして指定できるように見えます。 (繰り返しますが「hashableなものしかキーにできない」という制約はあります) そのかわり、javascriptと異なり、未定義の変数に該当する文字列を文字列としてのキーに指定する場合は必ず引用符で囲まなければなりません。(でなければ上記のようにNamedErrorが出てしまいます) pythonの辞書はjavascriptのオブジェクトに比べると、記述に手間がかかる・・・? でも、この「変数を辞書のキーとして指定できる」という仕様は、メリットもあると思います。 プログラミングをやっている立場からすれば、引用符で囲まれていないものは、中身が必ずしも文字列とは限らないというのは日常茶飯事です。 javascriptの例のように var v = "keystr" としたあとで a={v:3}としたら aは{"keystr":3} ではなく、 {"v":3}‘となってしまうのは、直感に反するような気がしませんか? 辞書のキーに(hashableなものに限りますが)変数を指定できるからこそ ``` if 64 < i < 64 + 26 + 1: a = {chr(i): i} else: a = {"DUMMY": 0} ``` とか ``` s = {chr(i): i for i in range(65, 65 + 26)} >>> print(s) >>> {'A': 65, 'B': 66, 'C': 67, 'D': 68, 'E': 69, 'F': 70, 'G': 71, 'H': 72, 'I': 73, 'J': 74, 'K': 75, 'L': 76, 'M': 77, 'N': 78, 'O': 79, 'P': 80, 'Q': 81, 'R': 82, 'S': 83, 'T': 84, 'U': 85, 'V': 86, 'W': 87, 'X': 88, 'Y': 89, 'Z': 90} ``` のような柔軟なプログラミングが可能になります。 ※もちろんjavascriptでも、 ``` var a = new Object(); var k = 'DUMMY'; a[k] = 0; //a['DUMMY'] = 0; または a.DUMMY = 0; と同じ ``` というように、連想配列を使うことで同じようなことはできます。 pythonでも、attrdictという外部ライブラリを使うことで、辞書をドットでアクセスすることは可能です。 以上、つらつらと書きましたが、あくまで私自身の推測によるところが大きいですので、もっと深遠な理由があるやもしれません。 参考にしたもの: MDN オブジェクトでの作業 Python における hashable 連想配列を使ったプロパティへの値の代入と参照 Pythonで辞書のキーにtupleが指定できた件(+パフォーマンスの話)