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

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

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

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

Q&A

解決済

2回答

2027閲覧

Pythonのsumよるテキストファイルの行数カウント方法の仕組みについて

Bicepper

総合スコア11

Python

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

0グッド

0クリップ

投稿2018/01/05 07:36

###前提
sumによるテキストファイルの行数カウント方法の仕組みが知りたい

お世話になります。
テキストファイルの行数をカウントしようと思い、当初は以下の方法で実装していました。

###実装ソースコード

python

1f = open('text.txt', 'r') 2string = f.readlines() 3print(len(string))

ところが、調べているうちに、以下の方法でもカウント可能なことがわかりました。

###第三者のソースコード

python

1print(sum(1 for i in open('hightemp.txt', 'r')))

参考:How to get line count cheaply in Python?

###疑問・試したこと
率直に申しまして、このsumによるカウント方法の仕組みが知りたいです。
なぜこれでカウントできるのでしょうか。
簡単な検証方法として以下を試しました。

python

1test = ['a', 'b', 'c', 'd', 'e'] 2 3print(sum(1 for i in test)) 4# 結果:5 5print(sum(2 for i in test)) 6# 結果:10 7print(sum(3 for i in test)) 8# 結果:15

###個人的に導き出した結論
「ジェネレータ式で生成されたジェネレータオブジェクトの総数にforの前に書かれている数を掛け合わせた結果が出力」
上記の理解で正しいのでしょうか。
Python初学者のためsumの動き、ジェネレータ式の動きをしっかりと把握していない部分もあるかと思います。
至らぬところがあると思いますが、誤解、間違い等の箇所があれば是非ご指摘いただきたいです。
よろしくお願いいたします。

参考:組み込み関数:sum

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

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

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

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

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

guest

回答2

0

python

1a = [1 for i in range(5)] 2#[1,1,1,1,1] 3sum(a) 4#1+1+1+1+1=5

sumするとジェネレータがStopまで実行されて、要素の数だけ1を足し合わせていることになります。


サイズがよほど大きくないとプロセスを立てるほうが時間を食うので、なんとも言えませんが、

python

1import subprocess 2run = subprocess.getoutput 3t = run('wc -l {0}'.format(filename)) 4print(t) 5l = int(t.split()[0]) 6print(l)

投稿2018/01/05 07:44

編集2018/01/05 07:48
mkgrei

総合スコア8560

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

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

Bicepper

2018/01/05 08:10

回答ありがとうございます。 「forの前の数が要素数分足されていく」ということなのですね。 理解が間違っていました。ありがとうございました。
mkgrei

2018/01/05 08:24

5.4G/977674行のファイルについて行数を数えてみたところ、 sumを使った方法だと~3.47s wcを使った方法だと~0.52s になりました。 ファイルが大変大きい場合はPythonで頑張らないほうがよいのかもしれません。
Bicepper

2018/01/05 08:55

コメントありがとうございます。 すみません、まだそこまで発想を展開させることができなかったのですが、読み込むファイルサイズのことも考慮すると、subprocessでwcを使用した方が無難、ということでしょうか。 大変勉強になります。検証もしていただきありがとうございました!
quickquip

2018/01/05 23:23

「だいたいこのぐらいという数がわかればいい」か「後続のPythonの処理のために必要な値」なのか気になりました。前者ならいいですけど、Pythonでイテレートする回数とwcの結果は違うものであって、数が違うことはありえますので。
mkgrei

2018/01/06 02:09

quiquiさん、コメントをありがとうございます。 wcは\nの数を数えるので、Pythonのイテレート回数より1だけずれるケースがありますね。
Bicepper

2018/01/06 03:27

quiqui様、mkgrei様 コメントありがとうございます。 もともとこの疑問に至った経緯が、以下のサイトの「10.行数のカウント」問題を解いていたためでした。 http://www.cl.ecei.tohoku.ac.jp/nlp100/#sec10 後続があるわけではないですが、「行数をカウントせよ」と明確な数を求めていますので、どちらかというと後者になります。
guest

0

ベストアンサー

ちょっと奇をてらった書き方に見えます。
理解のために、適当にsumを模した関数を作ってみましょう。

Python

1def my_sum(it): 2 total = 0 3 for elem in it: 4 total += elem 5 return total 6 7my_sum([0, 1, 2, 3, 4])

つまり、問題のコードは、次のように書いているのと結果的には同じです。

Python

1total = 0 2for _ in open(hoge, 'r'): 3 total += 1 4print(total)

これならわかりますかね。

投稿2018/01/05 07:46

編集2018/01/05 08:05
LouiS0616

総合スコア35658

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

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

Bicepper

2018/01/05 08:11

回答ありがとうございます。 sumの動きについてよく理解できました。 ありがとうございました。
mkgrei

2018/01/05 08:27 編集

元のリンクがとても大きなファイルを一気に読みこまずに行数を数える方法についてだったので、一応モチベーションはわかります。 内包表記のように書くことによってどれほど加速できるのかは測定してみないとわかりませんが。 追記:内包表記によって全く早くなりませんでした。素直にfor文で足すのと同じですね。
LouiS0616

2018/01/05 08:38

Pythonなら行数くらいちょいちょい取得できるかと思いましたが、案外モロな関数はないみたいですね。 mkgreiさんの回答のようにするのが現実的そうです。
Bicepper

2018/01/05 08:57

mkgrei様、LouiS0616様 コメントありがとうございます。 大変勉強になりました。
LouiS0616

2018/01/06 06:05

他言語に影響された書き方、ということでしょうか。 Haskellは全く書いたことがないですので、非常に新鮮な感じです。 実行速度がほぼ同じとなると、メモリを食わない分sumを用いた方法の方が有益なのかもしれませんね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問