在Python中定义列表列表的第一个元素

时间:2018-11-26 08:32:49

标签: python list

我有一个学校作业,因此我们必须使用PyCharm并遵守关于Python3的PEP8和Google标准。虽然我的代码运行良好,但PyCharm声称row [0]的索引具有意外值。

def create_matrix():
"""
    Function made to create a matrix of who wins or who loses based on the number of figures in a game.
    Keep in mind the order of the figures tuple. first element wins over second element, last element wins over
    first element. an element also wins against the element two steps before it, in the case of five elements.
    i haven't researched what relationships exist in higher dimensions, but there will always be an equal amount of
    elements who beat you, as elements you beat. the missing element will be a draw.
"""
figures = ("Scissors", "Paper", "Rock", "Lizard", "Spock")  # caution with order of elements
number_of_figures = len(figures)  # expected to be an odd number
half_set = number_of_figures // 2  # half_set = int((n-1)/2)

win_and_lose = [+1, -1]  # negative: row (player_b), positive: column (player_a), zero: draw
rows = [[None]*number_of_figures]*number_of_figures  # uses same size in memory as a "full" set

rows[0] = [0] + win_and_lose*half_set  # [0, -1, +1, -1, +1...]

for row in range(1, number_of_figures):
    rows[row] = rotate(rows[row-1], 1)

# for row in range(0, len(rows)):
#    print(rows[row])
return figures, rows

Linter warning

我已经测试过更改特定行,这给了我一个警告

    rows[0][0], rows[0][1], rows[0][2], rows[0][3], rows[0][4] = [0] + win_and_lose*half_set  # [0, -1, +1, -1, +1...]

并且该代码在没有任何棉绒警告的情况下工作。我的问题是我希望元组的大小可扩展。我知道我可以通过

的for循环来做到这一点
    for column in range(0, number_of_figures):
    if column == 0:
        rows[0][column] = 0
    elif column % 2 == 0:
        rows[0][column] = +1
    elif column % 2 == 1:
        rows[0][column] = -1
    else:
        raise Exception("Unexpected column value")

但是我对此有一些疑问:

1)对于想要查看代码的人来说根本无法理解。
2)当我现在尝试打印列表时,它已将所有行设置为[0,-1,+1,+1,-1],而不仅仅是我期望的第一个元素。这不会导致任何运行时错误,但这不是我想要的。

我的问题是,如何在不违反任何Python标准的情况下,以pythonic且易于阅读的方式编写这段代码。

奖励问题: 我想减少代码的内存使用量,并且通过__sizeof __()看到,如果行包含五个值为None的元素,则它将使用80个字节的内存。如果我有五个值为[None,None,None,None,None]的元素,则使用相同的大小。一旦为矩阵设置了一些值,大小将保持不变。有什么提示吗?我已经设置了rotate()函数,以便可以一次旋转列表n个位置,因此我可以跳到定义了第一行的任何给定行。

2 个答案:

答案 0 :(得分:2)

PyCharm抱怨是因为您将rows初始化为None列表的列表,然后将其重新分配为int列表的列表。不管这是一个警告,您都可以放心,因为动态类型是应该要做的事情(如果您要进行静态类型,请使用静态语言编写)。

您可以通过简单地将其初始化为以下方式来修复它:

rows = [[0 for _ in range(number_of_figures)] for _ in range(number_of_figures)]
# this is identical to `[[0] * number_of_figures] * number_of_figures` except it
# avoids the duplication of references issue you were experiencing that DYZ
# pointed out in the comments above.

答案 1 :(得分:0)

假设在第一个解决方案中不存在DYZ的注释,则可以使用type hinting帮助linter理解行的类型。在我的代码中,这消除了棉绒警告。

rows = [[None]*number_of_figures]*number_of_figures  # type: list #uses same size in memory as a "full" set

此语法也可用于python 3:

rows:list = [[None]*number_of_figures]*number_of_figures