You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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(...),同样会触发同规则下的提前引用问题。

修复方案

  1. 在cypher()函数开头添加全局变量声明global key,明确告诉Python函数内使用的key是外层定义的全局变量,不是局部变量。
  2. 修正解密分支的笔误:将密钥长度校验循环里的key = input("Lutfen Bes Haneli Bir Sayi Giriniz\n")改为deCypherKey = input("Lutfen Bes Haneli Bir Sayi Giriniz\n"),保持变量名一致。
  3. 调整主循环的分支缩进:当前代码在用户输入符合要求的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 05:57:13