Python报UnboundLocalError:局部变量key赋值前被引用问题求解
UnboundLocalError: 变量key赋值前被引用 问题排查
问题现象
一周前刚开始学习Python,运行自行编写的字符串加密程序时,控制台抛出异常:UnboundLocalError: local variable 'key' referenced before assignment。已知该报错的常见诱因是变量完成赋值定义前被引用,但代码中已经对key变量做了赋值操作,无法定位错误触发点,完整代码如下:
from stat import SF_APPEND import time import random keyType = 0 key = 0 deCypherKey = 0 operationType = 0 needToLoop = True alphabet = "abcdefghijklmnopqrstuvwxyz " print("ogulSifreleyici v1.0") time.sleep(0.3) print("Ipucu: Hem Sifrelemek Hem de Desifrelemek Icin Programi 2 Kere Calistirabilirsiniz") def cypher(): message = input("Mesajini Gir:\n") message = message.lower() unCypheredMessageLength = len(message) letterOfMessageInQueue = 0 keyStr = str(key) keyStrInt = 0 whichOrderOfAlphabet = 0 whichLetterOfAlphabet = " " whichDigitOfKey = 0 orderOfCypheredLetter = 0 cypheredLetter = "a" cypheredMessageList = [] cypheredStr = "" while unCypheredMessageLength > 0: whichLetterOfAlphabet = alphabet[whichOrderOfAlphabet] if message[letterOfMessageInQueue] == whichLetterOfAlphabet: print("match") print(whichOrderOfAlphabet, message[letterOfMessageInQueue], whichLetterOfAlphabet) keyStrInt = int(keyStr[whichDigitOfKey]) orderOfCypheredLetter = whichOrderOfAlphabet + keyStrInt if orderOfCypheredLetter > 26: orderOfCypheredLetter = orderOfCypheredLetter - 26 cypheredLetter = alphabet[orderOfCypheredLetter] cypheredMessageList.append(cypheredLetter) unCypheredMessageLength = unCypheredMessageLength - 1 letterOfMessageInQueue = letterOfMessageInQueue + 1 whichOrderOfAlphabet = 0 whichDigitOfKey = whichDigitOfKey + 1 if whichDigitOfKey > 4: whichDigitOfKey = whichDigitOfKey - 5 if len(cypheredMessageList) == len(message): cypheredStr = "".join(cypheredMessageList) print("Sifrelenmis Mesajiniz:\n" + cypheredStr) time.sleep(1) lastUserAnswer = input("1-Sifrele(Ayni Anahtar) 2-Sifrele(Farkli Anahtar)\n") if lastUserAnswer == "1": cypher() if lastUserAnswer == "2": key = input("Anahtar Giriniz(5 Haneli Sayi):\n") while len(str(key)) != 5: key = input("Lutfen Bes Haneli Bir Sayi Giriniz\n") if len(str(key)) == 5: cypher() cypher() else: whichOrderOfAlphabet = whichOrderOfAlphabet + 1 def deCypher(): deCypherMessage = input("Sifreli Mesajinizi Giriniz:\n") operationType = input("1-Sifrele 2-DeSifrele\n") while needToLoop == True: if operationType == "1": keyType = input("1-Anahtar gir(5 haneli sayi) 2-Rastgele Anahtar\n") if keyType == "1": key = input("Anahtar Giriniz:\n") while len(str(key)) != 5: key = input("Lutfen Bes Haneli Bir Sayi Giriniz\n") if len(str(key)) == 5: needToLoop = False cypher() needToLoop = False cypher() if keyType == "2": key = int(random.uniform(10000, 100000)) print("Anahtariniz: " + str(key)) cypher() needToLoop = False else: print("Lutfen Seceneklerden Birini Seciniz") needToLoop = True if operationType == "2": deCypherKey = input("Anahtarinizi Giriniz:\n") while len(str(deCypherKey)) != 5: key = input("Lutfen Bes Haneli Bir Sayi Giriniz\n") if len(str(key)) == 5: needToLoop = False deCypher() needToLoop = False deCypher() else: print("Lutfen Seceneklerden Birini Seciniz") needToLoop = True
错误根因
Python的作用域规则:只要函数内部存在对某个变量的赋值操作,Python就会将该变量判定为当前函数的局部变量,不会去外层全局作用域查找同名变量,无论这个赋值语句在函数的哪个位置。
代码中两处触发该问题:
cypher()函数内部,在加密完成后选择"使用新密钥重新加密"的分支中,存在key = input(...)的赋值语句,因此Python将整个cypher()函数内的key都判定为局部变量。但函数开头第一处引用key的代码keyStr = str(key)执行时,局部变量key还未完成赋值,直接触发报错。- 解密选项的密钥校验循环中存在笔误,本该给
deCypherKey赋值的位置写了key = input(...),同样会触发同规则下的提前引用问题。
修复方案
- 在
cypher()函数开头添加全局变量声明global key,明确告诉Python函数内使用的key是外层定义的全局变量,不是局部变量。 - 修正解密分支的笔误:将密钥长度校验循环里的
key = input("Lutfen Bes Haneli Bir Sayi Giriniz\n")改为deCypherKey = input("Lutfen Bes Haneli Bir Sayi Giriniz\n"),保持变量名一致。 - 调整主循环的分支缩进:当前代码在用户输入符合要求的5位密钥并调用
cypher()后,还会无条件再执行一次cypher(),导致重复加密,需要把分支外无意义的cypher()调用放到正确的判断逻辑内,避免重复执行。
作用域问题最小复现与参考修复
错误写法(和你遇到的报错完全一致):
key = 12345 def cypher(): print(key) # 此处触发UnboundLocalError,因为下方存在key的赋值,Python判定key为局部变量 key = 67890 cypher()修复写法:
key = 12345 def cypher(): global key # 声明key为全局变量 print(key) key = 67890 # 此处修改的是全局的key变量 cypher()
内容的提问来源于stack exchange,提问作者oas333
相关产品推荐
相关产品推荐

