Python while循环无法识别变量状态变更的问题排查
问题描述
开发用户名输入校验逻辑时,预期实现效果:当用户输入的名称包含数字、特殊符号等非普通字母内容时,程序提示用户重新输入。
实际运行异常:while循环始终无法识别校验状态变量的变更,无论输入什么内容都会持续执行循环逻辑,初步推测问题与def定义的函数内部修改变量的作用域机制有关。
原始实现代码如下:
from cgi import test from re import T import time import math big_nono_numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9,] big_nonosymbols = ["!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "-", "", "=", "+", ":", ";", "{", "}", "[", "]", "'", ">", "<", "/", "?"] yesyesyesses = ['yes', 'y', 'ye', 'ys', 'k', 'ok', 'sure', 'alright', 'okay'] nononoes = ['no', 'n', 'nah', 'na', 'never', 'i dont', 'not really', 'im good',] v1 = False v2 = False v3 = True def space(): print('') def validate1(): if i2.find('`') >=0: v2 = False elif i2.find('~') >=0: v2 = False elif i2.find('!') >=0: v2 = False elif i2.find('@') >=0: v2 = False elif i2.find('#') >=0: v2 = False elif i2.find('$') >=0: v2 = False elif i2.find('%') >=0: v2 = False elif i2.find('^') >=0: v2 = False elif i2.find('&') >=0: v2 = False elif i2.find('*') >=0: v2 = False elif i2.find('(') >=0: v2 = False elif i2.find(')') >=0: v2 = False elif i2.find('-') >=0: v2 = False elif i2.find('=') >=0: v2 = False elif i2.find('_') >=0: v2 = False elif i2.find('+') >=0: v2 = False elif i2.find('[') >=0: v2 = False elif i2.find('{') >=0: v2 = False elif i2.find(']') >=0: v2 = False elif i2.find('}') >=0: v2 = False elif i2.find('|') >=0: v2 = False elif i2.find(';') >=0: v2 = False elif i2.find(':') >=0: v2 = False elif i2.find("'") >=0: v2 = False elif i2.find('"') >=0: v2 = False elif i2.find(',') >=0: v2 = False elif i2.find('<') >=0: v2 = False elif i2.find('.') >=0: v2 = False elif i2.find('>') >=0: v2 = False elif i2.find('/') >=0: v2 = False elif i2.find('?') >=0: v2 = False elif i2.find('0') >=0: v2 = False elif i2.find('1') >=0: v2 = False elif i2.find('2') >=0: v2 = False elif i2.find('3') >=0: v2 = False elif i2.find('4') >=0: v2 = False elif i2.find('5') >=0: v2 = False elif i2.find('6') >=0: v2 = False elif i2.find('7') >=0: v2 = False elif i2.find('8') >=0: v2 = False elif i2.find('9') >=0: v2 = False else: v2 = True print(v2) def test(): print(1) chatbot_run = True space print('Welcome to Astronaugt-for-hire!') time.sleep(1) i1 = input('Do you want to hire an astronaught? ') if i1 in yesyesyesses: v1 = True space time.sleep(3) print("That's Great! First you will have to create an account.") elif i1 in nononoes: v1 = True time.sleep(2) print('WELL TOO BAD! YOU ARE ANYWAY. Time to make an account.') while v1 == False: i1 = input('Could you say that again? ') if i1 in yesyesyesses: v1 = True time.sleep(3) print("That's Great! First you will have to create an account.") elif i1 in nononoes: v1 = True time.sleep(1) print('WELL TOO BAD! YOU ARE ANYWAY. Time to make an account.') time.sleep(1) print('Lets start.') time.sleep(1.5) i2 = input('Step 1. What is your name? ') validate1() test() while v2 == False: i2 = input('please try again') validate1()
问题根因
- 核心原因是Python变量作用域规则:在
validate1()函数内部给v2赋值时,Python默认将v2识别为函数内的局部变量,不会修改全局作用域下初始值为False的v2。外层while循环判断的始终是全局的v2,自然会无限执行。 - 附带代码问题:
- 所有调用
space的位置都没加括号,仅写函数名不会执行打印空行的逻辑,只是引用了函数对象。 validate1直接读取全局变量i2,函数和外层逻辑耦合度极高,不利于维护。- 逐字符调用
find判断非法字符的写法冗余度极高,几十行判断完全可以用内置字符串方法简化。
- 所有调用
修复方案
快速修复(仅解决当前作用域问题)
在validate1函数开头添加global v2声明,明确告诉Python函数内操作的v2是全局变量,同时把所有space调用改为space()补全括号。
def validate1(): global v2 # 新增全局变量声明 # 原有判断逻辑不变
规范修复(推荐,彻底规避全局变量问题)
废弃全局变量传值的写法,让校验函数接收待校验字符串作为入参,直接返回布尔类型的校验结果,同时用字符串内置方法简化校验逻辑:
def space(): print('') def validate1(input_str): # 只要输入包含任意非字母字符,就返回校验不通过 for char in input_str: if not char.isalpha(): return False return True
对应调整主逻辑里的调用方式,直接用函数返回值做循环判断,不需要额外维护全局状态变量:
space() print('Welcome to Astronaugt-for-hire!') time.sleep(1) i1 = input('Do you want to hire an astronaught? ') v1 = False if i1 in yesyesyesses: v1 = True space() time.sleep(3) print("That's Great! First you will have to create an account.") elif i1 in nononoes: v1 = True time.sleep(2) print('WELL TOO BAD! YOU ARE ANYWAY. Time to make an account.') while v1 == False: i1 = input('Could you say that again? ') if i1 in yesyesyesses: v1 = True time.sleep(3) print("That's Great! First you will have to create an account.") elif i1 in nononoes: v1 = True time.sleep(1) print('WELL TOO BAD! YOU ARE ANYWAY. Time to make an account.') time.sleep(1) print('Lets start.') time.sleep(1.5) i2 = input('Step 1. What is your name? ') while not validate1(i2): i2 = input('输入包含数字或特殊符号,请重新输入:')
内容的提问来源于stack exchange,提问作者MISTERME
相关产品推荐
相关产品推荐

