【问题标题】:What to pass when passing arguments where a list or tuple is required?传递需要列表或元组的参数时要传递什么?
【发布时间】:2014-12-20 19:01:39
【问题描述】:

我应该使用以下哪一项以及为什么?

import numpy as np
a = np.zeros([2, 3])
b = np.zeros((2, 3))

在很多情况下,您可以通过任何一种方式传递参数,我只是想知道一个是否更 Pythonic,或者是否有其他原因应该优先考虑其中一个。

我查看了this question,人们试图解释元组和列表之间的区别。这不是我感兴趣的,除非有我应该关心的原因,我当然会忽略!

更新:

虽然 numpy 被用作示例,但这通常与 python 有关。一个非numpy的例子如下:

a = max([1, 2, 3, 5, 4])
b = max((1, 2, 3, 5, 4))

我没有编辑上面的内容,因为有些答案在他们的解释中使用了 numpy

【问题讨论】:

  • 我认为这对 Stackoverflow 来说是一个很好的问题。谢谢你的提问,加一个。
  • 除非这个问题是针对 numpy 的(它似乎不是),否则最好使用通用示例。
  • 除了为可能扩展的列表预分配通常微不足道的轻微开销外,这似乎是一个很好的自行车脱落主题。
  • 我看到有人投票结束此问题是基于意见,但是,我已帮助提问者重申客观性的问题。我认为这是一个很好的问题,我认为它不应该被关闭。
  • 对不起,如果问题是基于意见的。我尽量编辑,感谢@AaronHall 的编辑。你也是对的,它不是特定于 numpy 的。

标签: python list data-structures coding-style tuples


【解决方案1】:

我在将文字可迭代传递给构造函数或函数的上下文中回答这个问题,超出该类型无关紧要。如果你需要传入一个可散列的参数,你需要一个元组。如果您需要对其进行变异,请传入一个列表(这样您就不会将元组添加到元组中,从而增加对象的创建。)

您的问题的答案是,更好的选择因情况而异。这是权衡。

list 类型开头,它是可变的,它为将来的扩展预先分配内存:

a = np.zeros([2, 3])

专业版:易读。

缺点:它会浪费内存,而且性能较差。

接下来是tuple 类型,它是不可变的。它不需要为将来的扩展预先分配内存,因为它无法扩展。

b = np.zeros((2, 3))

专业版:它使用最少的内存,而且性能更高。

缺点:可读性稍差。

我的偏好是在需要考虑内存的情况下传递元组文字,例如,很多人都会使用的长时间运行的脚本。另一方面,当我使用交互式解释器时,我更喜欢传递列表,因为它们更具可读性,方括号和圆括号之间的对比便于视觉解析。

你应该只关心函数的性能,代码被编译成字节码:

>>> min(timeit.repeat('foo()', 'def foo(): return (0, 1)'))
0.080030765042010898
>>> min(timeit.repeat('foo()', 'def foo(): return [0, 1]'))
0.17389221549683498

最后,请注意,性能考虑将与其他考虑相形见绌。您使用 Python 是为了加快开发速度,而不是为了提高算法实现的速度。如果你使用一个糟糕的算法,你的表现会更糟。它在许多方面也非常出色。我认为这很重要,因为它可以扩展,如果它可以改善大量使用的流程,避免因一千次削减而死亡。

【讨论】:

  • 这可能更多地归结为列表原语或元组原语是否已经是某些给定上下文中的主要使用模式。我想如果您正在设计 NumPy 本身,以在大量用例中工作,那么请使用元组。但是,如果您正在为某个公司的团队将使用的 API 构建一个小扩展,并且他们已经拥有一个相当大的代码库,倾向于在很多地方假设列表,那么使用列表可能会更好,这样人们就不会不必从它们的列表中构造元组来使用你的 API。我认为这一点使列表的轻微内存开销相形见绌。
  • @MarkRansom 谢谢,但如果这是一个考虑因素,它可能应该是最后的考虑因素。
  • @AaronHall 实际上在问题的上下文中我的评论不合适,所以我收回了。问题是如果你调用一个带有序列参数的函数,你应该使用列表还是元组?如果被调用函数要将参数放入字典或集合中,它会坚持获取一个元组,而您将别无选择。
  • @MarkRansom 正是如此。说得好。
【解决方案2】:

如果在设计时知道项目的数量(例如坐标、颜色系统),那么我会使用元组,否则使用列表。

如果我正在编写一个接口,我的代码将倾向于只检查参数是可迭代的还是序列(而不是检查特定类型,除非接口需要特定类型)。我使用集合模块进行检查——感觉比检查特定属性更干净。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-03
    • 2011-03-14
    • 2014-04-22
    • 1970-01-01
    相关资源
    最近更新 更多