【问题标题】:Python: variable-length tuplesPython:可变长度元组
【发布时间】:2011-05-11 19:00:11
【问题描述】:

[Python 3.1]

我正在跟进元组应该是已知长度的设计概念(请参阅this comment),并且在大多数情况下应该用列表替换未知长度的元组。我的问题是在什么情况下我应该偏离这条规则?

例如,我知道从字符串和数字文字创建元组比列表更快(请参阅another comment)。因此,如果我的性能关键代码中有大量计算,例如sumproduct(tuple1, tuple2),我是否应该重新定义它们以处理列表,尽管性能受到影响? (sumproduct((x, y, z), (a, b, c)) 定义为x * a + y * b + z * c,其参数未指定但长度相等)。

那么使用def f(*x)时Python自动构建的元组呢?我认为这不是我每次使用时都应该强制列出的内容。

顺便说一句,(x, y, z) 的创建速度是否比 [x, y, z] 快(对于变量而不是文字)?

【问题讨论】:

    标签: python performance list python-3.x tuples


    【解决方案1】:

    在什么情况下我应该偏离 [元组应该是已知长度] 规则?

    无。

    这是意义的问题。如果一个对象基于固定数量的元素具有意义,那么它就是一个元组。 (x,y) 坐标、(c,m,y,k) 颜色、(lat, lon) 位置等等等等。

    元组具有固定数量的元素,具体取决于一般问题域和手头问题的具体情况。

    设计一个元素数量不定的元组是没有意义的。我们什么时候从 (x,y) 切换到 (x,y,z) 再切换到 (x,y,z,w) 坐标?不是简单地连接一个值,就好像它是一个列表一样?如果我们从 2-d 坐标移动到 3-d 坐标,通常会有一些非常花哨的数学来映射坐标系。不将元素附加到列表中。

    从 (r,g,b) 颜色转移到其他颜色是什么意思? rgb系统中的第四种颜色是什么?就此而言,cmyk ststem 中的第五种颜色是什么?

    元组不会改变大小。

    *args 是一个元组,因为它是不可变的。是的,它有无限数量的参数,但它是一个罕见的与已知、已定义大小的元组相反的例子。


    如何处理不确定长度的元组。这个反例是如此深刻,以至于我们有两个选择。

    1. 拒绝元组是固定长度并受问题约束的想法。由于这个反例,(x,y)坐标和(r,g,b)颜色的想法完全没有价值和错误。固定长度的元组?从不。

    2. 始终将所有*args 转换为列表,以始终对设计原则保持一定程度的不假思索。隐蔽到列表?总是。

    我喜欢全有或全无的选择,因为它们使软件工程变得如此简单和不加思考。

    也许,在这些极端情况下,这里有一小部分“这需要思考”。一小块碎片。

    是的,*args 是一个元组。是的,它的长度不定。是的,这是一个反例,其中“由问题域修复”被“简单地不可变”胜过。

    这导致我们在序列因不同原因不可变的情况下的第三种选择。你永远不会改变它,所以可以成为一个不定大小的元组。在更罕见的情况下,您将弹出 *args 的值,因为您将其视为堆栈或队列,那么您可能希望从中列出一个列表。但我们无法预先解决所有可能出现的问题。

    有时需要思考。


    当您进行设计时,您设计一个元组是有原因的。对您的数据施加有意义的结构。固定长度的元素数量?元组。可变数量的元素(即可变的)?列表。

    【讨论】:

    • 我能想到至少一个反例来反驳你的说法。 *args。那是一个元组,我不知道它会持续多久。我不认为你能想出一个比这更“pythonic”的反例。
    • @max:“性能影响是否太小而无需担心?”是的。这是关于意义。在这种情况下,性能并不重要。如果您需要更快的速度,请找到正确的算法。如果你可以证明你有正确的算法,并且你可以证明 Python实现太慢,那么就切换到C语言。
    • 如果你有一个固定大小的对象,但你需要修改它的元素怎么办?或者如果您有一个可变大小的对象,但您需要将其用作键?
    • 对我来说听起来过于简单了... ;-)
    • @max:通用的“sumproduct”并不合适。在大多数应用程序中,您实际上确实知道向量的大小,并且您实际上应该编写适合实际向量实际大小的 sumproduct。你真的不需要一个通用的、解决所有可能的问题、通用的sumproduct 函数。你真的需要一个专门的sumproduct4 来对 (x,y,z,r) 向量进行坐标转换。
    【解决方案2】:

    在这种情况下,您可能应该考虑使用 numpy 和 numpy 数组。

    与 numpy 数组之间的转换存在一些开销,但如果您进行大量计算,它会快得多

    【讨论】:

      【解决方案3】:

      在我看来,元组和列表之间唯一有趣的区别是列表是可变的,而元组不是。人们提到的其他区别对我来说似乎完全是人为的:元组就像结构,列表就像数组(这就是“元组应该是已知长度”的来源)。但是结构性如何与不变性保持一致?它不是。

      唯一重要的区别是语言所做的区别:可变性。如果需要修改对象,一定要使用列表。如果您需要散列对象(作为字典中的键或集合的元素),那么您需要它是不可变的,所以使用元组。就是这样。

      【讨论】:

        【解决方案4】:

        我总是使用最合适的数据结构来完成这项工作,并且并不真正担心元组是否会在这里或那里为我节省半毫秒。预先混淆你的代码通常不会最终得到回报。如果代码运行太慢,您可以稍后对其进行分析,并在真正重要的地方更改 0.01% 的代码。

        你所说的所有事情都与 python 版本的实现和它运行的硬件有关。您总是可以自己计时,看看它们在您的机器上会是什么。

        一个常见的例子是python中的“旧的不可变字符串连接起来很慢”。大约 10 年前是这样,然后他们在 2.4 或 2.5 中更改了实现。如果您自己进行测试,它们现在比列表运行得更快,但人们今天仍然相信这一点,并使用实际上运行速度较慢的愚蠢结构!

        【讨论】:

        • 也许你应该先做一些分析,然后再说其他人没有。尝试在 timeit 中从数字和字符串文字构造元组和列表,看看会发生什么。另外,关于混淆 python 的所有这些东西是什么?元组如何混淆任何东西?对我来说似乎非常清楚。
        • 如果您在代码中使用列表时使用元组会更清晰,那么它就是混淆代码。一个元组本身可能对任何人来说都是清楚的,但它是一个更大的代码块的一部分。阅读 Ned Batchelder 的答案。如果你需要一个使用它。如果您需要其他使用它。元组和列表都是在“恒定时间”O(1) 中构造的。那么为了一点速度而牺牲设计是否值得?
        【解决方案5】:

        元组是比列表简单得多的类型。在您可以忍受它们不可变的任何地方使用它们。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-11-20
          • 1970-01-01
          • 2014-07-27
          • 1970-01-01
          相关资源
          最近更新 更多