スコープ外の変数には宣言&代入がOK
関数内のグローバルに宣言&代入がNO
ローカル変数に宣言&代入がOK
関数内でグローバル変数に宣言と当時に代入できない仕様の意図が理解できません
誰か教えて下さい
aaa=[]//ok def method(): global a//ok global aa=[]//SyntaxError aaaa=12//ok
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

回答4件
0
ベストアンサー
これ、「仕様の意図」という切り口で追うとめっちゃ難しい質問ですよ。
まぁ兎にも角にもまずは、globalと同じような位置づけで追加された時期が新しいnonlocalについて実装の経緯(PEP)を探してみました。で、やっぱりPEPがありました。
PEP 3104 -- Access to Names in Outer Scopes
そうすると驚くことにこのPEP-3104のProposed Solutionには、
A shorthand form is also permitted, in which nonlocal is prepended to an assignment or augmented assignment:
nonlocal x = 3
nonlocal_stmt ::= "nonlocal" identifier ("," identifier)* ["=" (target_list "=")+ expression_list] | "nonlocal" identifier augop expression_list
と記述されていました。でもこのshorthand form(短い書き方)はPython 3.7で試してもSyntaxErrorですし、何よりGrammer的にもそのような書き方は許容されていないので、このPEP-3104の内容とPythonの実装実体が異なるという奇妙な事態が発生しているように見受けられます。そこで私はこのPEP-3104がRejectされた代物なのかと思って確認してみましたが、ココを見る限りそうでもないようで最初は私も状況がうまくつかめませんでした。でもPEP-3104をちゃんと読むと、
Note
The shorthand syntax was not added in the original implementation of the PEP. Later discussions [29] [30] concluded this syntax should not be implemented.
と書いてありました。そして以下2つの内容を確認すると最終的にはGuido van Rossumの発した一文にその「仕様の意図」がありました。
- [29] Issue 4199: combining assignment with global & nonlocal (Guido van Rossum)
- [30] Whatever happened to 'nonlocal x = y'? (Guido van Rossum)
I think it's needless added complexity (それは不必要に追加された複雑性だと私は考える)
that helps save one line of code in very few use cases. (【ちょっと意訳】非常に限られた局面でコードを1行短く書けるようにするという複雑性)
nonlocal x = 3
やglobal aa=[]
と書けるようにしないことによってPythonの中に守られるsimplicity(シンプルさ)があるということなんだと思います。書く側がglobal aa=[]
ではなくglobal aa; aa=[]
と書くほうが多分Pythonicなんだと思います。
投稿2019/01/12 14:38
編集2019/01/12 14:53総合スコア6149
0
関数内でグローバル変数に宣言と当時に代入できない仕様の意図
個人的な推測にすぎず、どこかでその根拠を見聞きしたわけではないですが・・・
Pythonの代入文は結構複雑な構文と機能を持っています。
https://docs.python.org/ja/3.7/reference/simple_stmts.html#assignment-statements
特に複数の変数に対して一つの代入文で値を設定できる点を考えますと、仮に「global/nonlocal宣言」と「代入」を同時に許すなら仕様の連続性(整合性)から
a, global b, nonlocal c = 1, 2, 3
global (a, b), nolocal (c, *d) = 1, 2, 3, 4, 5
なぁんて代入文もゆるさなくてはならず、(できなくはないのでしょうが)どれがglobal(あるいはnonlocal)なのか少々見づらいため、もともと変数を宣言せずにいきなり代入するのが普通なpythonでglobal/nonlocalという特殊な変数宣言だけのために代入文の構文をこれ以上複雑にしたくなかったのではないかと思いました。
さらにいえば、代入に付けられるなら「参照と宣言を同時に行う」ようなことを望む人がでやしないでしょうか?それがわるい構文かどうか総合的に言えるほどの知見がないですが、それを導入してしまうと構文規則がややこしいことになりそうな予感はします。
python
1def foo(): 2 ... 3 a = global g # うわぁ・・・ 4 a += 1 5 g = a * 2
また、Pythonの変数スコープは主として関数全体にわたる(lambda式の仮引数や内包表記やジェネレーター式など一部そうでないものがあるが)が基本であり、
python
1def foo(): 2 i = 0 3 for i in range(10): 4 print(i) 5 print(i)
上記のiのように有効範囲が広くなりがちなので「なるべくなら関数先頭に変数の種類の宣言のみ行う」方が見やすい(分かり易い)という狙いがあったのかも知れません。
投稿2019/01/12 14:54
編集2019/01/12 16:07総合スコア18404
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
grobal付きは、変数宣言ではなく、グローバル変数を参照する定義、なので初期化できません
変数宣言してるところでしか初期化できません
投稿2019/01/12 13:23
総合スコア88163
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

0
構文リファレンスを見てください。
https://docs.python.jp/3/reference/simple_stmts.html?highlight=global#the-global-statement
構文の定義
global_stmt ::= "global" identifier ("," identifier)*
意味
global 文は、列挙した識別子をグローバル変数として解釈するよう指定することを意味します。
代入できない理由ですが、そもそもpythonのスコープはレキシカルスコープといって構文を見ればスコープが決定されるような仕様になっています。なので、global
文は構文解析の時点で処理されます(リファレンスにもそう書いてある)。
代入文はもちろん実行時に実行されるので、一緒に処理できないですね。
ところで質問文のコード、method
といいつつやっていることはトップレベル関数の定義なので、function
とでもした方が個人的には好みかな・・・
投稿2019/01/12 13:52
総合スコア30939
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/01/12 15:05
2019/01/12 15:14