質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

9回答

3867閲覧

なぜpythonにはCライクなfor文がないのか?

ruei

総合スコア284

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

2グッド

4クリップ

投稿2018/10/10 09:02

3か月ぐらいしかpythonを使っていないビギナーの疑問なので、
本当のpythonの良さが分かっていないのだと思いますが、
どうしてpythonにはC言語ライクなfor文がないのでしょうか?

0から10まで回すためのfor文
1から10までを回すためのfor文
1から10までを0.1刻みで回すfor文
複雑な終端条件のfor文
10から1まで回すfor文
...
などなど
それぞれについてGoogle検索して目的のfor文を探す必要があります。
(それとも慣れると大丈夫なんでしょうか)

例えば1から10まで0.1刻みで回すfor文の場合

for i in range(1,11,0.1):

となりますが、これでは1とか11とか0.1が何を指しているかよく分からないし。
ちょっと複雑なfor文を書こうとするとすぐにGoogle検索する必要が出てきます。
メリットは何なのでしょうか。

yohhoy, set0gut1👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

gm300

2018/10/16 00:58

ちなみに、複雑なfor文とはどのような形のものでしょうか。
ruei

2018/10/16 01:48

ぱっと思い付くのだと、繰り返し二乗法のfor(;n>0;a*=a,n/=2)とか部分集合t内でのbitdpのfor(s=0;s<1<<n;s=(s-1)&t)とか他にも色々ありますね
guest

回答9

0

どうしてpythonにはC言語ライクなfor文がないのでしょうか?

C

1for (ループ初期化; ループ継続の判定; ループ継続時の追加処理) { 2 /* ループ本体処理 */ 3}

C言語ライクなfor文 = ループ初期化+ループ継続の判定+ループ継続時の追加処理 は、良くも悪くも 自由度が高過ぎる ため、Pythonに限らずモダンなプログラミング言語では採用されないことが多いように思います。C言語との互換性・類似性が重視される場合は、C言語ライクfor文 Python的for文(foreach文)の両方が提供されるように思います。

また別の観点では、次のような違いがあります:

  • C言語ライクfor文 = 手続き的・どのように反復処理するか(HOW)
  • Python的for文 = 宣言的・何についての反復処理か(WHAT)

C言語ライクfor文は(C言語自身の古さもあり)どちらかと言えばコンピュータ寄り=「CPUで具体的に 何をする のか」という観点で記述されます。一方で、Python的for文はプログラマが「私(人間)は抽象的に 何をしたい のか」という観点で記述します。

例)リスト構造に含まれる全要素を列挙したい場合:

  • C言語ライクfor文 = ポインタ型の宣言や、リンクノード間を辿るコード記述が必要
  • Python的for文 = 直接的に「リストを走査する」処理を直接コード化できる

このような抽象化は、「イテレータ(iterator)」という仕組み・パターンを介して実現されます。プログラマの慣れの問題はありますが、一般的には後者の方がモダンで好ましいというトレンドにあります。


Pythonチュートリアル - for文より引用:

Pythonのfor文は、読者がC言語やPascal言語で使いなれているかもしれないfor文とは少し違います。(Pascalのように) 常に算術型の数列にわたる反復を行ったり、(Cのように)繰返しステップと停止条件を両方ともユーザが定義できるようにするのとは違い、Pythonのfor文は、任意のシーケンス型(リストまたは文字列)にわたって反復を行います。

投稿2018/10/10 09:55

yohhoy

総合スコア6191

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yohhoy

2018/10/10 10:00

欄外コメント:プログラミング言語の能力には「A)やりたい事は何でも出来ること」「B)やりたい事を簡潔に表現できること」の2種類があると考えています。C言語ライクfor文はA)を満たしますが、B)からは程遠く、可読性の低い難解なコードも書けてしまいます。Python的for文はB)を重視した言語デザインとなっており、これは「あえてプログラミング言語の自由度を制限すること」で達成されています。
guest

0

Cのfor文とpythonのfor文は、見た目は似ているようでかなり別のものだと思った方がいいと思います。Cにおいて、

C

1for(A;B;C){ 2 // 中身 3}

というのは、結局

C

1A 2while(B){ 3 // 中身 4 C; 5}

というのと同じですかね。つまり、まずAで初期化して、Bという条件が満たされている間、 中身のコード+Cを繰り返し実行する、という繰り返しを指示したものだと思いますが、pythonではあまり繰り返しということは意識されない気がします。pythonのfor文の一般形は

python

1for x in iterable_object: 2 do_something(x)

という感じです。iterable_objectというのは、何かしら1つずつ取り出してこれるオブジェクトです。(詳しくは、__iter__というメソッドを正しく実装しているものです。)組み込み型ではlist(配列)やrangeはもちろんのこと、set, dictなどが該当します。pythonのfor文では、このiterable_objectから一つずつ何か取り出して、それに対して何か操作をします。そして取り出し終わるか、breakが実行されたら、for文は終了します。
pythonのfor文のメリットは、配列などの中身を直接取り出すことができることだと思います。Cの場合は、配列の長さより小さいうちは、などという条件をつけてインデックスを一つずつ大きくし、arr[i]として配列の中身にアクセスしていく必要がありますが、pythonの場合は、単に

python

1for x in arr: 2 do_something(x)

とすれば良いのです。配列の中身を取り出すために、インデックを初期化したり、停止条件をつけたりという余計なことを考えなくても良いわけです。
複雑なfor文を書きたいときは、みなさんおっしゃるようにwhileを使えば良いと思います。つまり

C

1for(A;B;C){ 2 // 中身 3}

python

1A 2while B: 3 # 中身 4 C

と書けば良いです。でも、上に述べたようなpythonのfor文の特徴(一つずつ何か取り出してきて実行する)という特徴をうまく使えば、こういう構文はあまり必要にならないと思います。

投稿2018/10/10 09:57

moch

総合スコア122

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ruei

2018/10/10 11:35

ありがとうございます。 もしかして、for i in range(10): というのは、 int[] arr=new int[10]; for(ini i=0;i<10;++i) arr[i]=i; for(int i:arr){ } と同じということですか。 arrの長さが長いと、メモリ大変なことになりませんか。
moch

2018/10/10 11:50

ちょっと違います。range(10)というのはrangeというオブジェクトで、listとは異なります。具体的に何が違うかというと、例えばa = [0, 1, 2, ...,9]というリストは、0から9までの値をすでに持っているのですが、range(10)は、そう書いた段階では、中身がありません。それでも、 for i in range(10): ...コード... と書くと、iの中に順次0, 1, 2...を入れて行ってくれます。 Cで対応するのは for(ini i=0;i<10;++i){...コード...} になると思います。 rangeの中で、(ini i=0;i<10;++i)みたいなことをやって、iを順次差し出してくれると思って良いかと。(pythonの実装をちゃんと知っている訳ではないのでおそらく、という感じですが。) python2系にはrangeとxrangeというのがあって、その頃range(10)と書いたら、本当に[0,1,2,...,10]を作っていたので、xrange(python3のrangeに相当)を使った方が、メモリ的に良いということだったと思います。
ruei

2018/10/10 12:02

ありがとうございます。 ちょっと疑問に思ったのですが、for文の中でiを変な値(例えばfloatにキャスト)にすると、ループは壊れるんでしょうか。
moch

2018/10/10 12:06

そこら辺は全く自由な感じです。 for i in range(10): i = 'hello' print(i) とかでも動きます。
ruei

2018/10/10 12:23

ええ...自由すぎる。 ありがとうございます。
guest

0

どうしてpythonにはC言語ライクなfor文がないのでしょうか?

イテレータを利用する方がモダンなのかと。
実際に最近の~~C/~~C++では、範囲ベースfor文が積極的に使われているかと思います。
(**修正: ** Cでは範囲ベースfor文は使えないようです。)

確かにCライクのfor文が欲しくなる時もありますが、そこまで不便さは感じないですね。

0から10まで回すためのfor文

1から10までを回すためのfor文
1から10までを0.1刻みで回すfor文
10から1まで回すfor文

全て range(start, stop, step) で対応可能です。

複雑な終端条件のfor文

while True で無限ループし、条件に合うとき break すれば良いです。
場合に依っては itertools.count も便利です。


だいたいこの手の疑問はデザインと歴史を調べれば解消するのですが、載っていないですね。

投稿2018/10/10 09:07

編集2018/10/10 09:20
LouiS0616

総合スコア35660

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ruei

2018/10/10 09:25

while Trueで無限ループして、条件に合うときbreakすればよい そう書くしかないのでそう書くのですけど、なんか気持ち悪いので、そのたびにfor(;;)文で書けないかというのを(以前検索したのを忘れて)Google検索し、whileで書くしかないとなっています...。 全て range(start, stop, step) で対応可能です。 その通りなのですけども、、、9割はrange(stop)で間に合うので、range(start,stop,step)の使い方を忘れてしまうのですよね…。 範囲ベースfor文は舐める配列があるので、感じる印象は全然違います・・・。 fortranもpythonみたいなfor文なのでこちらのほうがスピードが出るのかなと思ったり。
LouiS0616

2018/10/10 09:31

> whileで書くしかないとなっています...。 Pythonでは while True を多用します。そのうち慣れると思います。 > range(start,stop,step)の使い方を忘れてしまうのですよね…。 与える値の順序がスライスと同じなので、これは覚えた方が良いです。 忘れてしまっても、リファレンスだけすぐ引けるようにしておけば解決出来ます。 > 範囲ベースfor文は舐める配列があるので、感じる印象は全然違います・・・。 イテレータを取得して巡回しているので、内部の動作はC++と同じです。 rangeオブジェクトがイテラブルであることさえ知っていれば。 > fortranもpythonみたいなfor文なのでこちらのほうがスピードが出るのかなと思ったり。 速さを追求する言語じゃないですし。
guest

0

rangeの仕様を覚えれば、とりあえず大抵のインデックスループに対応できます。

どうしてもCライクなforがほしければ、whileで同様のことを実現しましょう。


なぜpythonにはCライクなfor文がないのか?

以下憶測。

Cスタイルのforってかなり滅茶苦茶なことができる構文です。カンマ演算子と代入で自由自在に難読コードを生成できます。

それを嫌ったというのは大いにありそう。

あと、単純に構文上なじまない気がします。文のヘッダで「代入文」を実行するというのも気持ち悪いですし。

投稿2018/10/10 09:30

hayataka2049

総合スコア30933

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ruei

2018/10/10 11:54

確かにpython の構文と馴染まないのはありそうです。ありがとうございます。
guest

0

c

1for (int i = 0; i < 10; i += 1) { 2}

と、

python

1i = 0 2while i < 10: 3 i += 1

に、どれほどの違いがあるというのだろう?
むしろPythonの方が文字数少ないというのに。

投稿2018/10/10 09:20

fuzzball

総合スコア16731

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ruei

2018/10/10 09:44

前者を読むのに、脳のMPは要らなくて、後者を読むのには脳のMPが必要だというところですかね。
ruei

2018/10/10 09:47

自分の場合、前者だと、バグった時にfor(;;)のほうは疑わないんですけど、i=0,while i<10,i+=1のほうは自分がミスしていないか疑うと思います
guest

0

たしかに自分も C++ から来たので、for(;;) スタイルの構文がないのは戸惑いましたが、慣れの問題です。
次の2パターンだけ抑えておけば、大丈夫かと思います。

パターン1 数値の範囲 for

c

1for(TYPE i = begin; i < end; i += step)

は以下と読み替えます。

python

1range(begin, end, step) 2# float の場合は 3numpy.arange(begin, end, step) # range() の上位互換

パターン2 数値の範囲以外の for

python

1while 条件: 2 # 処理

投稿2018/10/10 09:14

tiitoi

総合スコア21956

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

逆に、なぜCにはPythonライクなfor文がないのか、を考えてみましょう。

その答えは、PythonはCではないから。ということになろうかと思います

for(i=1;i<11;i++){}
は何を指してるかよくわからない、と、Python屋さんに言われたら、納得させることのできる説明ができるでしょうか。

まあ、そういうことです

投稿2018/10/10 09:09

y_waiwai

総合スコア87774

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

参考情報

  • Pythonのfor文によるループ処理(range, enumerate, zipなど)

https://note.nkmk.me/python-for-usage/

本当は、逆になぜ C では あのような for 構文が用意されたか? を考えるべきかもしれません。

i++ や ++i は機械語のそのまま落とせる表現です。
fortan での繰り返し構文は do 変数=初期値,最終値[,刻み幅] でした。(web 検索して調べました)

投稿2018/10/10 12:35

編集2018/10/15 15:32
katoy

総合スコア22324

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

C言語のfor文の自由度が高すぎる点のひとつに

C

1for(i=0;i<10;++i){ .... }

と書いた場合、....の部分でiの値を書き換えられることがあります。この場合の動作が読みにくい。

投稿2018/12/24 13:07

myoon

総合スコア100

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問