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

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

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

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

Python

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

Q&A

解決済

2回答

1502閲覧

pythonの特定の変数のスコープがおかしい

退会済みユーザー

退会済みユーザー

総合スコア0

Python 3.x

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

Python

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

0グッド

0クリップ

投稿2019/10/27 19:50

二分探索木を作りたい

pythonで二分探索木について勉強しているとき、二分探索木を作る関数を作った際に特定の変数だけ使えません。

発生している問題・エラーメッセージ

#ファイル名 addBST(1) #ファイル名 print(newIdx) UnboundLocalError: local variable 'newIdx' referenced before assignment

該当のソースコード

Python3

1class BST: 2 def __init__(self): 3 data = 0 4 left = 0 5 right = 0 6 7tree = [0]*10 8for i in range(len(tree)): 9 tree[i] = BST() 10rootIdx = 0 11newIdx = 0 12 13def addBST(data): 14 currentIdx = 0 15 addFlag = False 16 print(newIdx) 17 tree[newIdx].data = data 18 tree[newIdx].left = -1 19 tree[newIdx].right = -1 20 if newIdx != rootIdx: 21 currentIdx = rootIdx 22 addFlag = False 23 while True: 24 if data < tree[currentIdx].data: 25 if tree[currentIdx].left == -1: 26 tree[currentIdx].left = newIdxaddFlag = True 27 else: 28 currentIdx = tree[currentIdx].left 29 else: 30 if tree[currentIdx].right == -1: 31 tree[currentIdx].right = newIdx 32 addFlag = True 33 else: 34 currentIdx = tree[currentIdx].right 35 if addFlag == False: 36 break 37 newIdx += 1 38 39addBST(1) 40addBST(3) 41addBST(2)

試したこと

print関数の引数を他の変数(rootIdxや新しい変数tmp)などに変えたところ、正常に出力されました。

補足情報

環境
mojave 10.14.4
python 3.5.4

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

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

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

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

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

guest

回答2

0

ベストアンサー

関数の中である変数名に対して代入文を使っていれば、その変数はローカル変数になります。
(ただの代入文の話。累積代入文や添字表記への代入は別途議論が必要)

ローカル変数だということは、ローカルスコープ内で名前解決しないといけないということです。つまり、関数ブロックの中で代入より先に参照すればエラーになります。

同名のグローバル変数がたまたまあったとしても、それはローカル変数の名前解決には関係のないことです。この考えかたは理解してください。
(ただのNameErrorにならないのがむしろ優しいといったところ)

それで、やりたいことが「この変数はグローバル変数として扱いたい」なら関数ブロックの先頭にglobal宣言を追加してください。ローカル変数でいいなら、参照の前に何らかの値を入れれば可です。

投稿2019/10/27 21:54

hayataka2049

総合スコア30933

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

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

0

インデントが、おかしくなっているのか意図的にしているのかわかりませんが、
以下のようにすれば、エラーは解消することができます。

ただ、後々newIdxという変数を使うことがあるのであれば、設計を見直すことを提案します。

python

1class BST: 2 def __init__(self): 3 data = 0 4 left = 0 5 right = 0 6 7tree = [0]*10 8for i in range(len(tree)): 9 tree[i] = BST() 10 11 12def addBST(data): 13 rootIdx = 0 14 newIdx = 0 15 currentIdx = 0 16 addFlag = False 17 print(newIdx) 18 tree[newIdx].data = data 19 tree[newIdx].left = -1 20 tree[newIdx].right = -1 21 if newIdx != rootIdx: 22 currentIdx = rootIdx 23 addFlag = False 24 while True: 25 if data < tree[currentIdx].data: 26 if tree[currentIdx].left == -1: 27 tree[currentIdx].left = newIdxaddFlag = True 28 else: 29 currentIdx = tree[currentIdx].left 30 else: 31 if tree[currentIdx].right == -1: 32 tree[currentIdx].right = newIdx 33 addFlag = True 34 else: 35 currentIdx = tree[currentIdx].right 36 if addFlag == False: 37 break 38 newIdx += 1 39 40addBST(1) 41addBST(3) 42addBST(2)

変更点としては、「addBST」関数内のローカルスコープに「newIdx」を宣言してあげることで、
「addBST」関数内で使うことができるようになります。

よくわからない場合は、下記のPythonチュートリアルを読んでみてください。
https://docs.python.org/ja/3/tutorial/classes.html#python-scopes-and-namespaces

投稿2019/10/27 20:05

Akihito_Jv

総合スコア64

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問