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

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

詳細はこちら
Python

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

Q&A

解決済

3回答

4006閲覧

local variable 'Q' referenced before assignment と出てしまう

kyamamama

総合スコア4

Python

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

0グッド

0クリップ

投稿2021/01/14 07:35

楕円加算について研究しています
local variable 'Q' referenced before assignmentと出てきてしまって困っています

def third_methodで初期値をbite=1ならばQ=P(=G)、bite=2ならばQ=P2=(G2)とするように組みたいと考えています

#Fp上のy-2=x^3+ax+yでの p,a,b=11,1,2 G=(1,2) def inv(n,p):#inv(obj)objのビット単位反転を返す return pow(n,p-2,p) def div(c,w): return(c*inv(w,p))%p def ec_double(A):#P=Qのとき if A[0]==float("infinity"): x=float('infinity') y=float('infinity') else: l=div(3*A[0]**2+a,2*A[1]) if l==0: x=float('infinity') y=float('infinity') else: x=(l**2-A[0]-A[0])%p y=(l*(A[0]-x)-A[1])%p return x,y def ec_add(A,B): if A[0]==B[0] and A[1]==B[1]: l=div(3*A[0]**2+a,2*A[1]) x=(l**2-A[0]-A[0])%p y=(l*(A[0]-x)-A[1])%p elif A[0]==B[0] and A[1]!=B[1]: x=float('infinity') y=float('infinity') elif A[0]==float('infinity'): x=B[0] y=B[1] elif B[0]==float('infinity'): x=A[0] y=A[1] else: l=div(B[1]-A[1],B[0]-A[0]) x=(l**2-A[0]-B[0])%p y=(l*(A[0]-x)-A[1])%p return x,y def ec_third(A): if A[0]==float('infinity'): x=float('infinity') y=float('infinity') elif A[1]==0: x=A[0] y=A[1] else: t=div(3*A[0]**2+a,2*A[1]) l=div(2*A[1]-t*(3*A[0]-t**2),3*A[0]-t**2) if l==0: x=float('infinity') y=float('infinity') else: x=(l**2-t**2+A[0])%p y=(l*(2*t**2-3*A[0]-l**2)-(t*(3*A[0]-t**2)-A[1]))%p return x,y def Base_10_to_n(X,n): if(int(X/n)): return Base_10_to_n(int(X/n),n)+str(X%n) return str(X%n) def third_mathod(P,d): if Base_10_to_n(d,3)[0]==1: Q=P for bit in Base_10_to_n(d,3)[1:]:#1番目の要素から最後の要素まで取得 Q=ec_third(Q) if bit =="1": Q=ec_add(Q,P) elif bit =="2": Q=ec_add(Q,P) Q=ec_add(Q,P) elif Base_10_to_n(d,3)[0]==2: P2=ec_double(P) Q=P2 for bit in Base_10_to_n(d,3)[1:]: Q=ec_third(Q) if bit=="1": Q=ec_add(Q,P) elif bit=="2": Q=ec_add(Q,P) Q=ec_add(Q,P) return Q G3=third_mathod(G,3) print(G3)

エラーコード

UnboundLocalError Traceback (most recent call last) <ipython-input-30-5fa6841430c9> in <module> ----> 1 G3=third_mathod(G,3) 2 print(G3) <ipython-input-29-93dfe3f2dd59> in third_mathod(P, d) 98 Q=ec_add(Q,P) 99 --> 100 return Q 101 UnboundLocalError: local variable 'Q' referenced before assignment

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

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

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

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

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

guest

回答3

0

なぜかお二人の回答にスコープが出てきますが、スコープの問題ではありません。
pythonでは、関数に入るときに新しいフレームが作成されて、グローバル変数を受取り、ローカル変数用に辞書がコピーされます。新規にバインドされたローカル変数は、ローカル変数用の辞書に登録されますが、ローカル変数用の辞書は関数から戻るときにフレームと共に破棄されるのです。if文の中もこの条件は同じです。

このプログラムコードでは単純にelseのないif文を使って、条件がどちらも成り立たないので、Qに値がバインドされていないだけです。

解決策は関数の最初にQに何かを割当てておくか、else節でQに何かを割り当てるかです。

投稿2021/01/14 08:34

ppaul

総合スコア24670

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

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

A_kirisaki

2021/01/14 08:38

あっ!!マジだ!!!
kyamamama

2021/01/15 03:10

ご回答ありがとうございます 参考にさせていただきます!
guest

0

その関数の概形は、

Python

1def third_mathod(P,d): 2 if 条件1: 3 Q = P 4 (以下略) 5 else if 条件2: 6 P2 = ... 7 Q = P2 8 (以下略) 9 10 return Q

となっていますから、条件1も条件2も成立しなかった場合にQには値が割り当てられないことになります。にもかかわらず、return Qで~~(スコープ外の)~~Qの値を参照しようとしているので、件のエラーが表示されます。

Qの初期値をif文の前に設定するか、それぞれのif文の中でreturn Qとして、末尾ではreturn Noneとでも書くかしてください。

投稿2021/01/14 07:45

編集2021/01/14 08:44
Daregada

総合スコア11990

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

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

kyamamama

2021/01/14 08:02

ご回答ありがとうございます ```ここに言語を入力 def third_mathod(P,d): if Base_10_to_n(d,3)[0]==1: Q=P for bit in Base_10_to_n(d,3)[1:]:#1番目の要素から最後の要素まで取得 Q=ec_third(Q) if bit =="1": Q=ec_add(Q,P) elif bit =="2": Q=ec_add(Q,P) Q=ec_add(Q,P) return Q elif Base_10_to_n(d,3)[0]==2: P2=ec_double(P) Q=P2 for bit in Base_10_to_n(d,3)[1:]: Q=ec_third(Q) if bit=="1": Q=ec_add(Q,P) elif bit=="2": Q=ec_add(Q,P) Q=ec_add(Q,P) return Q return None G3=third_mathod(G,3) print(G3) ``` 上記のように書き直してみましたが、すべての値がNoneになってしまいました...
Daregada

2021/01/14 08:18

ここは「local variable 'Q' referenced before assignmentが出る問題」を解決する質問に対する回答なので、「書いたコードが思い通りに動かない(書いた通りに動いている)問題」については、別に質問を立ててください。楕円加算に詳しい人が答えるでしょう。
kyamamama

2021/01/15 03:10

ご回答ありがとうございます。その通りですね、失礼しました。 ご意見参考にさせていただきます。
guest

0

ベストアンサー

~~ython では if 文ブロックの中で 変数のスコープが閉じていますのでその中で宣言した変数はブロックが終わると寿命が終わってしまいます。それより外で宣言された変数であれば if の中から書き換えても生き残ります。つまり Q に初期値を入れないと Q の中身がない可能性があるよ、と言っているわけです。~~単純に if の条件漏れで Q が定義されてない場合があります。なので

Python

1Q = 0

と関数の最初に書いておけば大丈夫でしょう(初期値が 0 なのかわかりませんが)。

追記:
もうちょっとよく読みました。したらば

Python

1Q = P if Base_10_to_n(d,3)[0] == 1 else ec_double(P)

と初期値は書けますね。多分もっとネストも出来ます、が、重要なのは Q に何らかの値が入っていることです。

投稿2021/01/14 07:41

編集2021/01/14 08:39
A_kirisaki

総合スコア2853

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

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

kyamamama

2021/01/14 08:10 編集

ご回答ありがとうございます、エラーの意味がよくわかりました 初期値を同じように設置すると、エラーはなくなりました。しかし、 G1,G2,G3の値がすべて一緒になってしまいました… 実際にはそれぞれ(1,2),(10,0),(1,9)となります ```ここに言語を入力 def third_mathod(P,d): Q = P if Base_10_to_n(d,3)[0] == 1 else ec_double(P) for bit in Base_10_to_n(d,3)[1:]:#1番目の要素から最後の要素まで取得 Q=ec_third(Q) if bit =="1": Q=ec_add(Q,P) elif bit =="2": Q=ec_add(Q,P) Q=ec_add(Q,P) return Q G1=third_mathod(G,1) G2=third_mathod(G,2) G3=third_mathod(G,3) print(G1)#(10,0) print(G2)#(10,0) print(G3)#(10,0) ```
A_kirisaki

2021/01/14 08:23

そこについては質問の範囲外になってしまうので頑張ってねとしか……。一つ一つの関数が正しい値を返しているのか確かめてください。「ユニットテスト」を書いておくのも手でしょう。複雑な計算は関数ごとにきちんとチェックしていくのがポイントです。そして自動でテストを走らせるとコードを変更したときに値が変わるふるまいをしても気がつけるので便利です。pytest というのが使えるので試してみると良いでしょう。 あとは if 文は必ず else 節をつけるようにするとかすると科学計算系は間違いが少なくなって有効です。
kyamamama

2021/01/15 03:09

ご回答ありがとうございます、参考人させていただきます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問