[英]Python variable not seen by nested function
我正在建立一个解决数独难题的程序。 这是代码:
def set_table(boxes_v, boxes_h, tiles_v, tiles_h):
""" boxes_v = boxes on vertical side of the whole table;
boxes_h = boxes on horixontal side of the whole table;
tiles_v = tiles on vertical line in each box;
tiles_h = tiles on horizontal line in each box.
"""
total_boxes = boxes_v * boxes_h
tiles_in_box = tiles_v * tiles_h
return [[{None : [False, 0]} for x in range(1, tiles_in_box + 1)] for a in range(total_boxes)]
def insert_numbers(table, numbers_and_positions):
""" table = sudoku table set up in "set_table";
numbers_and_postions = dictionary containing already given numbers and their positions in the table.
"""
noPos = numbers_and_positions
for number in noPos:
box = noPos[number][0]
tile = noPos[number][1]
table[box][tile] = {None : [True, number]}
return table
def test(table, index, number):
"Tests if number is suitable in a tile on vertical and horizontal lines"
box_index, tile_index = index
lines = {
0 : [(0,1,2), (0,3,6)],
1 : [(0,1,2), (1,4,7)],
2 : [(0,1,2), (2,5,8)],
3 : [(3,4,5), (0,3,6)],
4 : [(3,4,5), (1,4,7)],
5 : [(3,4,5), (2,5,8)],
6 : [(6,7,8), (0,3,6)],
7 : [(6,7,8), (1,4,7)],
8 : [(6,7,8), (2,5,8)]
}
box_line_h, box_line_v = lines[index[0]]
tile_line_h, tile_line_v = lines[index[1]]
################################### horizontal line tester
taken_numbers_h = []
for box_index in box_line_h:
index_counter = 0
for tile in table[box_index]:
if index_counter in tile_line_h:
taken_numbers_h.append(tile[None][1])
index_counter += 1
################################### vertical line tester
taken_numbers_v = []
for box_index in box_line_v:
index_counter = 0
for tile in table[box_index]:
if index_counter in tile_line_v:
taken_numbers_v.append(tile[None][1])
index_counter += 1
################################### box tester
taken_numbers_b = []
for tile in table[box_index]:
taken_numbers_b.append(tile[None][1])
###################################
taken_numbers = taken_numbers_h + taken_numbers_v + taken_numbers_b
if number in taken_numbers:
return True
elif number not in taken_numbers:
return False
def reset_key(dictionary, old_key, new_key, value):
"Resets a key of a dictionary to a different name"
dictionary[new_key] = dictionary[old_key]
del dictionary[old_key]
return dictionary
def solve(table):
""" Solves the sudoku puzzle
"""
box_index = 0
tile_index = 0
safe = True
def repeat():
tile[None][1] += 1
if tile[None][1] > 9:
tile[None][1] = 0
safe = False
tile_index -= 1
elif tile[None][1] <= 9:
if test(table, [box_index, tile_index], tile[None][1]) is True:
repeat()
elif test(table, [box_index, tile_index], tile[None][1]) is False:
tile_index += 1
safe = True
valid = False
while valid is not True:
box = table[box_index]
tile = box[tile_index]
if tile[None][0] is True:
if safe is True:
tile_index += 1
safe = True
elif safe is False:
tile_index -= 1
elif tile[None][0] is False:
repeat()
我在Python Shell中所做的是:
>>>table = set_table(3,3,3,3)
>>>table = insert_numbers(table, {0 : [0,4]})
>>>solve(table)
我期望发生的是该程序将表[0](框1)上每个字典的值更改为{None:[False,1]},{None:[False,2]},{None:[False, 3]},依此类推,直到它在整个网格的第一个大框内的最后一个小框处达到9为止,因为代码应引起索引错误。 这是因为当到达第一个大盒子中的最后一个小盒子时,应该针对数字1-8违反规则的测试结果为负,因为它们显然已经在盒子中了。 但是,我没有看到此错误,而是看到了以下错误:
Traceback (most recent call last):
File "<pyshell#2>", line 1, in <module>
solve(t)
File "C:\Users\cdobr\Desktop\Sudoku Solver.py", line 153, in solve
repeat()
File "C:\Users\cdobr\Desktop\Sudoku Solver.py", line 129, in repeat
if test(table, [box_index, tile_index], tile[None][1]) is True:
UnboundLocalError: local variable 'tile_index' referenced before assignment
我应该怎么做才能解决这个问题? 好像函数内部的函数看不到父级的变量。
tile_index
是一个非局部变量,但您未指定该变量。 您可以使用nonlocal
显式地执行此操作:
def repeat():
nonlocal tile_index
为什么nonlocal
来此,而不是任何其他非本地变量来指定? 由于这一行:
tile_index -= 1
递归调用使之得以执行。 但是,在进行赋值时,除非另有说明,否则python假定变量是局部变量。 其他非局部变量均未分配/更新,因此不适用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.