Python 元组可读性:[0,0]vs(0,0)

Python 元组可读性:[0,0]vs(0,0),python,tuples,readability,Python,Tuples,Readability,我使用Python已经有一段时间了,我发现了“pythonic”的编码方式。 我在代码中使用了很多元组,大多数元组都是极坐标或笛卡尔坐标 我发现自己在写这篇文章: window.set_pos([18,8]) 与此相反: window.set_pos((18,8)) 为了去掉双括号,我发现很难读懂 由于我的代码工作正常,python似乎自动完成了从列表到元组的类型转换 但这是编码的好方法吗? 你有什么我可以用来写可读代码的演示技巧吗 提前感谢您的回答。如果您想强调参数是元组这一事实,您可以明

我使用Python已经有一段时间了,我发现了“pythonic”的编码方式。 我在代码中使用了很多元组,大多数元组都是极坐标或笛卡尔坐标

我发现自己在写这篇文章:

window.set_pos([18,8])
与此相反:

window.set_pos((18,8))
为了去掉双括号,我发现很难读懂

由于我的代码工作正常,python似乎自动完成了从列表到元组的类型转换

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


提前感谢您的回答。

如果您想强调参数是元组这一事实,您可以明确地将其转换为:

window.set_pot(tuple([18, 18]))

在我看来,使用
(18,8)
而不是
[18,8]
的唯一优点是元组对象是不可变的,您可以确保它在传递的函数中不会被更改,而
[18,8]
可以很容易地更改。

Python没有做任何从列表到元组的自动转换,除非set_pos方法显式执行此操作。元组和列表具有非常相似的协议,因此它们在该协议中可以互换。您可能仍然会破坏一些东西,特别是因为元组是可以散列的不可变的,而列表不是

要回答你的问题,只需写信

window.set_pos( (18,18) )
正确的空格可以创造编码风格的奇迹。

你说呢

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
这些都是非常小的差异,在你达到更大的规模之前都不重要——比如在数十亿次通话中——所以权衡是值得的


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

我会小心地决定避开元组,而选择到处都是列表。你用过这个模块吗?观察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应用程序中可能永远不会成为问题(正如您的示例所示),但出于性能方面的原因,您可能希望在代码中的任何地方都要小心使用它。

我严重怀疑元组与列表在性能方面是否有显著差异。不要做微优化,除非你的分析器这么说。可读性是首要任务

list
tuple
都是

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

在这种情况下,直观的列表可能更容易阅读

无论你选择什么,都要始终如一

检查
窗口是否支持以下功能:

window.pos = 18, 8

实现它的一种可能方法是将
pos
A和bind
set\u pos()
作为setter。我也喜欢您编写它的方式,在我看来,它的定义更明确。Python不是“从列表到元组进行类型转换”。这是可行的:大概是
窗口。set_pos
需要两个项的序列,但不一定是2-
元组(我这么说大概是因为我不知道
窗口。set_pos
来自何处或它的功能)。重写函数以获取两个参数,而不是一个2元组。PEP-8建议不要这样做:@jamylak:同意,我同意PEP的建议,但这是一个值得破例的特殊情况。@jamylak它不是由语言强制执行的,这意味着它只是Python作者碰巧喜欢的一种编码风格。这不是编码风格的全部,也不应该被视为这样。只要将它们视为良好的指导原则,并准备在它们损害可读性时打破它们——比如在本例中。谢谢您的精确回答!我知道这看起来有点奇怪,但我很高兴使用一个不合适的对象只是为了可读性。我的“set_pos”方法只是将参数解压成两个变量,但大多数时间都在循环中使用,我关心性能问题。14ns很重要吗?不,14ns在设置窗口位置时根本不重要。非常感谢,你说服了我!我非常关心性能,因为我的应用程序不是GUI,而是带有图形GUI的游戏。You's bytecode详细答案对于理解后台正在发生的事情非常有帮助(我不知道dis模块)。我只是对两个函数进行了计时:列表版本的时间大约是元组版本的两倍(1000万次调用的时间分别为2.1秒和0.9秒)。但是,对于两个元素集合,差异较小:1.6秒对0.9秒。啊,对了——我忘了元组文字是。如果您传递的是文本(而不是由变量构造的元组),这可能会产生很大的不同。+1表示元组与列表的语义,这几乎应该始终是使用的决定因素。