実現したいこと
sample.txtは次のようなファイルです。
0 #num
1 #a[1]
2 #a[2]
3 #ns
0、1、2、3これらの変数は入力パラメータで、変数の説明のために「#以下の部分」を残したいです。このファイルを読み込みたくて、「該当のソースコード」を書きました。(昔に作ったコードなので、参考にしたサイトのURLは分かりませんでした。申し訳ありません)
行数も比較的少なく、正しく動きます。しかし、このような問題に出会ったときに「該当のソースコード」は自然なコードなのか、皆様がどのようなコードを書かれるかが気になりました。もっと自然なコードがあれば教えてください。(「自然」をどう考えるかが難しいですが・・・)
該当のソースコード
python
1a = [0 for i in range(3)] 2 3with open("sample.txt", "r", encoding="utf-8") as f: 4 list = f.readlines() 5 6para= [] 7for i in list: 8 word = i.split() 9 para.append(word) 10 11num = para[0][0] 12a[1] = para[1][0] 13a[2] = para[2][0] 14ns = para[3][0] 15 16print(num) #0 17print(a[1]) #1 18print(a[2]) #2 19print(ns) #3
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

回答7件
0
データの扱いの要件がわからないのでどうすればいいかは全くわかりませんが、一点、気になったところだけコメント。
データの分割にsplitを使うのは悪手だと思う。 コメントにスペースが含まれていたら、正常に分離できません。コメントが固定なのであれば、それは、とっておく意味がないし。
「#」の前の数値がデータで、以降がコメントだとすると、たとえば正規表現で分離。
python
1import re 2 3para =[] 4with open("sample.txt", "r", encoding="utf-8") as f: 5 for l in f.readlines(): 6 m = re.match(r'^(\d+) *#(.*$)', l) 7 if m: 8 para.append({'value': int(m.groups()[0]), 9 'comment': m.groups()[1]}) 10 11print(para)
データによってはfloatにしたいとかは、仕様がわからないので対応不能。
投稿2025/08/12 07:09
総合スコア14588
0
回答はいくつかついていますので、
このような問題に出会ったときに「該当のソースコード」は自然なコードなのか、
について。
問題(やりたいこと)を正しく文章化して、それをコード化するのが良いです。
一般的な言い方をすると、「プログラムの仕様を決めてからその仕様に合わせてコーディングしましょう」ということです。
質問のコードだと、split()
で分解してその[0]
をデータとして取得してます。
このコードから、「やりたいこと」を予想して復元すると、
「各行を空白文字で分割して、各行の最初の非空白の塊を文字列型として取り出す」
ですが、これが本当にやりたいことであれば、これで良いです。
ただ、質問文章を読むと「行中に#
があれば#
以降を無視して(削除して)、#
より前の部分を(前後の空白を削除したうえで)文字列型として取り出す」がやりたいことに見えるので、もしそうであれば、このコードはやりたいことをストレートに反映してないので、良くないです。「#
以降はコメントである」という認識で1#コメント
という#
の前に空白が無いデータを作ってしまうと破綻します。
あるいは、「#
の後に、代入したい変数名が書いてあるので、その変数に代入する」がやりたいことなら、全然違うコードになります。cametanさんの回答はそういう方向ですね。
まあ、「今、目の前にあるこのデータだけで正しく動けばいい」という使い捨てプログラムなら設計段階から手抜きして問題ありません。今回のデータだと、「空白で区切った1つめ」と「#
以降(と空白)を無視」は同じなので、そこを明確にせずに進めるということです。ただし、再利用されないようにちゃんとプログラムを削除しておきましょう。
一方、使い捨てでないプログラムの場合、「今回はこういうデータだけだけど、今後~~という形式のデータもあり得るので、そういったときにも無修正で対応できるといい(or簡単な修正で対応したい)」ということであれば、それも含めて「やりたいこと」ですから、それに応じたコードにします。
投稿2025/08/15 11:57
総合スコア86395
0
pythonのテクニックに関するご質問であれば以下は読み飛ばしてください。
(split、スライス、正規表現を使うだとか。については言及しません)
Pythonなら関数を定義するのが自然だと思います。
(A) '#'以降の文字列を削除する関数
(B) ファイルの中身の意味のあるデータだけを抽出する中間処理
の二つを私は考えました。
フローとしとしては(B)の処理で(A)を使い行(文字列)毎に処理をします。
以下の例ではジェネレータ構文を使っていますが、想定しているスクリプトは別に全行読み込んで処理をしてもいいとは思います。
理想だけでいえばmap関数のように処理自体を引数として受け取れる方がいいかもしれません。
py
1 2def remove_after_hash(s: str) -> str: 3 # '#'までの文字列を返す 4 if '#' in s: 5 return s.split('#', 1)[0] 6 return s 7 8 9def extract_data(file: TextIO) -> Iterator[str]: 10 # ファイルの必要な部分だけを返す 11 for line in file: 12 line = remove_after_hash(line) 13 yield line 14
remove_after_hashは手続き的な命名なのでコメントを消すとか、意味のある部分だけを残すみたいな意味に変えたほうが人によっては自然に感じるかもしれません。
そうしたほうが空文字を消すみたいな処理もここでカスタマイズしやすいと思います。
「該当のソースコード」は自然なコードなのか、皆様がどのようなコードを書かれるかが気になりました。もっと自然なコードがあれば教えてください。(「自然」をどう考えるかが難しいですが・・・)
フローそのものの自然さに着目しても有益なことがないので、カプセル化されているものだと考えたほうが様々な利点があります。
カプセル化というか、関心の分離というか。正しい言葉ではないでしょうがそういうノウハウが活きるという話です。
*もっと汎用性について議論したい人がextract_data
の関数定義について、指摘してくるかもしれませんが、好きなようにリッチ(笑)にカスタマイズすればよろしいかと思います。空行を無視するだとかね。
投稿2025/08/12 17:23
総合スコア68
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2025/08/13 07:43 編集

0
既に解決済みなので,御参考です。
re.sub() 関数を用いてコメント部分(#
から末尾まで)を取り除き,条件式(三項演算子) を用いて浮動小数点数(float()
)と整数(int()
)を切り替えて数値化しています。
Python
1import re 2 3with open('sample.txt', 'r', encoding='utf-8') as f: 4 lst = [s for s in f.read().splitlines()] 5lst = [re.sub('#.*$', '', s) for s in lst] 6lst = [float(s) if i == 1 or i == 2 else int(s) for i, s in enumerate(lst)] 7 8a = [0.0] * 4 9num, a[1], a[2], ns = lst 10 11print(num, a, ns) 12# 0 [0.0, 1.5, 2.0, 0.0] 3
投稿2025/08/12 09:37
総合スコア479
0
例えばこんなん、とか?
Python
1#!/usr/bin/env python3 2 3import sys 4 5a = [0] 6 7if __name__ == '__main__': 8 with open(sys.argv[1], "r") as f: 9 para = [x.split() for x in f.readlines()] 10 for i, j in para: 11 match j: 12 case '#num': 13 num = i 14 case '#ns': 15 ns = i 16 case _: 17 a.append(i) 18 print(f'{num}\n{a[1]}\n{a[2]}\n{ns}') 19 20
個人的には、「リスト内包表記が使えてるのに惜しいな」って感想。もっと縮められる。
それから、せっかく「付属情報を付けてる」状態なんだから、判別に利用すべきだと思った。
そういう場合、Python3.10から追加されたmatch文
を上手く使うべきだと思う。
パターンマッチは極めて強力なんで、ガンガン使おう。
そんなトコかな?
投稿2025/08/12 06:17
総合スコア158
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2025/08/13 06:57

0
ベストアンサー
もっと自然なコードがあれば教えてください。(「自然」をどう考えるかが難しいですが・・・)
確かに「自然なコード」という表現は解釈に困るところですが、例えば Numpy を利用すると以下の様に書くことができます。
※ numpy.loadtxt()
のデフォルト設定では #
をコメント文字列の開始と見なして読み飛ばします
numpy.loadtxt — NumPy v2.3 Manual
comments: str or sequence of str or None, optional
The characters or list of characters used to indicate the start of a comment. None implies no comments. For backwards compatibility, byte strings will be decoded as ‘latin1’. The default is ‘#’.
python
1import numpy as np 2 3a = np.zeros(4) 4num, *a[1:3], ns = np.loadtxt('sample.txt') 5num, ns = num.astype(int), ns.astype(int) 6 7print(num) #0 8print(a[1]) #1.5 9print(a[2]) #2.0 10print(ns) #3
投稿2025/08/12 03:17
編集2025/08/12 06:40総合スコア21391
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2025/08/12 06:50

あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2025/08/12 07:28
2025/08/12 07:30 編集
2025/08/12 08:02
2025/08/12 08:11