21

我使用 Python 已经有好几次了,我发现了“pythonic”的编码方式。我在代码中使用了很多元组,其中大多数是极坐标或笛卡尔位置。

我发现自己在写这个:

window.set_pos([18,8])

而不是这个:

window.set_pos((18,8))

摆脱我发现难以阅读的双括号。

似乎 python 正在自动进行从列表到元组的类型转换,因为我的代码可以正常工作。

但这是一种编码的好方法吗?你有任何我可以用来编写可读代码的演示技巧吗?

预先感谢您提供的肯定有启发性的答案。

4

6 回答 6

25

我会谨慎地决定避开元组以支持无处不在的列表。你用过dis模块吗?当你创建一个列表和创建一个元组时,观察 Python 在字节码级别做什么:

>>> def f():
...     x = [1,2,3,4,5,6,7]
...     return x
... 
>>> def g():
...     x = (1,2,3,4,5,6,7)
...     return x
... 
>>> import dis
>>> dis.dis(f)
  2           0 LOAD_CONST               1 (1)
              3 LOAD_CONST               2 (2)
              6 LOAD_CONST               3 (3)
              9 LOAD_CONST               4 (4)
             12 LOAD_CONST               5 (5)
             15 LOAD_CONST               6 (6)
             18 LOAD_CONST               7 (7)
             21 BUILD_LIST               7
             24 STORE_FAST               0 (x)

  3          27 LOAD_FAST                0 (x)
             30 RETURN_VALUE     
>>>
>>>   
>>> dis.dis(g)
  2           0 LOAD_CONST               8 ((1, 2, 3, 4, 5, 6, 7))
              3 STORE_FAST               0 (x)

  3           6 LOAD_FAST                0 (x)
              9 RETURN_VALUE   

尽管它在 GUI 应用程序中可能永远不会成为问题(就像您的示例那样),但出于性能原因,您可能希望在代码中的任何地方都小心谨慎。

于 2012-06-29T12:46:49.580 回答
12

你说

似乎python正在自动进行从列表到元组的类型转换

这是值得怀疑的。由于列表和元组都是序列类型,它们都实现了许多相同的行为,并且您使用的任何 GUI 库都必须不需要任何仅列表行为。

在许多情况下这样做可能没问题,但请注意,列表确实比元组占用更多空间:

>>> sys.getsizeof((1, 2))
72
>>> sys.getsizeof([1, 2])
88

并且在某些方面可能比元组慢:

>>> lst, tup = [1, 2], (1, 2)
>>> def unpack(x):
...     a, b = x
...     
>>> %timeit unpack(tup)
10000000 loops, best of 3: 163 ns per loop
>>> %timeit unpack(lst)
10000000 loops, best of 3: 172 ns per loop

这些都是非常小的差异,直到您达到更大的规模(例如数十亿次调用)才有意义,因此权衡可能是值得的。

不过,我不经常看到人们这样做。这似乎是一个很好的可读性技巧,但在某些情况下可能会产生意想不到的后果。例如,如果您传递一个您打算稍后再次使用的列表,那么您必须小心不要在函数内部修改它。最后,正如JF Sebastian正确指出的那样,元组和列表的含义往往略有不同。以非常规的方式使用它们可能会否定您寻求的可读性提升。

于 2012-06-29T12:27:05.210 回答
8

我严重怀疑元组与列表在您的情况下会在性能上产生显着差异。除非您的分析器这么说,否则不要进行微优化。可读性是一个优先事项。

list并且tuple都是序列类型

语义元组可能更可取(请参阅元组有结构,列表有顺序)。位置是具有 x、y 属性的单个对象。

在这种情况下,视觉列表可能更容易阅读。

无论你选择什么,只要保持一致

检查是否window支持以下内容:

window.pos = 18, 8

实现它的一种可能方法是创建posa属性并绑定 set_pos()为 setter。

于 2012-06-29T13:28:20.480 回答
4

IMO 使用(18,8)over的唯一优点[18,8]是元组对象是不可变的,您可以确保它不会在传递的函数内部更改,而[18,8]可以轻松更改。

于 2012-06-29T12:24:40.420 回答
4

Python 不会进行任何从列表到元组的自动转换,除非 set_pos 方法明确地这样做。tuple 和 list 具有非常相似的协议,因此它们在该协议中往往可以互换。您仍然可能会破坏事情,特别是因为元组是可以散列的不可变的,而列表不是。

要回答你的问题,只需写

window.set_pos( (18,18) )

适当的空间用编码风格创造奇迹。

于 2012-06-29T12:26:03.230 回答
0

如果你想强调你的参数是一个元组这一事实,你可以明确地转换它:

window.set_pot(tuple([18, 18]))
于 2012-06-29T12:22:45.183 回答