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

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

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

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

Q&A

解決済

4回答

2717閲覧

returnが値を返さない

退会済みユーザー

退会済みユーザー

総合スコア0

Python

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

0グッド

1クリップ

投稿2020/10/18 14:06

編集2020/10/19 00:47

returnで値が正しく返ってきません。

Python

1def division(x,y): 2 boolean=False 3 x=x 4 y=y 5 try: 6 z=x/y 7 boolean=True 8 except ZeroDivisionError: 9 y+=1 10 division(x,y) 11 if boolean==True: 12 #print(z)は正しく値を返す 13 print(z) 14 #return zは値を返さない 15 return z 16division(2,0)

多くの方にご回答いただき誠にありがとうございました。おかげさまで書きたかったプログラムが書けました。下のコードのように書くと、引数を更新して正しく計算されるまで関数を呼び直すという動作ができます。

Python

1Z=[] 2def division(x,y): 3 boolean=False 4 x=x 5 y=y 6 try: 7 z=x/y 8 boolean=True 9 Z.append(z) 10 except ZeroDivisionError: 11 y+=1 12 division(x,y) 13 14division(2,0) 15print(Z[0])

また、これを応用して、反応器段数、原料濃度、溶液と冷媒の温度差を変数にとり連続混合槽型反応器のシミュレーションを行うコードを作成しました。(大学で学んでいる化学工学の問題です。かなりマニアックな領域なので化学工学に馴染みのない方が見るのは難しいかもしれません。)

Python

1""" 2与えられた定数(prepared constants) 3Gp: 生産量(product flow rate) [kg/s] 4ζ: 反応転化率(conversion) 5γ: 原料中のブタジエン重量割合(weight fraction of monomer in the feed) 6τ: 滞留時間(residence time) [s] 7ρ: 溶液密度(density of mixture) [kg/m^3] 8α: 反応器の高さ/直径比(ratio of height to diameter of the reactor) 9ΔH: ブタジエンの反応熱(heat of polymerization of butadiene) [J/mol] 10ΔT: 反応溶液と冷媒の温度差(temperature difference between reactant and coolant) [℃] 11λ: 溶液の熱伝導率(thermal conductivity of solution) [W/(m・K)] 12μ: 溶液の粘度(viscosity of solution) [Pa・s] 13Cp: 溶液の比熱(specific heat of solution) [J/(kg・K)] 14M: ブタジエンの分子量(molecular weight of butadiene) [g/mol] 15""" 16 17""" 18計算により求められる値(values obtained by calculation) 19v: 溶液の体積流量(volumetric flow rate of solution) [m^3/s] 20V: 反応器体積(volume of the reactor) [m^3] 21D: 反応器直径(diameter of the reactor) [m] 22Qp: 反応熱(heat of reaction) [J] 23P: 攪拌の消費電力(power consumption of stirring) [kW] 24h: 冷却装置の熱伝達率(heat transfer coefficiency of the coolant) [W/m^2・K] 25Nu: ヌッセルト数(Nusselt number) 26Pr: プラントル数(Prantdl number) 27Re: レイノルズ数(Reynols number) 28n: 1分あたり攪拌回数(number of stirring per minute) [/s] 29Np: 動力数(power number) 30""" 31 32""" 33値の記録に使用するリスト(list to record the value) 34P_log: i段目の反応器の消費電力を計算する際の挙動をi番目の要素に記録する 35 (record the behavior when calculating the power consumption of the i-th reactor in the i-th element) 36P_list: 反応器毎の攪拌消費電力を記録する(record the power consumption of each reactor) 37P_total: 最終的な計算結果を保存する(save the final result of calculation) 38""" 39 40""" 41例外処理(exception handling) 42排熱を処理しきれない場合は冷媒の温度を1度ずつ下げる 43(if the exhaust heat cannot be processed, lower the temperature of the refrigerant by 1 degree.) 44""" 45 46import math 47Gp = 0.729 48ζ = 0.60 49γ_1 = 0.05 50τ_1 = 18000 51ρ = 850 52α = 1.3 53ΔH = 72800 54λ = 0.128 55Cp = 1680 56M = 54.0 57V_1=514.6 #V_1=v*τ_1 58v_1=0.02859 #v_1=Gp/(ρ*γ_1*ζ) 59 60#反応速度定数を求める(find the reaction rate constant) 61ζ_total=ζ 62k=v_1*ζ_total/(V_1*(1-ζ_total)) 63 64P_log=[[]] 65P_list=[] 66P_total=[] 67 68def reactor(N, γ, ΔT): 69 P_log=[[]] 70 P_list=[] 71 N=N 72 γ=γ 73 ΔT=ΔT 74 #反応器のサイズを求める(find the size of each reactor) 75 τ=(1/k)*(1/math.pow(1-ζ_total,1/N)-1) 76 v=Gp/(ρ*γ*ζ_total) 77 V=v*τ 78 D=math.pow(4*V/(1.3*math.pi),1/3) 79 #各反応器の熱収支を計算する(calculate heat balance of each reactor) 80 ζ_each=1-math.pow(1-ζ_total,1/N) 81 try: 82 for i in range(N): 83 P_log.append([]) 84 P_log[i+1].append(0) 85 Qp=(ΔH/(M*0.001))*k*ρ*V*(1-ζ_each)**(i+1)*γ 86 h=Qp/(1.3*math.pi*(D**2)*ΔT) 87 Nu=h*D/λ 88 μ=0.0010*math.pow(50,1.7)*math.pow(1-(1-ζ_each)**(i+1),2.5)*math.exp(21*γ) 89 Pr=μ*Cp/λ 90 Re=math.pow((1/0.5)*Nu*math.pow(Pr,-1/3),3/2) 91 n=μ*Re/(ρ*(D/2)**2) 92 Np=14.6*math.pow(Re,-0.28) 93 P=0.0010*Np*ρ*(n**3)*((D/2)**5) 94 P_log[i+1].append(P) 95 while abs((P-P_log[i+1][len(P_log[i+1])-2])/P)>1.00*math.pow(10, -3): 96 h=(Qp+P*1000)/(1.3*math.pi*(D**2)*ΔT) 97 Nu=h*D/λ 98 Pr=μ*Cp/λ 99 Re=math.pow((1/0.5)*Nu*math.pow(Pr,-1/3),3/2) 100 n=μ*Re/(ρ*(D/2)**2) 101 Np=14.6*math.pow(Re,-0.28) 102 P=0.0010*Np*ρ*(n**3)*((D/2)**5) 103 P_log[i+1].append(P) 104 P_list.append(P_log[i+1][-1]) 105 P_total.append(sum(P_list)) 106 P_total.append(ΔT) 107 except OverflowError: 108 if ΔT<=50+273: 109 ΔT+=1 110 reactor(N, γ, ΔT) 111 else: 112 print("Warning: The feed is too thick. Reduce γ.") 113reactor(1, 0.07, 65) 114print(P_total)

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

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

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

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

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

gentaro

2020/10/18 14:34

Pythonならインデントをちゃんと揃えたソースじゃないと意味ないんで、質問文を編集してマークダウンでコードを記載しましょう。
退会済みユーザー

退会済みユーザー

2020/10/18 15:04 編集

ご指摘ありがとうございます。teratailの利用が初めてなものでインデントされていないことに気づいておりませんでした。大変失礼いたしました。
toast-uz

2020/10/18 14:44

入力画面の上にあるボタン<code>を選択して、自動的に入力される ```ここに言語を入力 コード ``` の「コード」という場所にコードを書いてください。
y_waiwai

2020/10/18 14:47

このままではコードが読めないので、質問を編集し、<code>ボタンを押し、出てくる’’’の枠の中にコードを貼り付けてください
bsdfan

2020/10/19 04:16

解決済みなので、こちらにコメントさせていただきます。 もともとのサンプルコードの、exceptの中の、 division(x,y) を return division(x,y) とすればよかったのではないかと思います。(再帰関数のイメージで) 外部の配列に値を追加して値を返すというやり方は、あんまりいい方法ではないと思います。
退会済みユーザー

退会済みユーザー

2020/10/19 04:42

bsdfanさん、ありがとうございます。確かに、一応動きはしたものの汚いコードだなとは感じていました。except節にreturn function(x, y+1)を入れて動作を確認してみました。再帰関数など、あまり使い慣れていないので良く勉強させていただきます。
guest

回答4

0

Python

1def division(x,y): 2 boolean=False 3 x=x 4 y=y 5 try: 6 z=x/y 7 boolean=True 8 except ZeroDivisionError: 9 y+=1 10 division(x,y) 11 if boolean==True: 12 return z

Python

1a = division(10, 10) 2print(a) 3# 1.0 4 5a = division(10, 9) 6print(a) 7# 1.1111111111111112

試したところ、division(10, 10)とすると1.0が返ってきました。division(10, 9)とすると1.1111111111111112が返ってきました。ちゃんと値を返してくれているようです。

【追記】
Daregadaさんの回答を見てdivision(2, 0)を試したところNoneが返ってきました。
ではfinallyを追加してはどうでしょうか?

Python

1def division(x,y): 2 x=x 3 y=y 4 try: 5 z=x/y 6 except ZeroDivisionError: 7 y+=1 8 z = division(x,y) 9 finally: 10 return z

投稿2020/10/18 15:18

編集2020/10/18 15:28
meg_

総合スコア10580

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

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

gentaro

2020/10/18 15:20

division(10,0)とかやったときの話では。
退会済みユーザー

退会済みユーザー

2020/10/18 15:24

meg_さん、gentaroさん、ありがとうございます。Daregadaさんという方の回答でy=0の時に値を返さない理由がわかりました。
退会済みユーザー

退会済みユーザー

2020/10/19 00:23 編集

meg_さん 「Daregadaさんの回答を見てdivision(2, 0)を試したところNoneが返ってきました。 ではfinallyを追加してはどうでしょうか?」 →アドバイスありがとうございます。 それも試していたのですが、駄目でした。今回の場合、例外処理として呼び出されるdivision(2, 1)の結果は実行中のdivision(2, 0)の中にreturnされてしまうため、returnしても出力できないとのことでした。このようなケースでは、関数の外に空のリストを用意しておき、returnを使う代わりに計算結果をそのリストに追加するという方法で計算結果を取得できました。
guest

0

ベストアンサー

ええと、division(2, 0)を呼び出すと、ZeroDivisionErrorをキャッチして、division(2, 1)を呼び出しますよね。

たしかに、そのときの処理では、booleanTrueになり、return zで値2を返します。どこに返すかというと、division(2, 1)を呼び出したdivision(2, 0)を実行中の関数divisionにですね。

返された値は(代入したりしていないので)特に使われることなく捨てられてしまい、次のif文に移ります。こちらの環境ではbooleanFalseのままなので、if文は成立せず、return zは実行されません。

結局、division(2, 0)を呼び出した側には、Noneが返されることになります。

投稿2020/10/18 15:13

編集2020/10/18 15:17
Daregada

総合スコア11990

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

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

退会済みユーザー

退会済みユーザー

2020/10/18 15:23

なるほど、値を返してくれない理由について理解できました!ご丁寧にありがとうございます!!
退会済みユーザー

退会済みユーザー

2020/10/18 15:29 編集

計算が正しく行われるまで関数の引数を更新して関数を呼び直すという動作を実現したかったのですが、この場合、関数の外に値を記録するためのリストを用意しておき、計算が正しく行われた時に値をリストにアペンドするという方法で、計算結果を取得できることがわかりました。Daregadaさん、おかげで大変助かりました。
toast-uz

2020/10/19 03:58

最後のご理解は少し疑問です。本来は、関数から関数を呼び出す、ということを避けるべきです。 関数は複数の値のセットを返せますので、(正常かどうかと異常ならその理由、正常時の結果)のセットを返すようにして、呼び出し側で異常時に引数を変えて関数を呼び直す、というのが望ましいです。
退会済みユーザー

退会済みユーザー

2020/10/19 04:39

toast-uzさん、ありがとうございます。 乏しい知識で一応は動くものが作れたという感じで、綺麗なコードではないというか、あまり良い書き方ができていない気がするというのはなんとなく感じておりました。つい先ほど別の方からいただいたコメントを参考に try: return(argument) except: return function(argument+1) で実装しました。tryとexceptの両方にreturnを書けばよかったのですね。
gentaro

2020/10/19 05:11

> tryとexceptの両方にreturnを書けばよかったのですね。 その方法はスタックオーバーフローの危険があるんでやめた方が良いです。 素直に呼び出し元で対処しましょう(と最初から回答してますが) また、この問題はそもそも引数yが0か否かの事前チェックをしていれば、事前に回避できるはずです。
shiro-to

2020/10/22 07:00 編集

@gentaroさん エラーが起こるプログラムの例として0徐算を挙げただけで、最終的には「エラーが起こらなくなるまで引数を更新し続ける」というプログラムを実装しようとしているように見えます。(どうして質問者の方が1回しかエラーの起こり得ないプログラムを例に挙げたのか謎ですが) なので事前に0か否かチェックをしていればというのは的外れな気がします。
guest

0

returnが値を返すのは、

if boolean==True:

が成立しているときだけ、です。
その他の場合は値を返しません

投稿2020/10/18 14:57

y_waiwai

総合スコア87774

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

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

退会済みユーザー

退会済みユーザー

2020/10/18 15:01

print(z)は実行されるのでboolean==Trueは成立しています。
退会済みユーザー

退会済みユーザー

2020/10/18 15:03

division(2,0)で例外を発生させた後、except節でy+=1を実行してから再度division(x,y)を呼び出しているので、今度はboolean==Trueとなり、print(z)が実行されます。しかし、この書き方ではreturn zが値を返してくれないらしく、例外処理で正しく値を返す方法がわからないため質問させていただいております。
y_waiwai

2020/10/18 15:04

なら値を返します。何か勘違いしてませんか? というより、値を返さないのはどうにかしましょうよ。
退会済みユーザー

退会済みユーザー

2020/10/18 15:11

pythonについては初学者ですので、拙い質問でご不快な思いをさせてしまっていたら申し訳ありません…。 「なら値を返します」とのことですが、事実、上記のコードでprint(z)では2.0と表示されるもののreturn zでは何も表示されませんでした。 私もこのコードで値が返ってくるものと思って書いたものの、予想と異なる結果が出たため困惑しております。もしtry, exceptの後に正しく値を返す方法をご存知でしたら、お教えいただけないでしょうか。
y_waiwai

2020/10/18 15:14

表示されないってだけですか? どう表示させるコードを書いたんでしょうか。そこんところを提示しましょう。
退会済みユーザー

退会済みユーザー

2020/10/19 02:48 編集

コードは上に示したもののみです。 他の方の回答で、division(2,0)の例外処理によりdivision(2,1)が呼び出されreturn zは確かに実行されるものの、その結果は出力に現れず、呼び出し元のdivision(2,0)の中に返されてしまいそのまま破棄されてしまうということがわかりました。 y_waiwaiさんも、お付き合いいただき誠にありがとうございました。 追記 平和に済ませようかとも思ったのですがちょっと我慢ならなかったので書かせていただきます。知ったかぶって突っかかる前に自分の知識が間違ってないか少し確認してみてはいかがでしょうか。 ・「returnが値を返すのは、if boolean==True:が成立しているときだけ、です。」→存じ上げております。また、except節の処理によって最終的にif boolean==Trueになっております。 ・「なら値を返します。何か勘違いしてませんか?」→出力としては返しません。あなたの方が何か勘違いなされているかと思いますので実際にコードを動かしてお確かめください。 ・「というより、値を返さないのはどうにかしましょうよ。」→それが自力でできなかったので質問させていただいておりました。回答してくださるのであればもう少し質問の意図を汲み取っていただけますと助かります。また、「どうにかしましょう」とおっしゃるのであれば何か具体案をお示しください。 ・「表示されないってだけですか?どう表示させるコードを書いたんでしょうか。そこんところを提示しましょう。」→print(z) return zを連続で書いた際にprint(z)の結果が表示されてreturn zの結果が表示されなかったという内容であることはきちんと見ればわかっていただけるかと思います。コードと質問内容を見てから回答してください。 今後他の方の質問に回答される際はどうかもう少しお手柔らかにお願いいたします。私などより遥かに幅広い知識と能力をお持ちかと思いますので、今後その力を活かしてますますご活躍されますことを期待いたします。 <(_ _)>ペコリ
y_waiwai

2020/10/19 04:47

それがわかってるなら、その抜けがないようにコードを組みましょう。 あからさまに不完全なコードを提示されても、ああ、こんな事がわからない初心者なんだなあ、としか思えません その抜けをどうすることもできないならそういうふうに質問しましょうよ。 そう言ってくれればその方法を教えます あなたがいくら理解している、と言い張っても、見も知らないなんの関係もない赤の他人のオイラにはそれが本当のことだとはわかりません
gentaro

2020/10/19 05:31

我慢ならない、などという感情的な問題があるのなら、第三者の意見として言わせていただきます。 この回答およびコメントは「親切なもの」とは言えませんが、関数内で条件分岐し、ある条件の場合は値を返すのに、その条件以外は値を返さない、という作りになっているのを「どうにかしましょう」という最初の指摘は至極真っ当なものです。(これは私の回答も同じ趣旨) > ・「returnが値を返すのは、if boolean==True:が成立しているときだけ、です。」→存じ上げております。また、except節の処理によって最終的にif boolean==Trueになっております。 これは成立してません。 exceptに内での処理でboolean==Trueになるようなコードではありません。 この点において「何か勘違いしてませんか?」という指摘はもっともです。 > 回答してくださるのであればもう少し質問の意図を汲み取っていただけますと助かります。 回答者はエスパーではありません。 あなたのコードの意図をあなたが全て説明していない限り、回答者に「汲み取れ」というのは無茶です。 もし正確に伝わっていないと感じるのであれば、それはあなたが努力して伝えてください。 また、回答者側からも同じことを言われるとどう思いますか? 「この回答の意図を汲み取れ」と言われたら、あなたにそれができてますか? > 今後他の方の質問に回答される際はどうかもう少しお手柔らかにお願いいたします。 質問者は「お客様」ではありません。 あなたにとって厳しいと感じても、わざわざ時間を割いてあなたの問題の解決を手助けしようとしている相手であることを忘れないでください。
gentaro

2020/10/19 05:32

書いてたら退会してたw
y_waiwai

2020/10/19 06:25

自分のプライドが邪魔をして、コードの理解ができなくなっている残念な例、というところでしょうか。
guest

0

提示されたコードだけで判断するとbooleanの値がFalseの場合に関数が値を返すことがありません。
通常このような関数の定義はするべきではありません。
booleanの値がFalseの場合でも何らかの値を返しましょう。

返す値がない場合、そもそもtry-exceptて例外をキャッチせずに呼び出し元にそのまま例外を返すか、あるいはキャッチした場合に別途例外をraiseして呼び出し元に例外を通知し、呼び出し元で「例外が発生した」事を検知(キャッチ)して、値が返らなかったケースの処理をしましょう。


追記
たぶん処理フローのイメージがついてないんだろうから、ステップ実行のできる環境(VSCodeとか)を用意してそのスクリプトを1行ずつ実行しながら変数の値がどうなっているのか調査してください。

投稿2020/10/18 14:57

編集2020/10/18 15:19
gentaro

総合スコア8949

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

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

退会済みユーザー

退会済みユーザー

2020/10/19 00:21 編集

ご回答ありがとうございました。確かに、複雑なプログラムを書くときは行ごとの実行ができる環境があると便利だと思いますので、そうした環境を使いこなせるように頑張りたいと思います。 今回のコードに関しては、例外処理でdivision(2, 1)が呼び出されるためboolean==Trueに変わり、最終的にreturn zがきちんと実行されてはいるものの、その返り値を返す場所が出力ではなく実行中のdivision(2, 0)という関数の中になってしまうため返り値が出力されないということでした。 エラーなく計算が実行されるまで例外処理を繰り返して最後に正しく計算されたらbooleanをTrueに変えて計算結果を出力するというプログラムを作りたかったのですが、そう明記していなかったため質問の意図が伝わりにくかったかと思います。申し訳ございません。 今後質問させていただくときはプログラムの意図を明記するよう留意します。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問