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

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

新規登録して質問してみよう
ただいま回答率
85.48%
コードレビュー

コードレビューは、ソフトウェア開発の一工程で、 ソースコードの検査を行い、開発工程で見過ごされた誤りを検出する事で、 ソフトウェア品質を高めるためのものです。

Python

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

Q&A

1回答

1174閲覧

func(*values)に与える要素が1つのときの処理を速くしたい

退会済みユーザー

退会済みユーザー

総合スコア0

コードレビュー

コードレビューは、ソフトウェア開発の一工程で、 ソースコードの検査を行い、開発工程で見過ごされた誤りを検出する事で、 ソフトウェア品質を高めるためのものです。

Python

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

1グッド

0クリップ

投稿2020/06/30 06:30

編集2020/06/30 06:30

下記コードadd_all()は外部でadd()を複数回呼び出す代わりに複数の引数を取れるようにしたものです。
_add()は複数の引数を持ち再帰的に呼び出されるので外部から隠してあり、質問の本質とも関係ありません。
add_all()の引数は1つでも構わないのでadd(*values: int)として2つをまとめてしまおうと考えました。
ですが、実際には*valuesとすると、たとえ1つの要素しか与えなくても関数内でforループが回されるために遅くなりました ([Wandbox]三へ( へ՞ਊ ՞)へ ハッハッ)。
複数引数を取りながらも、与える要素が1つのときの速さを損なわせない上手い方法はないのでしょうか?

Python

1def add(value: int) -> None: 2 _add(value, 0, 0) 3 4 5def add_all(*values: int) -> None: 6 """ 7 外部での↓の代わり 8 for v in values: 9 add(v) 10 """ 11 for v in values: 12 _add(v, 0, 0) 13 14 15def add(*values: int) -> None: 16 """上2つを統合できるが、与えるvalueが1つのとき、add(value)より遅い""" 17 for v in values: 18 _add(v, 0, 0)
LouiS0616👍を押しています

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

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

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

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

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

guest

回答1

0

ダメ元でディスパッチしてみたら案外高速化できたので共有します。

Python

1from functools import singledispatch 2 3@singledispatch 4def add_all(*values: int) -> None: 5 for v in values: 6 pass 7 8@add_all.register(int) 9def add_all(value: int) -> None: 10 pass

実行結果 Wandbox

for-loop alone: 0.30347180s add(): 1.22422028s add_all(): 1.29843211s

参考functools --- 高階関数と呼び出し可能オブジェクトの操作 — Python 3.8.3 ドキュメント

可変長引数への対応

残念ながら、add_all(*range(10))のような肝心の複数対応がエラーになるようです

引数をタプルに格納するのに時間がかかっていると仮説を立て、次のように組んでみました。

Python

1def add_all(value, *values: int) -> None: 2 if not values: 3 pass 4 else: 5 for v in [value, *values]: 6 pass

実行結果 Wandbox

for-loop alone: 0.32705522s add(): 1.31953120s add_all(): 2.10929275s

先ほどのように劇的ではありませんが、多少の改善は見られるようです。
ただし今度は引数無しの場合に対応していませんが。

投稿2020/06/30 06:39

編集2020/06/30 06:59
LouiS0616

総合スコア35660

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

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

LouiS0616

2020/06/30 06:44

逆に早すぎて不思議です。 引数の型をキーにした辞書を作って実現されていると思っていたのですけど、実際にはもっと効率化されているのかもしれません。
LouiS0616

2020/06/30 06:50

あれ、本当ですね。もうちょっと考えてみます。
退会済みユーザー

退会済みユーザー

2020/06/30 06:51

dispatchとregisterで登録順を変えると複数にも対応するのですが、速さのメリットはなくなりました。 難しいですね... https://wandbox.org/permlink/ZJJXxjMgh5HU114k
LouiS0616

2020/06/30 07:00

可変長引数に対応した方法を追記しました。
LouiS0616

2020/06/30 07:05

> dispatchとregisterで登録順を変えると複数にも対応する それだと add_all(value: int) が呼ばれなくなっちゃってますね。
退会済みユーザー

退会済みユーザー

2020/06/30 07:25 編集

value, *valuesで分けると、確かに速くなりました。 実際のコードの2_000_000回の操作で、add(value), add_all(*values)の併用を基準とすると、add(*values)が+300ms, add(value, *values) +200msといったところでした。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問