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

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

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

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

Python

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

Q&A

解決済

4回答

858閲覧

Python: ほとんど似ているものを関数化できるか

Nippun

総合スコア1147

Python 3.x

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

Python

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

0グッド

0クリップ

投稿2018/12/24 11:46

Python

1def func(s): 2 callNum = 0 3 for i in s: 4   if callNum <= 0: 5 break 6 if i == 0: 7 break 8 if i == 2: 9 callNum -= 1 10 11 for i in s: 12     if callNum <= 0: 13 break 14 if i == 0 and callNum == 3: 15 break 16 if i == 3: 17 callNum -= 1

2つのfor文の中身がほとんど同じだがif文が少し違う場合、for文の部分を関数化できますか?

Python

1# この部分 2for i in s: 3     if callNum <= 0: 4 break 5コード

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

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

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

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

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

guest

回答4

0

本当は質問のコードは書き直して欲しい。
今のコードはcallNumが絶対に0のままで変化しないし、(sがイテレータでないなら)このコードは何もしないので、実際のコードでcallNumをどこで書き換えるのか回答者側から見えなくて最適な方法は実のところわからない。


純粋に形だけみたら関数化などしないで(つまり、"そもそも関数化するのは悪手"に見えるので)

Python

1def func(s): 2 callNum = 0 3 for is_first in [True, False]: 4 for i in s: 5      if callNum <= 0: 6 break # ※ 7 if i == 0 and (is_first or callNum == 3): 8 break 9 if i == (2 if is_first else 3): # トリッキーには 3 - is_first でいいですが 10 callNum -= 1

と私ならするでしょう。


ただし、最初に書いたように、このコードはcallNumがずっと0のままで、※のところで必ずfor i in sを抜けるので(sがイテレータでないなら)なんの作用もなく終わります。

結局この関数は

Python

1def func(s): 2 i = iter(s) 3 next(i, None) 4 next(i, None)

と事実上等しいです。

callNumをいったいどこでどんな風に変えるのか、その想定が違えばよい方法も違うでしょう。
ここまでの議論は全部無駄な話でしかないと思います。

投稿2018/12/25 01:07

quickquip

総合スコア11038

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

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

0

for文の2番目のif の条件,3番目のif の条件が異なるのでまとめたいということなら、
for文をforloop関数とし、条件をbooleanを返す関数として与えられそうですね。

python

1def func(s): 2 callNum = 0 3 def forloop (t, predicate1, predicate2) 4 nonlocal callNum 5 for i in t: 6   if callNum <= 0: 7 break 8 if predicate1(i, callNum): 9 break 10 if predicate2(i, callNum): 11 callNum -= 1 12 forloop(s, (lambda i, callNum: pass), (lambda i, callNum: pass )) 13 forloop(s, (lambda i, callNum: pass), (lambda i, callNum: pass ))

投稿2018/12/24 14:52

編集2018/12/24 15:49
fu7mu4

総合スコア1088

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

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

hayataka2049

2018/12/24 15:04

構文の間違いは(意図的っぽいのとそうでもないのとありますが)スルーするとして、それだとcallNumがforloopのローカル変数になりUnboundLocalError: local variable 'callNum' referenced before assignmentといったエラーを出してくれます。
fu7mu4

2018/12/24 15:37

nonlocal callNum をforloopの定義につければいいですかね
guest

0

ベストアンサー

見通しを良くするためにbreakするifはまとめてみます。

python

1def func(s): 2 call_num = 0 # ついでにpython風の命名に直した 3 for i in s: 4 if call_num <= 0 or i == 0: 5 break 6 if i == 2: 7 call_num -= 1 8 9 for i in s: 10 if call_num <= 0 or (i == 0 and call_num == 3): 11 break 12 if i == 3: 13 call_num -= 1

無理やり関数化すると、こうでしょうか。クロージャを使っています。

python

1def make_cond(break_cond, decr_cond): 2 def f(call_num, i): 3 if break_cond(call_num, i): 4 return "break" 5 if decr_cond(call_num, i): 6 return "decr" 7 else: 8 return None 9 return f 10 11def func(s): 12 call_num = 0 # ついでにpython風の命名に直した 13 14 f = make_cond(lambda call_num, i: call_num <= 0 or i == 0, 15 lambda call_num, i: i==2) 16 for i in s: 17 ret = f(call_num, i) 18 if ret == "break": 19 break 20 if ret == "decr": 21 call_num -= 1 22 23 f = make_cond(lambda call_num, i: call_num <= 0 or (i == 0 and call_num == 3), 24 lambda call_num, i: i==3) 25 for i in s: 26 ret = f(call_num, i) 27 if ret == "break": 28 break 29 if ret == "drcr": 30 call_num -= 1 31

2つのforは2重ループで管理できそうです。

python

1def make_cond(break_cond, decr_cond): 2 def f(call_num, i): 3 if break_cond(call_num, i): 4 return "break" 5 if decr_cond(call_num, i): 6 return "decr" 7 else: 8 return None 9 return f 10 11def func(s): 12 call_num = 0 # ついでにpython風の命名に直した 13 14 funcs = [ 15 make_cond(lambda call_num, i: call_num <= 0 or i == 0, 16 lambda call_num, i: i==2), 17 make_cond(lambda call_num, i: call_num <= 0 or (i == 0 and call_num == 3), 18 lambda call_num, i: i==3) 19 ] 20 21 for f in funcs: 22 for i in s: 23 ret = f(call_num, i) 24 if ret == "break": 25 break 26 if ret == "decr": 27 call_num -= 1

見ての通り、コードがすっきりすると言ったメリットは特にありません。

投稿2018/12/24 13:17

hayataka2049

総合スコア30933

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

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

0

敢えて関数化するなら

Python

1def myFor(s, callNum, p): 2 3 for i in s: 4   if callNum <= 0: 5 break 6 if p == 0: 7 if i == 0: 8 break 9 if i == 2: 10 callNum -= 1 11 if p == 1: 12 if i == 0 and callNum == 3: 13 break 14 if i == 3: 15 callNum -= 1 16 17 return callNum 18 19def func(s): 20 callNum = 0 21 callNum = myFor(s, callNum, 0): 22 callNum = myFor(s, callNum, 1):

投稿2018/12/24 12:38

teefpc

総合スコア111

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問