🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Python 2.7

Python 2.7は2.xシリーズでは最後のメジャーバージョンです。Python3.1にある機能の多くが含まれています。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

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

Q&A

解決済

4回答

1110閲覧

pythonにおける変数と演算速度について

退会済みユーザー

退会済みユーザー

総合スコア0

Python 2.7

Python 2.7は2.xシリーズでは最後のメジャーバージョンです。Python3.1にある機能の多くが含まれています。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

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

0グッド

0クリップ

投稿2019/12/09 13:21

変数を使った方がいい時と使わない方がいいとき

python

1#Pattern 1 2l = ["a","b","c","d","e"] 3leng = len(l) 4for i in range(lengh): 5 print(i) 6 7#Pattern 2 8l = ["a","b","c","d","e"] 9for i in range(len(l)): 10 print(i)

これは単純すぎる例ですが、pattern1とpattern2ではlengの変数をおくかおかないかを変えています。どちらの方が賢いコードですか?
また、繰り返し参照するときは一度変数でおいた方が効率がいいのか、それとも毎度計算してそれを参照するのが効率がいいのか、わかる方教えてください。

######補足
現在私は、計算コストが高そうなときは変数をおくようにしています。どのような方法ががプログラムとして正しいか教えて欲しいです。

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

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

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

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

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

shiracamus

2019/12/09 14:17

pattern2 の print は print(l[i]) にするべきでは?
guest

回答4

0

タイプミスが無いとして、このケースだと2がいいですが、一般論としてはケースバイケースです。

速度については、まず差が無いと思ったほうがいいです。Cだと最適化するとコードが同じになるかもしれません。

全く同じ内容でコストの高い計算を、繰り返し回数の非常に多いループの中で複数回行うなら、ループの前に変数に代入しておいた方が、速いことになりますね。それが有意にうれしいケースは多くないと思います。

変数に代入するというのは、値に名前を付けることです。
leng = len(l)して、lengを使うのと、len(l)を直接使うのであれば、前者は何の長さか不明で、後者はlの長さということが見ただけでわかります。
lengへの代入場所と、参照場所が離れている場合は、どんどんlengの点数が悪くなります。

複雑な式の場合、それが何であるのか、ぱっと見でわかりにくいので、変数に代入することで名前を与えると、意味が分かりやすくなります。その場合は、1回しか参照しない場合でも変数に代入してそれを参照した方がいいです。
名前を付ける意味がない場合は、同じ式を複数回書くこともあります。計算コスト次第ですが。

式がわかりにくい場合の別案としては、コメントで書いておくという人もいるでしょうが、私は変数名を使いますね。複雑な説明となり、変数名で説明しきれない場合はコメントを書かざるを得ないでしょうが。

以上は、私個人の趣味で書く場合で、複数人のプロジェクト(書くのは一人でも別の人がメンテする場合も)だと、ルールを決めて従うことになります。

投稿2019/12/09 14:04

otn

総合スコア85893

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

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

0

ベストアンサー

どちらの方が賢いコードですか?

ちょっと狡い回答ですが、どちらも賢く無いです。

Python

1for i, _ in enumerate(l): 2 print(i)

繰り返し参照するときは一度変数でおいた方が効率がいいのか、それとも毎度計算してそれを参照するのが効率がいいのか

効率だけ見るぶんには前者の方が良いことが多いです。
しかしリストに対するlenは定数時間で取得できるので、ほとんど差は出ません。

大きな差が出ないのであれば、実行効率より分かり易さを取るべきです。

計算コストが高そうなときは変数をおくようにしています。

充分分かり易いコードになるのであれば、変数を設ければ良いのです。

何度も使う一度しか使わない
計算コストが高い変数を使うべきどちらでも良い
計算コストが安いどちらでも良いどちらでも良い

計測コードについて

計測した結果、ほとんど差が出ない旨追記しましたが...
実行時間の差があまりに少なく、偶発的に結果が逆転するので撤回します。参考にならないです。

Python

1import timeit 2 3 4def pattern1(l): 5 length = len(l) 6 for i in range(length): 7 pass 8 9def pattern2(l): 10 for i in range(len(l)): 11 pass 12 13 14l = ["a","b","c","d","e"] 15print( 16 'pattern1:', timeit.timeit(lambda: pattern1(l), number=1_000_000) 17) 18print( 19 'pattern2:', timeit.timeit(lambda: pattern2(l), number=1_000_000) 20)

実行結果 Wandbox

pattern1: 0.625347338616848 pattern2: 0.6491380594670773

投稿2019/12/09 13:31

編集2019/12/09 14:03
LouiS0616

総合スコア35668

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

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

LouiS0616

2019/12/09 14:00

計測した旨追記しましたが、考察に値するものではなかったので回答末尾へ移動しました。
guest

0

#Pattern 2 です。

for 文の in の部分は1度しか評価されません。
そのため #Pattern 1 のように書いても大して速くできません。

class Iterator: def __init__(self, sequence): self._sequence = sequence self._index = -1 def __iter__(self): print('ここが評価されるのは1度だけ') return self def __next__(self): self._index += 1 try: return self._sequence[self._index] except IndexError: raise StopIteration iterator = Iterator([0, 1, 2, 3, 4]) for element in iterator: print(element)
>>> for element in iterator: ... print(element) ... ここが評価されるのは1度だけ 0 1 2 3 4 >>>

投稿2019/12/09 13:29

nico25

総合スコア830

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

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

退会済みユーザー

退会済みユーザー

2019/12/09 13:47

回答ありがとうございます。追加でもう1つ質問なのですが、定義した変数がメモリ上から消えるのはプログラム自体が停止された時だけですか?それともメモリの容量を増やすためにプログラムに変数定義を取り消す方法とかってあったりするんですか?
nico25

2019/12/09 14:01

細かい動作はわからないのですが、 "参照カウント" が 0 になった時に "ガベレージコレクション" に回収されると聞いています。 lst0 = [0, 1, 2] # 参照カウント 1 lst1 = lst0 # 参照カウント 2 del lst0 # 参照カウント 1 del lst1 # 参照カウント 0 <--- 誰からも参照されなくなると削除される。
guest

0

#Pattern 1って、エラーに成りません?

実行結果

投稿2019/12/09 13:32

cateye

総合スコア6851

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

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

cateye

2019/12/09 13:36

lengh?・・・・leng
退会済みユーザー

退会済みユーザー

2019/12/09 14:23

すみません、スペルミスです。。。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問