Python:可以交换数学运算符以避免代码重复吗?

Python: Possible to exchange math operators so as to avoid code duplication?

我有这个功能(见下文),看起来它会自己重复四次。这四个代码片段非常相似,它们只是在一些数学运算符上有所不同。是否可以缩短此代码?我找不到办法,但我希望能够调用一个函数(在函数中)交换代码片段中的“-”、“+”和“<”/“>”符号,这样我就可以不必重复?

代码

def diag_grannar(storlek,troll_position): #funktion som kollar efter diagonala grannar
    ny_rad = troll_position[0]
    ny_kol = troll_position[1]
    diag_grannar = []

    # while-loopen letar efter diagonala grannar snett vänster ovanifrån troll_position
    while True:
        ny_rad -= 1
        ny_kol -= 1
        if ny_rad >= 1 and ny_kol >= 1:
            diag_grannar.append([ny_rad,ny_kol])
        else:
            ny_rad = troll_position[0]
            ny_kol = troll_position[1]
            break

    # while-loopen letar efter diagonala grannar snett vänster nedanifrån troll_position
    while True:
        ny_rad += 1
        ny_kol -= 1
        if ny_rad <= storlek and ny_kol >= 1:
            diag_grannar.append([ny_rad,ny_kol])
        else:
            ny_rad = troll_position[0]
            ny_kol = troll_position[1]
            break

    # while-loopen letar efter diagonala grannar snett höger nedanifrån troll_position
    while True:
        ny_rad += 1
        ny_kol += 1
        if ny_rad <= storlek and ny_kol <= storlek:
            diag_grannar.append([ny_rad,ny_kol])
        else:
            ny_rad = troll_position[0]
            ny_kol = troll_position[1]
            break

    # while-loopen letar efter diagonala grannar snett höger ovanifrån troll_position
    while True:
        ny_rad -= 1
        ny_kol += 1
        if ny_rad >= 1 and ny_kol <= storlek:
            diag_grannar.append([ny_rad,ny_kol])
        else:
            ny_rad = troll_position[0]
            ny_kol = troll_position[1]
            break

    return diag_grannar

为了清楚起见,我指的是这些代码片段:

while True:
    ny_rad -= 1
    ny_kol += 1
    if ny_rad >= 1 and ny_kol <= storlek:
        diag_grannar.append([ny_rad,ny_kol])
    else:
        ny_rad = troll_position[0]
        ny_kol = troll_position[1]
        break

此致;

让我们从彻底摆脱循环开始:

def diag_grannar(storlek,troll_position):
    ny_rad = troll_position[0]
    ny_kol = troll_position[1]
    diag_grannar = []

    diag_grannar.extend([x,y] for x, y in zip(range(ny_rad-1, 0, -1), range(ny_kol-1, 0, -1)))
    diag_grannar.extend([x,y] for x, y in zip(range(ny_rad+1, storlek+1), range(ny_kol-1, 0, -1)))
    diag_grannar.extend([x,y] for x, y in zip(range(ny_rad+1, storlek+1), range(ny_kol+1, storlek+1)))
    diag_grannar.extend([x,y] for x, y in zip(range(ny_rad-1, 0, -1), range(ny_kol+1, storlek+1)))

    return diag_grannar

现在我们可以根据需要尝试反转范围。 range(x-1, 0, -1) 等同于 reversed(range(1, x)).

def diag_grannar(storlek,troll_position):
    ny_rad = troll_position[0]
    ny_kol = troll_position[1]
    diag_grannar = []

    xs = range(1, ny_rad + 1)
    ys = range(1, ny_kol + 1)

    diag_grannar.extend(list(t) for t in zip(reversed(xs), reversed(ys))
    diag_grannar.extend(list(t) for t in zip(xs, reversed(ys))
    diag_grannar.extend(list(t) for t in zip(xs, ys))
    diag_grannar.extend(list(t) for t in zip(reversed(xs), ys))
    return diag_grannar

我们可以遍历同一事物的各种参数化...需要注意的是,我们始终可以使用加法而不是交换数学运算符,只需添加 1 或 -1(比交换匹配运算符更容易)

def diag_grannar1(storlek,troll_position): #funktion som kollar efter diagonala grannar
    ny_rad = troll_position[0]
    ny_kol = troll_position[1]
    diag_grannar = []
    def diag_compare(v1, leq):
        if leq:
            return v1 <= storlek
        else:
            return v1 >= 1
    params = [((-1, -1, False, False)),
              ((1, -1, True, False)),
              ((1, 1, True, True)), 
              ((-1, 1, False, True))]

    for v1, v2, leq1, leq2 in params:
        while True:
            ny_rad += v1
            ny_kol += v2
            if diag_compare(ny_rad, leq1) and diag_compare(ny_kol, leq2):
                diag_grannar.append([ny_rad,ny_kol])
            else:
                ny_rad = troll_position[0]
                ny_kol = troll_position[1]
                break

    return diag_grannar

如果将重复的代码放在一个函数中,您可以将内置 operator 模块中的函数作为参数传入,然后使用它们。