【问题标题】:How to convert a conditional statement to a simple expression? Is compounding a return this way Acceptable practice?如何将条件语句转换为简单表达式?以这种方式复合回报是否可以接受?
【发布时间】:2023-03-14 01:15:01
【问题描述】:

我正在做的练习是由一本接受字典参数并要求我给出 True 或 False 的返回值的书给出的。我是 Python 3 的新手,作为个人学习练习,我想将“作为棋盘的有效字典”的所有条件转换为单个返回值。我还没有真正测试过这段代码的错误,因为它还没有完成,但我确实通过我找到的在线验证器运行了它https://extendsclass.com/python-tester.html

我想知道如何将以下 2 个代码块转换为简单的表达式,以便在下面的函数中的 return 语句中使用,您可以在下面看到我已经将大多数表达式转换为返回值" 因为“所有表达式都必须 == True”

for pieces in dictionary.values():
    if all(pieces.startswith('b')) or \
         all(pieces.startswith('w')):
        return True
    else:
        return False

上面的代码块循环遍历传递给函数的字典键作为“片段”, 并单独比较每个键以确定它是否以“b”或“w”的值开头。因此,如果任何键不以“b”或“w”开头,则字典“棋盘”为假,因为它包含不正确的棋子。好的,我想我看到了一个错误,我将对其进行调查并尝试解决。好的,我注意到上面代码中有一些错误需要解决我目前正在研究如何正确执行上面的代码。

for square in dictionary:
    try:
        if int(square[:0]) <= 8 and \
            square[-1] <= 'h':
            return True
        else:
            return False
    except ValueError:
        return False

我在上面的代码块上工作了很长时间,但仍然不确定这是我想要它做的“最佳”实现。但我还是新手,我已经尽力了。 无论如何,它切片字典键并比较键中的第一个字符以确保它不超过 8,这是最大“有效范围”,如果超过有效范围,它返回 false,并且任何非 int 显然自动为 False 并返回由“例外”。

然后它对字典键进行切片以获取字典键的最后一个字符,并将其与

这是当前的函数,末尾有一个测试字典:

def cBV(dic):                        # (c)hess(B)oard(V)alidator
    Err = 'Error: Invalid Board -'
    if not isinstance(dic, type({})):
        raise TypeError('Object passed to cBV is not of type <class dict>')
    
    chess_pieces = {'bk pieces': 0, 'wh pieces': 0,
                    'bk pawns': 0, 'wh pawns': 0}

    # converts dictionary values into keys and assigns those keys "counn of values"      
    for squares, pieces in dic.items:
        if pieces.startswith('b'):                 # alt if pieces[:0] == 'b':
            if pieces.startswith('bpawn'):         # alt if pieces == 'bpawn':
                chess_pieces['bk pawns'] += 1
            chess_pieces['bk pieces'] += 1
        elif pieces.startswith('w'):
            if pieces.startswith('wpawn'):
                chess_pieces['wh pawns'] += 1
            chess_pieces['wh pieces'] += 1
        
    return 'wking' in dic.values() and \                
            'bking' in dic.values() and \
            chess_pieces['bk pieces'] <= 16 and \
            chess_pieces['wh pieces'] <= 16 and \ 
            chess_pieces['bk pawns'] <= 8 and \
            chess_pieces['wh pawns'] <= 8 and \ 
            


dict = {'8h': 'wking', '2c': 'bking', '3a': 'wpawn', '3b': 'wpawn', '3c': 'wpawn',
    '3d': 'wpawn', '3e': 'wpawn', '3f': 'wpawn', '3g': 'wpawn', '3h': 'wpawn', '4b': 'wpawn'}
test = cBV(dict)
print('Is this a valid chessboard? ' + str(test))

【问题讨论】:

    标签: python-3.x return


    【解决方案1】:

    你现在拥有的东西很好,你应该感到自豪 - 有更多花哨的技术可以让事情变得更简洁,当你深入了解各种数据结构的工作原理时,你会更加习惯它们。

        for pieces in dictionary.values()
            if pieces.startswith('b') or \
                 pieces.startswith('w'):
                return True
            else:
                return False
    

    可以转为单行

    return all(
        piece.startswith('b') or piece.startswith('w')
        for piece in dictionary.values()
    )
    

    它做了一些事情。

    • all() 函数接受任何可迭代对象,如果该可迭代对象中的所有值都是真值,则返回 True。如果其中一个不存在,则它会“短路”并返回 False
    • 作为我们对all() 的论据,我们给出了“理解”。理解本质上是一个单行 for 循环,形式为 f(element) for element in iterable:它执行任何 f(element) 是,对于可迭代中的每个 element
      • 在我们的例子中,可迭代对象是dictionary.values(),它返回dictionary(这里是'wking', 'wpawn', ...)中的所有(但不包括键)。在这种情况下,这些是字符串。
      • piece 是我们为理解的每个“迭代”分配的每个元素。它将运行piece = 'wking',然后运行piece = 'wpawn',等等。
      • piece.startswith('b') or piece.startswith('w') 是我们为每个 piece 执行的函数。这将输出TrueFalse,具体取决于是否满足条件。
      • 您可以将推导式括在方括号[] 中,以将其作为常规列表输出。但是,如果您将理解作为参数提供给像 all() 这样的函数,这就是我们在这里所做的,那么它将最终成为一个“生成器”,一个稍微高效的对象,它只计算一个对象时间。对我们而言,这并不重要。
      • 总体而言,理解生成一个包含TrueFalse 的系列,all() 将使用该系列。

    与您的第二个代码 sn-p 类似。您已经掌握了基础知识,但可以更简洁。你的代码:

    def allSquaresAreInRange(dictionary):
        for square in dictionary:
            try:
                if int(square[:0]) <= 8 and \
                    pieces[-1] <= 'h':
                    return True
                else:
                    return False
            except ValueError:
                return False
    

    可以变成

    def allSquaresAreInRange(dictionary):
        try:
            return all(
                (1 <= int(row) <= 8) and ('a' <= col <= 'h')
                for (row, col) in dictionary
            )
        except ValueError:
            return False
    

    这里我们利用了一些东西:

    • 和以前一样,我们使用all(),和以前一样,我们使用理解。但是这一次,我们直接遍历dictionary
      • 遍历dict 在功能上与遍历dict.keys() 相同。所以,我们正在遍历键 '8h', '2c', ...
    • 每个键都是一个两个字符的字符串。字符串是可迭代的,就像列表一样,并且大多数可迭代对象都有一个有趣的属性,称为“多重赋值”:如果我们分配的变量与可迭代对象的元素数量完全相同,那么这些元素就会被拆分。
      • 例如,(row, col) = '8h' 在功能上与row = '8h'[0]col = '8h'[1] 相同。在这两种情况下,我们都剩下row = '8'col = 'h'
      • 如果任一侧的元素数量不匹配,则会生成ValueError - 例如,如果键只有一个字符,或者只有三个字符。这样做的一个副产品是,rowcol 被保证是恰好是一个字符的长字符串,如果该错误没有发生的话。
    • 我们的条件检查row 是否在1 和8 之间,以及col 是否在A 和H 之间,使用大于/小于符号。这将再次返回 TrueFalse
      • 正如您所发现的,在不代表整数的对象上使用int()也会抛出ValueError
    • 这个新的 sn-p 保留了您想出的 try/except 块,因为它们工作得很好。

    Python 有一种以“高效编写”代码为荣的文化。也就是说,看起来尽可能花哨的代码,并遵循函数式编程范式。理解以及all()any() 是其中的重要组成部分,因此它们可能是它们解决的任何问题的“正确”解决方案(如果他们可以写得简洁)。

    同样,sn-p

    if condition:
        return True
    else:
        return False
    

    几乎总是可以压缩成

    return condition
    

    (或return bool(condition),如果condition 处理具有真实性但不是布尔值的值,例如None 或空列表或字符串)。如果这适用,这是一种很好的做法(但同样,它并不总是适用)。

    不过,最重要的是,您的代码可以按照您希望的方式运行,并且足够清晰,您可以在几个月后回到它并弄清楚 什么 你正在这样做,以及为什么你这样做。在某些情况下, 可以写成推导式,但这会使它们变得极其复杂和不可读——在这些情况下,有时最好不要将它们写成推导式,而是写得更冗长方式。在您继续开发时请记住这一点,您会做得很好。

    【讨论】:

    • 我学到了很多东西。只是为了澄清你是否在第二部分中说我可以定义上述函数,然后像这样在我当前函数的“返回”中使用它? def cBV(dic): return allSquaresAreInRange(dictionary)
    • 您可能希望将其定义为第二个函数,然后在 if 语句中调用它。请记住,return完全跳出你的函数,不管它后面是什么,所以如果你需要在if 语句中做一些复杂的事情,你可以构建一个更小的函数,然后调用它来获取它的返回值。
    猜你喜欢
    • 2016-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-24
    • 2016-10-02
    • 2011-12-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多