繁体   English   中英

嵌套函数无法看到Python变量

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM