No.4ベストアンサー
- 回答日時:
> 最後はどういう意味ですか?
う〜ん・・・正直、説明がメンドくせぇんだよなぁ(苦笑)。
ええとね、敢えて差別的に言いますが、この世には「マトモなプログラミング言語」と「スクリプト言語」の二つがあります。
その他にもあるんですが、現代では「超古代的」なんで殆ど生き残っていません(BASIC、とか例に挙げられても困るだろうし)。
ALGOLって言語があって、現代の「マトモなプログラミング言語」はこの言語が持ってるレキシカルスコープと言う機能が持ち込まれています。
プログラムの最小構成は「ブロック」と考えて良いのですが。
例えば関数はブロックを作るし、forやwhile、あるいは条件分岐のif等もブロックを形成しますが、ALGOLの影響を受けた言語はブロックは同時にレキシカルスコープを形成するようになっています。
レキシカルスコープと言うのはある変数が生成された時にその変数の有効範囲はその変数が置かれたブロックに限る、と言う約束の事です。
例えば、往年のANSI Cだとパッと分かる結果にはなってなかったのですが、今のC、要するにJISが持ち込んでるISO C99だと、
int func(void) {
for (int i = 0; i < 3; i++) {} // ここでforブロック内で変数iを生成する
return i; // しかしここのiはforブロック外なので、for内でのiは参照出来ない
}
こういうコードを書くとエラーになります。
レキシカルスコープの重要な性質として、ブロック内からその外に変数を探しには行けるんだけど、逆に外からは「同名でも」変数を探しに行く事が出来ない。
ついでにもう一つ試してみましょう。
void func(void) {
int i = 0; // ここで変数iを宣言する
for (int i = 0; i < 3; i++) {} // ここでも変数iを宣言するがブロック外のiとは別物になる
printf("%d\n", i); // ここのiは何でしょう?
}
これはエラー無しでコンパイルされますが、さて、iの中身は・・・?
今までのレキシカルスコーピングのルールを把握してればiは0だ、と言う事が分かるでしょう。最初に宣言された通りiは0になる。
重要なのは、forブロックを形成したトコで宣言されたiは、外側にある、関数funcが形成するブロックのiとは「同名でも別物」だと言う事です。
これがALGOL影響下にある「マトモなプログラミング言語」の動作です。ブロック毎に変数を宣言した場合、その有効範囲はそのブロック内だけに限る、と言う事です。
そして内側のブロックで使われてる変数がブロック内で定義されてない場合、「外側のブロックに」その変数が定義されてるかどうか探しに行きます。
逆に外側から内側へとは探しに行けない。それがレキシカルスコープのルールです。
一方、一般的に言うと、Pythonを始めとする通称「スクリプト言語」と呼ばれる言語群は・・・まぁ、正式な定義ではないんですが、いずれにせよ大体のケースでは
・関数はレキシカルスコープを伴うブロックを形成するが、forやwhile、あるいは条件節(if)等のブロックはレキシカルスコープを伴わない
と言うのが見られます。
例えば最初のC言語のエラーが出るコードだとPython版はエラーにならず実行出来ちゃうんですよねぇ。
def func():
for x in (0, 1, 2): # forブロック内でxを宣言する
x
return x # forブロック外でもforブロック内で定義されたxを使える
つまり、Pythonに於いてはforブロックはレキシカルスコープを形成しない。
言い換えると内側にあるブロックで定義された変数はその外側からでも丸見えだ、と言う事です。
つまり、ブロックをまたいで同名の変数を使用する、と言う場合、Pythonでは貴方が考えるように、まさしく「同名の変数」が不用意に書き換えられちゃう可能性があるので、危険だ、と言うのはある種当たってはいるんですよ。
だから上のコードをちょっと改造して、
def func():
x = 0
for x in (0, 1, 2):
x
return x + 1
みたいにすると思わぬ結果を招くかもしんない。なんせxはガードされてないから、です。
同じようなコードをCで書くと
void func(void) {
int i = 0;
for (int i = 0; i < 3; i++) {}
printf("%d\n", i + 1);
}
となりますが、結果は違います。Cの場合はforが作るブロックはレキシカルスコープでガードされてるので、外に置かれた変数iとは何も関係がない。
だから両者は結果が違います。
んで、Pythonでforをいくつも同名の変数を使って回したい、ってのは結論から言うとO.K.です。何故ならforを使う前提だとそのループ用の変数は「書き換えて使う」ってのが前提なんでO.K.なんですよ。
むしろ危険なのは上で紹介したような例。forが作るブロック内で作った変数と「それ以外の関数の地」の部分では変数名を変えた方が良い、って事です。
今まで見てきたように、C言語のようなALGOL影響下の「マトモな」プログラミング言語だと、ブロック内の変数はレキシカルスコープでガードしてくれるんで、同名変数を使っても構わないんだけど、Pythonはその辺が全く信頼が置けない、と言う事です。
No.3
- 回答日時:
一時的な回数カウンターとして使うものであれば、同じもので構いません。
スコープの範囲内のみ有効な変数になります。
https://atmarkit.itmedia.co.jp/ait/articles/1905 …
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- 英語 現在完了の「継続」ではなく「経験」の期間を表す前置詞について 2 2022/05/06 11:39
- その他(プログラミング・Web制作) ColabでのPytorchのエラー 1 2022/11/19 20:51
- 英語 分離不定詞 1 2023/07/16 17:29
- TOEFL・TOEIC・英語検定 英検準1級英作文の添削をお願いします。 ポイントはCurriculumとGlobalizationを 4 2023/05/29 11:33
- C言語・C++・C# 変数のスコープ 5 2023/05/27 17:50
- その他(プログラミング・Web制作) Pythonでこのプログラミングを作りたいのですが 1 2022/10/24 18:56
- 英語 「~, such as, for example,~」例示表現を並べる意図について 2 2022/07/04 18:43
- 英語 文法的解釈を教えてください 1 2023/06/22 10:05
- 英語 In adults, the ratio is about two to three times a 1 2023/01/17 17:39
- その他(プログラミング・Web制作) Pythonでこのプログラミングを作成するには 2 2022/10/25 21:19
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C言語、C+、C++、C#の違い
-
質問失礼します。 プログラム言...
-
Pythonって何を意識した言語な...
-
C言語とhtmlの違いを どな...
-
最新のプログラム言語を学ぶに...
-
COBOLで文字タイプを数字...
-
プログラムに書かれる"%"記号の...
-
TO_CHARで小数点以下がある場合...
-
C++ ってなんて読む?
-
COBOLでのNOT = の AND条件
-
プログラミング言語の制作方法...
-
C#とC++のざっくりとした違いを...
-
UNITY Float型の接尾辞fって
-
VBSとWSHは読み方が違うだけで...
-
Solve()とは、なんですか?
-
C++における継続行
-
Excelの開発言語ってなんですか?
-
C言語って古いですか?
-
Int('1234') で、strをかんたん...
-
アプリ開発について 初心者です...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C言語、C+、C++、C#の違い
-
質問失礼します。 プログラム言...
-
最新のプログラム言語を学ぶに...
-
COBOLでのNOT = の AND条件
-
C言語って古いですか?
-
rpa化する言語としてら何があり...
-
UNITY Float型の接尾辞fって
-
TO_CHARで小数点以下がある場合...
-
プログラミング言語の制作方法...
-
COBOLで文字タイプを数字...
-
プログラムに書かれる"%"記号の...
-
C言語とhtmlの違いを どな...
-
Int('1234') で、strをかんたん...
-
C++ ってなんて読む?
-
Excel VBAで文字化けする (英語...
-
C言語 解答について。
-
VBSでDim、Private、Publicの違い
-
Excelの開発言語ってなんですか?
-
C# でソフト開発をした事のある...
-
C#とC++のざっくりとした違いを...
おすすめ情報
for 文はそれぞれ独立していて二重になったりしていないです。初歩的で小さいことだけど、大切だと思います。