用Python的方式还是可以更轻松地理解?

时间:2019-04-29 10:17:29

标签: python

我试图成为更多的Pythonic和更少的C ++。但是,所有行数最多不能超过79个字符会造成每天的挣扎。这是一个示例:

def list_of_possible_moves(self):  # version 1
    return [] if self._state != Game.play else [index for index, square in enumerate(self._board) if square == TicTacToe.square_free]

它是138个字符长,必须打破。 (1)三行:

def list_of_possible_moves(self):  # version 2
    return [] if self._state != Game.play else\
        [index for index, square in enumerate(self._board)
         if square == TicTacToe.square_free]

(2)可能以两行显示(i,s代替索引,正方形)。仍然是80,而不是79:

def list_of_possible_moves(self):  # version 3
    return [] if self._state != Game.play else\
        [i for i, s in enumerate(self._board) if s == TicTacToe.square_free]

(3)最后,我决定保留该版本:

def list_of_possible_moves(self): # version 4 (C++)
    if self._state is not Game.play:
        return []
    list_of_moves = []
    for index, square in enumerate(self._board):
        if square == TicTacToe.square_free:
            list_of_moves.append(index)
    return list_of_moves

我做错了什么?有更好的方法编写这段代码吗?

4 个答案:

答案 0 :(得分:6)

这是样式/口味问题;如有疑问,请在代码上使用black代码格式化程序;如果在Black之后看起来丑陋,请将其拆分为多个语句。

我会“拆分差异”并先处理特殊情况,然后使用列表理解。

def list_of_possible_moves(self):
    if self._state is not Game.play:  # Not playing, no moves possible.
        return []
    return [
        index
        for index, square in enumerate(self._board)
        if square == TicTacToe.square_free
    ]

答案 1 :(得分:4)

首先,您可以扩展if, else单线:

def list_of_possible_moves(self):
    if self._state != Game.play:
        return []
    else:
        return [index for index, square in enumerate(self._board) if square == TicTacToe.square_free]

但是它仍然更长。 打破理解的一种好方法是根据Google styleguide的建议使用值-for-条件:

def list_of_possible_moves(self):
    if self._state != Game.play:
        return []
    else:
        return [
            index 
            for index, square in enumerate(self._board) 
            if square == TicTacToe.square_free
        ]

但是,如果您不想扩展它,可以将index重命名为i,这在1.理解和2. enumerate中完全有效。您也可以重命名square

def list_of_possible_moves(self):
    if self._state != Game.play:
        return []
    else:
        return [i for i, sq in enumerate(self._board) if sq == TicTacToe.square_free]

这里是85个字符长,所以有点太长了,但这通常可以减少行数。

答案 2 :(得分:4)

长版本是最可重用的版本,您仍然可以使用理解管道:

def list_of_possible_moves(self): # version 4 (C++)
    if self._state is not Game.play:
        return []
    non_squares_indexes = [
        i for i, x in enumerate(self._board) if x == TicTacToe.square_free
    ]
    return non_squares_indexes

答案 3 :(得分:4)

在框外思考一下-考虑self._state检查是否真正属于此代码级别。如果您的班级需要在多个地方检查self._state,这很奇怪,建议您replace the conditional logic with polymorphism。现在,您为主要的游戏状态指定了一个单独的类,该类通过理解来确定可能的动作。以及其他游戏状态的其他类,这些状态只会为您提供空列表-假设您确实需要将其作为界面的一部分(请考虑是否确实需要在不玩游戏时检查可用动作的列表) !)。