请教一种值对比时令人困惑的写法

118 views
Skip to first unread message

Alvin Qi

unread,
Jan 18, 2018, 1:38:03 AM1/18/18
to python-cn(华蟒用户组,CPyUG 邮件列表)
前些天发现项目代码中有一种诡异的写法,感觉很奇怪,于是和朋友讨论了一下,结果朋友告诉我“绝对”不建议那样写,但公司项目里全都是那种写法,我很困惑,所以想来这里请教一下各位前辈。

公司里的这种写法是:

if a in ('a', 'b', 'c',):
   
# do something


显然,这种写法的意思是,当变量a的值为'a'、'b'、'c'时,可以做一些事情。

那么同样,我完全可以用下面这种写法:

if a in ['a', 'b', 'c']:
   
# do something


这两种写法,在我看来是看不出任何区别的,但朋友讲,元组是一种不可变的数据结构,通常可以用作一种匿名的结构体,然后可以做类型判断啦等等。
这个我是理解的,但说到以上这种代码,又说元组一般不用于迭代的场景。

我是新人,接触Python不满3个月,完全不明白这两种写法有何本质区别、以及优劣。
所以想请教社区前辈,这两种写法到底有何区别,哪种是推荐的写法呢?

Leo Jay

unread,
Jan 18, 2018, 2:00:36 AM1/18/18
to python-cn:CPyUG
就你列出来的使用场景来说,是没有区别的。标准库里,使用 in tuple 的情况远比 in list 的多。
leo@leo-desktop:/usr/lib/python2.7$ fgrep -R ' in [' *.py | wc -l
22
leo@leo-desktop:/usr/lib/python2.7$ fgrep -R ' in (' *.py | wc -l
274

ZLJ

unread,
Jan 18, 2018, 2:01:33 AM1/18/18
to pyth...@googlegroups.com
要在这里说明用tuple相对于用list的好处,得先解决你当前代码中的另一个问题-magic literal value。无论是`('a', 'b', 'c')`还是`['a', 'b', 'c']`,都不能让人直接看出来开发者想表达的业务逻辑,如果将这个tuple或list赋值给一个有意义的变量名的话,tule和list孰优孰劣就比较明显了:

```
VALID_ITEMS = ['a', 'b', 'c']

if a in VALID_ITEMS:
     # do something
```

```
VALID_ITEMS = ('a', 'b', 'c')

if a in VALID_ITEMS:
     # do something
```

前面一种写法中,因为`VALID_ITEMS`是一个list,而list是mutable的,你很难避免哪个猪队友在某个隐蔽的角落悄悄往这个list中加一个或者减一个元素,并最终导致一些莫名奇妙的bug。
后一种写法中,`VALID_ITEMS`是一个tuple,而tuple是immutable的,语言本身保证了任何时候看到的VALID_ITEMS都是你第一次看到的VALID_ITEMS。




--
邮件来自: `CPyUG`华蟒用户组(中文Python技术邮件列表)
规则: http://code.google.com/p/cpyug/wiki/PythonCn
详情: http://code.google.com/p/cpyug/wiki/CpyUg
严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
---
您收到此邮件是因为您订阅了Google网上论坛上的“python-cn(华蟒用户组,CPyUG 邮件列表)”群组。
要退订此群组并停止接收此群组的电子邮件,请发送电子邮件到python-cn+unsubscribe@googlegroups.com
要发帖到此群组,请发送电子邮件至python-cn@googlegroups.com
要查看更多选项,请访问https://groups.google.com/d/optout

laike9m

unread,
Jan 18, 2018, 2:03:22 AM1/18/18
to python-cn(华蟒用户组,CPyUG 邮件列表)
这里难道不是应该用 set 么。而且实际上 Python 会把 set literal 优化成 frozenset,不会每次调用函数都创建

--

Alvin Qi

unread,
Jan 18, 2018, 2:21:59 AM1/18/18
to pyth...@googlegroups.com
set在这里的用法,我可以认为是一个特别的优化技巧。感谢指导~

您收到此邮件是因为您订阅了Google网上论坛上“python-cn(华蟒用户组,CPyUG 邮件列表)”群组中的主题。
要退订此主题,请访问https://groups.google.com/d/topic/python-cn/sbB6r3SkTGo/unsubscribe
要退订此群组及其所有主题,请发送电子邮件到python-cn+unsubscribe@googlegroups.com

要发帖到此群组,请发送电子邮件至python-cn@googlegroups.com
要查看更多选项,请访问https://groups.google.com/d/optout



--
Alvin Qi

Alvin Qi

unread,
Jan 18, 2018, 2:23:37 AM1/18/18
to pyth...@googlegroups.com
嗯嗯 
这种写法我明白,在这样的代码风格中,tuple确实比list放心不少。

您收到此邮件是因为您订阅了Google网上论坛上“python-cn(华蟒用户组,CPyUG 邮件列表)”群组中的主题。
要退订此主题,请访问https://groups.google.com/d/topic/python-cn/sbB6r3SkTGo/unsubscribe
要退订此群组及其所有主题,请发送电子邮件到python-cn+unsubscribe@googlegroups.com

要发帖到此群组,请发送电子邮件至python-cn@googlegroups.com
要查看更多选项,请访问https://groups.google.com/d/optout



--
Alvin Qi

Alvin Qi

unread,
Jan 18, 2018, 2:25:34 AM1/18/18
to pyth...@googlegroups.com
我也发现了,确实是这样。

虽然不是很懂底层区别,但从代码风格上向社区靠拢是没错的。

--
邮件来自: `CPyUG`华蟒用户组(中文Python技术邮件列表)
规则: http://code.google.com/p/cpyug/wiki/PythonCn
详情: http://code.google.com/p/cpyug/wiki/CpyUg
严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
---
您收到此邮件是因为您订阅了 Google 网上论坛上“python-cn(华蟒用户组,CPyUG 邮件列表)”群组中的主题。

要退订此主题,请访问https://groups.google.com/d/topic/python-cn/sbB6r3SkTGo/unsubscribe
要退订此群组及其所有主题,请发送电子邮件到python-cn+unsubscribe@googlegroups.com
要向此群组发帖,请发送电子邮件至 pyth...@googlegroups.com
要查看更多选项,请访问 https://groups.google.com/d/optout



--
Alvin Qi

Yuchen Ying (yegle)

unread,
Jan 18, 2018, 3:43:03 AM1/18/18
to pyth...@googlegroups.com

很久以前,tuple iterate的时候速度比其他类型快

 

http://www.diveintopython3.net/native-datatypes.html#tuples

https://stackoverflow.com/questions/3340539/why-is-tuple-faster-than-list

 

 

Sent from Mail for Windows 10

要退订此群组及其所有主题,请发送电子邮件到python-cn+...@googlegroups.com


要向此群组发帖,请发送电子邮件至 pyth...@googlegroups.com
要查看更多选项,请访问 https://groups.google.com/d/optout



 

--

Alvin Qi

--

邮件来自: `CPyUG`华蟒用户组(中文Python技术邮件列表)
规则: http://code.google.com/p/cpyug/wiki/PythonCn
详情: http://code.google.com/p/cpyug/wiki/CpyUg
严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
---

您收到此邮件是因为您订阅了Google网上论坛上的“python-cn(华蟒用户组,CPyUG 邮件列表)”群组。
要退订此群组并停止接收此群组的电子邮件,请发送电子邮件到python-cn+...@googlegroups.com
要发帖到此群组,请发送电子邮件至pyth...@googlegroups.com
要查看更多选项,请访问https://groups.google.com/d/optout

 

piglei

unread,
Jan 18, 2018, 4:51:16 AM1/18/18
to pyth...@googlegroups.com
我印象中这种情况一般都是推荐用 tuple 的,主要是 immutable 和速度的原因。至于以前为什么不用 set,主要是因为:

- Python 2.6 时代是没有 set literal 语法的,所以一般直接写 ("a", "b")。改成 set 的话需要多打好几个字母和括号,非常费事
- 一般情况下做这种比较时目标集都不大,所以 tuple 的性能通常足够好

不过现在确实得改改习惯了,直接写 {"a", "b"} 会更好一点。

 

我也发现了,确实是这样。

 

虽然不是很懂底层区别,但从代码风格上向社区靠拢是没错的。

 

要退订此群组及其所有主题,请发送电子邮件到python-cn+unsubscribe@googlegroups.com


要向此群组发帖,请发送电子邮件至 pyth...@googlegroups.com
要查看更多选项,请访问 https://groups.google.com/d/optout



 

--

Alvin Qi

--
邮件来自: `CPyUG`华蟒用户组(中文Python技术邮件列表)
规则: http://code.google.com/p/cpyug/wiki/PythonCn
详情: http://code.google.com/p/cpyug/wiki/CpyUg
严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
---
您收到此邮件是因为您订阅了Google网上论坛上的“python-cn(华蟒用户组,CPyUG 邮件列表)”群组。

要退订此群组并停止接收此群组的电子邮件,请发送电子邮件到python-cn+unsubscribe@googlegroups.com
要发帖到此群组,请发送电子邮件至python-cn@googlegroups.com
要查看更多选项,请访问https://groups.google.com/d/optout

 

--
邮件来自: `CPyUG`华蟒用户组(中文Python技术邮件列表)
规则: http://code.google.com/p/cpyug/wiki/PythonCn
详情: http://code.google.com/p/cpyug/wiki/CpyUg
严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
---
您收到此邮件是因为您订阅了Google网上论坛上的“python-cn(华蟒用户组,CPyUG 邮件列表)”群组。

shhgs

unread,
Jan 18, 2018, 9:36:50 AM1/18/18
to pyth...@googlegroups.com
很多情况下,这两种写法都是可以的。

tuple比list好的地方在于,tuple是immutable的,所以当你遍历整个序列的时候,序列不会发生变化。但是List则是mutable的,语法上完全可以在遍历的过程中增删元素。newbie经常会有这个错误。多线程环境下也会有这个问题。tuple则根本不给你犯错误的机会。

至于set,其实就安全性上讲还是不如tuple。而且set 跟 list 和 tuple 不能比, 那两位是从有Python那天起就有的第一等容器,而 set 的资历还是“比较”浅的。所以很多人会不自觉地用tuple。其实在标准类库里,这样的蛛丝马迹不少。比方像dict的keys方法,照道理应该返回一个set,为什么是list?其实就是因为有dict的时候,还没有set。



 

我也发现了,确实是这样。

 

虽然不是很懂底层区别,但从代码风格上向社区靠拢是没错的。

 

要退订此群组及其所有主题,请发送电子邮件到python-cn+unsub...@googlegroups.com



 

--

Alvin Qi

laike9m

unread,
Jan 18, 2018, 10:14:15 AM1/18/18
to pyth...@googlegroups.com
他又没有自己遍历,in 判断根本不用考虑你说的那些,而且 literal 又不可能改变

On 1/18/18, shhgs <shhgs....@gmail.com> wrote:
> 很多情况下,这两种写法都是可以的。
>
> tuple比list好的地方在于,tuple是immutable的,所以当你遍历整个序列的时候,序列不会发生变化。但是List则是mutable的,语法上完全可以在遍历的过程中增删元素。newbie经常会有这个错误。多线程环境下也会有这个问题。tuple则根本不给你犯错误的机会。
>
> 至于set,其实就安全性上讲还是不如tuple。而且set 跟 list 和 tuple 不能比, 那两位是从有Python那天起就有的第一等容器,而
> set
> 的资历还是“比较”浅的。所以很多人会不自觉地用tuple。其实在标准类库里,这样的蛛丝马迹不少。比方像dict的keys方法,照道理应该返回一个set,为什么是list?其实就是因为有dict的时候,还没有set。
>
>
>
> 2018-01-18 4:51 GMT-05:00 piglei <pigle...@gmail.com>:
>
>> 我印象中这种情况一般都是推荐用 tuple 的,主要是 immutable 和速度的原因。至于以前为什么不用 set,主要是因为:
>>
>> - Python 2.6 时代是没有 set literal 语法的,所以一般直接写 ("a", "b")。改成 set
>> 的话需要多打好几个字母和括号,非常费事
>> - 一般情况下做这种比较时目标集都不大,所以 tuple 的性能通常足够好
>>
>> 不过现在确实得改改习惯了,直接写 {"a", "b"} 会更好一点。
>>
>> 2018-01-18 16:42 GMT+08:00 Yuchen Ying (yegle) <cny...@gmail.com>:
>>
>>> 很久以前,tuple iterate的时候速度比其他类型快
>>>
>>>
>>>
>>> http://www.diveintopython3.net/native-datatypes.html#tuples
>>>
>>> https://stackoverflow.com/questions/3340539/why-is-tuple-faster-than-list
>>>
>>>
>>>
>>>
>>>
>>> Sent from Mail <https://go.microsoft.com/fwlink/?LinkId=550986> for
>>> Windows 10
>>>
>>>
>>>
>>> *From: *Alvin Qi <peng...@gmail.com>
>>> *Sent: *Wednesday, January 17, 2018 11:25 PM
>>> *To: *pyth...@googlegroups.com
>>> *Subject: *Re: [CPyUG] 请教一种值对比时令人困惑的写法
>>> 要退订此群组及其所有主题,请发送电子邮件到python-cn+...@googlegroups.com
>>> 要向此群组发帖,请发送电子邮件至 pyth...@googlegroups.com
>>> 要查看更多选项,请访问 https://groups.google.com/d/optout
>>>
>>>
>>>
>>>
>>>
>>> --
>>>
>>> Alvin Qi
>>>
>>> --
>>> 邮件来自: `CPyUG`华蟒用户组(中文Python技术邮件列表)
>>> 规则: http://code.google.com/p/cpyug/wiki/PythonCn
>>> 详情: http://code.google.com/p/cpyug/wiki/CpyUg
>>> 严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
>>> ---
>>> 您收到此邮件是因为您订阅了Google网上论坛上的“python-cn(华蟒用户组,CPyUG 邮件列表)”群组。
>>> 要退订此群组并停止接收此群组的电子邮件,请发送电子邮件到python-cn+...@googlegroups.com
>>> 要发帖到此群组,请发送电子邮件至pyth...@googlegroups.com
>>> 要查看更多选项,请访问https://groups.google.com/d/optout
>>>
>>>
>>>
>>> --
>>> 邮件来自: `CPyUG`华蟒用户组(中文Python技术邮件列表)
>>> 规则: http://code.google.com/p/cpyug/wiki/PythonCn
>>> 详情: http://code.google.com/p/cpyug/wiki/CpyUg
>>> 严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
>>> ---
>>> 您收到此邮件是因为您订阅了Google网上论坛上的“python-cn(华蟒用户组,CPyUG 邮件列表)”群组。
>>> 要退订此群组并停止接收此群组的电子邮件,请发送电子邮件到python-cn+...@googlegroups.com
>>> 要发帖到此群组,请发送电子邮件至pyth...@googlegroups.com
>>> 要查看更多选项,请访问https://groups.google.com/d/optout
>>>
>>
>> --
>> 邮件来自: `CPyUG`华蟒用户组(中文Python技术邮件列表)
>> 规则: http://code.google.com/p/cpyug/wiki/PythonCn
>> 详情: http://code.google.com/p/cpyug/wiki/CpyUg
>> 严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
>> ---
>> 您收到此邮件是因为您订阅了Google网上论坛上的“python-cn(华蟒用户组,CPyUG 邮件列表)”群组。
>> 要退订此群组并停止接收此群组的电子邮件,请发送电子邮件到python-cn+...@googlegroups.com
>> 要发帖到此群组,请发送电子邮件至pyth...@googlegroups.com
>> 要查看更多选项,请访问https://groups.google.com/d/optout
>>
>
> --
> 邮件来自: `CPyUG`华蟒用户组(中文Python技术邮件列表)
> 规则: http://code.google.com/p/cpyug/wiki/PythonCn
> 详情: http://code.google.com/p/cpyug/wiki/CpyUg
> 严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
> ---
> 您收到此邮件是因为您订阅了 Google 网上论坛的“python-cn(华蟒用户组,CPyUG 邮件列表)”群组。
> 要退订此群组并停止接收此群组的电子邮件,请发送电子邮件到python-cn+...@googlegroups.com
> 要向此群组发帖,请发送电子邮件至 pyth...@googlegroups.com
> 要查看更多选项,请访问 https://groups.google.com/d/optout
>


--

--
laike9m.com

Mengyang Li

unread,
Jan 18, 2018, 5:44:30 PM1/18/18
to pyth...@googlegroups.com
那你的朋友有没有说为什么绝对不要那样写?会baodiao么?

2018-01-17 22:38 GMT-08:00 Alvin Qi <peng...@gmail.com>:

--
邮件来自: `CPyUG`华蟒用户组(中文Python技术邮件列表)
规则: http://code.google.com/p/cpyug/wiki/PythonCn
详情: http://code.google.com/p/cpyug/wiki/CpyUg
严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
---
您收到此邮件是因为您订阅了Google网上论坛上的“python-cn(华蟒用户组,CPyUG 邮件列表)”群组。
要退订此群组并停止接收此群组的电子邮件,请发送电子邮件到python-cn+unsubscribe@googlegroups.com
要发帖到此群组,请发送电子邮件至python-cn@googlegroups.com
要查看更多选项,请访问https://groups.google.com/d/optout



--
Best regards,
ᶘ ᵒᴥᵒᶅ
Mengyang Li

赖信桃

unread,
Jan 18, 2018, 9:03:34 PM1/18/18
to python-cn(华蟒用户组,CPyUG 邮件列表)
这么说不对吧,从你贴的Stack Overflow来看,tuple比list迭代的速度完全可以忽视,但是tuple的创建比list创建快了一个数量级:



$ python2.6 -mtimeit '(1, 2, 3, 4)'   
10000000 loops, best of 3: 0.0266 usec per loop
$ python2.6 -mtimeit '[1, 2, 3, 4]'
10000000 loops, best of 3: 0.163 usec per loop

在 2018年1月18日星期四 UTC+8下午4:43:03,@yegle写道:

要退订此群组及其所有主题,请发送电子邮件到python-cn+unsubscribe@googlegroups.com


要向此群组发帖,请发送电子邮件至 pyth...@googlegroups.com
要查看更多选项,请访问 https://groups.google.com/d/optout



 

--

Alvin Qi

--
邮件来自: `CPyUG`华蟒用户组(中文Python技术邮件列表)
规则: http://code.google.com/p/cpyug/wiki/PythonCn
详情: http://code.google.com/p/cpyug/wiki/CpyUg
严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
---
您收到此邮件是因为您订阅了Google网上论坛上的“python-cn(华蟒用户组,CPyUG 邮件列表)”群组。

Shell Xu

unread,
Jan 18, 2018, 9:38:16 PM1/18/18
to CUPG
这个问题我说一下自己看法吧。

首先,不要看整个thread里面说速度的那些post。对于一个入门级的Python程序员来说(甚至对于大多数Python程序员),追求两者的速度差异并没有价值,还不如改行学Java效果好。

其次,使用list和tuple的逻辑效果,在这个场景下是一样的。因为你显然也不会拿着co_consts去调来改去。如果要讲到细微差别的话,必须先构造一个合适的场景。然而在这些场景下,一般你看一下也知道为什么用其中一个而不用另一个了。

第三,无数post应该说过了。这里的正解当然是set。如果你朋友建议你不要这么写,用set,这当然是对的。

最后。不知道是不是我多心。我拿这两个代码(list和tuple出来的版本)dis出来的结果是一样的,在编译结果级看不出差异来。Python是不是自动优化掉了?

2018-01-18 14:38 GMT+08:00 Alvin Qi <peng...@gmail.com>:

--
邮件来自: `CPyUG`华蟒用户组(中文Python技术邮件列表)
规则: http://code.google.com/p/cpyug/wiki/PythonCn
详情: http://code.google.com/p/cpyug/wiki/CpyUg
严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
---
您收到此邮件是因为您订阅了Google网上论坛上的“python-cn(华蟒用户组,CPyUG 邮件列表)”群组。
要退订此群组并停止接收此群组的电子邮件,请发送电子邮件到python-cn+unsubscribe@googlegroups.com
要发帖到此群组,请发送电子邮件至python-cn@googlegroups.com
要查看更多选项,请访问https://groups.google.com/d/optout



--
彼節者有間,而刀刃者無厚;以無厚入有間,恢恢乎其於游刃必有餘地矣。
blog: http://shell909090.org/

laike9m

unread,
Jan 18, 2018, 9:44:54 PM1/18/18
to python-cn(华蟒用户组,CPyUG 邮件列表)

是自动优化了,之前贴的那篇文章有提到

Furthermore, Python does the same thing to lists. If a literal list object is put in a membership test, Python will replace it with an actual tuple constant in the code

Alvin Qi

unread,
Jan 18, 2018, 11:20:41 PM1/18/18
to pyth...@googlegroups.com
感谢各位大佬。

最开始有提到,朋友认为“元组是一种不可变的数据结构,通常可以用作一种匿名的结构体,然后可以做类型判断等等”,同时朋友也认为tuple既然是一种匿名结构体,那怎么可以拿来做遍历呢?

当然,显然,我认为这种说法是站不住脚的,因为Python本身就提供了这种机制,又因为这种机制带来了更多的便利,比如安全性、性能优势等,因此大家爱用tuple做遍历也是理所当然。

至于是否使用set,我自己也用过,但确实很少见到有人在这样场景中使用set。

但是,但是呢。。。既然Python本身提供了这么多机制来做一件事情,自然少不了百家争鸣,作为新手,有时候实在是比较困惑了... 不过还是要感谢各位前辈~

您收到此邮件是因为您订阅了Google网上论坛上“python-cn(华蟒用户组,CPyUG 邮件列表)”群组中的主题。
要退订此主题,请访问https://groups.google.com/d/topic/python-cn/sbB6r3SkTGo/unsubscribe
要退订此群组及其所有主题,请发送电子邮件到python-cn+unsubscribe@googlegroups.com

要发帖到此群组,请发送电子邮件至python-cn@googlegroups.com
要查看更多选项,请访问https://groups.google.com/d/optout



--
Alvin Qi

yegle

unread,
Jan 18, 2018, 11:24:43 PM1/18/18
to pyth...@googlegroups.com

我觉得tuple当成可遍历的数据结构是误用


要退订此群组并停止接收此群组的电子邮件,请发送电子邮件到python-cn+...@googlegroups.com
要发帖到此群组,请发送电子邮件至pyth...@googlegroups.com
要查看更多选项,请访问https://groups.google.com/d/optout



--
彼節者有間,而刀刃者無厚;以無厚入有間,恢恢乎其於游刃必有餘地矣。
blog: http://shell909090.org/

--
邮件来自: `CPyUG`华蟒用户组(中文Python技术邮件列表)
规则: http://code.google.com/p/cpyug/wiki/PythonCn
详情: http://code.google.com/p/cpyug/wiki/CpyUg
严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
---
您收到此邮件是因为您订阅了Google网上论坛上的“python-cn(华蟒用户组,CPyUG 邮件列表)”群组。
要退订此群组并停止接收此群组的电子邮件,请发送电子邮件到python-cn+...@googlegroups.com
要发帖到此群组,请发送电子邮件至pyth...@googlegroups.com
要查看更多选项,请访问https://groups.google.com/d/optout

--
邮件来自: `CPyUG`华蟒用户组(中文Python技术邮件列表)
规则: http://code.google.com/p/cpyug/wiki/PythonCn
详情: http://code.google.com/p/cpyug/wiki/CpyUg
严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
---
您收到此邮件是因为您订阅了Google网上论坛上“python-cn(华蟒用户组,CPyUG 邮件列表)”群组中的主题。
要退订此主题,请访问https://groups.google.com/d/topic/python-cn/sbB6r3SkTGo/unsubscribe
要退订此群组及其所有主题,请发送电子邮件到python-cn+...@googlegroups.com

要发帖到此群组,请发送电子邮件至pyth...@googlegroups.com
要查看更多选项,请访问https://groups.google.com/d/optout



--
Alvin Qi

--
邮件来自: `CPyUG`华蟒用户组(中文Python技术邮件列表)
规则: http://code.google.com/p/cpyug/wiki/PythonCn
详情: http://code.google.com/p/cpyug/wiki/CpyUg
严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
---
您收到此邮件是因为您订阅了Google网上论坛上的“python-cn(华蟒用户组,CPyUG 邮件列表)”群组。

依云

unread,
Jan 19, 2018, 12:37:07 AM1/19/18
to pyth...@googlegroups.com
On Fri, Jan 19, 2018 at 12:20:30PM +0800, Alvin Qi wrote:
> 感谢各位大佬。
>
> 最开始有提到,朋友认为“元组是一种不可变的数据结构,通常可以用作一种匿名的结构体,然后可以做类型判断等等
> ”,同时朋友也认为tuple既然是一种匿名结构体,那怎么可以拿来做遍历呢?
>
> 当然,显然,我认为这种说法是站不住脚的,因为Python本身就提供了这种机制,又因为这种机制带来了更多的便利,比如安全性、性能优势等,因此大家爱用tuple做遍历也是理所当然。
>
> 至于是否使用set,我自己也用过,但确实很少见到有人在这样场景中使用set。

你也很少见到有人用 Python 3 吧。

我觉得在 in 测试的时候用 tuple 最大的问题在于,直接写的时候通常是少数几
个值,写在一行里的,比如 if x in ("one", "two")。然后呢,因为某种原因,
当 x == "two" 的时候你不需要它了,于是删掉一个元素,不注意就变成 if x in
("one")……你又不可能总保留逗号,不然会成 ("one",, "three") 这样子。

与其每次改 tuple 时顾及一下里边元素的个数,不如使用 list,保持一致性。

--
Best regards,
lilydjwg

Linux Vim Python 我的博客:
https://blog.lilydjwg.me/
--
A: Because it obfuscates the reading.
Q: Why is top posting so bad?

赖信桃

unread,
Jan 19, 2018, 12:46:15 AM1/19/18
to python-cn(华蟒用户组,CPyUG 邮件列表)
这并不是误用,而是Python的有意而为之。元组一开始是做记录字段值的,但是Python讲求实用主义,于是也实现了迭代的协议。

Fluent Python这本书有一段杂谈谈到了这个问题,非常符合这个帖子的主题,引用一下全文:

The nature of tuples In 2012 I presented a poster about the ABC language at PyCon US. Before creating Python, Guido had worked on the ABC interpreter, so he came to see my poster. Among other things, we talked about the ABC compounds which are clearly the predecessors of Python tuples. Compounds also support parallel assignment and are used as com‐ posite keys in dictionaries (or tables, in ABC parlance). However, compounds are not sequences. They are not iterable and you cannot retrieve a field by index, much less slice them. You either handle the compound as whole or extract the individual fields using parallel assignment, that’s all. I told Guido that these limitations make the main purpose of compounds very clear: they are just records without field names. His response: “Making tuples behave as se‐ quences was a hack.” This illustrates the pragmatic approach that makes Python so much better and more successful than ABC. From a language implementer perspective, making tuples behave as sequences costs little. As a result, tuples may not be as “conceptually pure” as com‐ pounds, but we have many more ways of using them. They can even be used as immut‐ able lists, of all things! It is really useful to have immutable lists in the language, even if their type is not called frozenlist but is really tuple behaving as sequence.

中文:

元组的本质 
 2012年,我在PyCon US上贴了一张关于ABC语言的墙报。Guido在开创Python语 言之前曾做过 ABC 解释器方面的工作,因此他也去看了我的墙报。我们聊了不少,而 且都提到了 ABC 里的 compounds 类型。compounds 算得上是 Python 元组的鼻祖,它既 支持平行赋值,又可以用在字典(dict)里作为合成键(ABC 里对应字典的类型是表 格,即 table)。但 compounds 不属于序列,它不是迭代类型,也不能通过下标来提取 某个值,更不用说切片了。要么把 compounds 对象当作整体来用,要么用平行赋值把 里面所有的字段都提取出来,仅此而已。

在 2018年1月19日星期五 UTC+8下午12:24:43,@yegle写道:

我觉得tuple当成可遍历的数据结构是误用


要退订此群组并停止接收此群组的电子邮件,请发送电子邮件到python-cn+unsubscribe@googlegroups.com
要发帖到此群组,请发送电子邮件至python-cn@googlegroups.com
要查看更多选项,请访问https://groups.google.com/d/optout



--
彼節者有間,而刀刃者無厚;以無厚入有間,恢恢乎其於游刃必有餘地矣。
blog: http://shell909090.org/

--
邮件来自: `CPyUG`华蟒用户组(中文Python技术邮件列表)
规则: http://code.google.com/p/cpyug/wiki/PythonCn
详情: http://code.google.com/p/cpyug/wiki/CpyUg
严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
---
您收到此邮件是因为您订阅了Google网上论坛上的“python-cn(华蟒用户组,CPyUG 邮件列表)”群组。
要退订此群组并停止接收此群组的电子邮件,请发送电子邮件到python-cn+unsubscribe@googlegroups.com
要发帖到此群组,请发送电子邮件至python-cn@googlegroups.com
要查看更多选项,请访问https://groups.google.com/d/optout

--
邮件来自: `CPyUG`华蟒用户组(中文Python技术邮件列表)
规则: http://code.google.com/p/cpyug/wiki/PythonCn
详情: http://code.google.com/p/cpyug/wiki/CpyUg
严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
---
您收到此邮件是因为您订阅了Google网上论坛上“python-cn(华蟒用户组,CPyUG 邮件列表)”群组中的主题。
要退订此主题,请访问https://groups.google.com/d/topic/python-cn/sbB6r3SkTGo/unsubscribe
要退订此群组及其所有主题,请发送电子邮件到python-cn+unsubscribe@googlegroups.com

要发帖到此群组,请发送电子邮件至python-cn@googlegroups.com
要查看更多选项,请访问https://groups.google.com/d/optout



--
Alvin Qi

--
邮件来自: `CPyUG`华蟒用户组(中文Python技术邮件列表)
规则: http://code.google.com/p/cpyug/wiki/PythonCn
详情: http://code.google.com/p/cpyug/wiki/CpyUg
严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
---
您收到此邮件是因为您订阅了Google网上论坛上的“python-cn(华蟒用户组,CPyUG 邮件列表)”群组。

laixintao

unread,
Jan 19, 2018, 12:50:43 AM1/19/18
to python-cn(华蟒用户组,CPyUG 邮件列表)
不好意思,中文没有贴完全,重新贴一下中文版:

元组的本质

2012年,我在PyCon US上贴了一张关于ABC语言的墙报。Guido在开创Python语 言之前曾做过 ABC 解释器方面的工作,因此他也去看了我的墙报。我们聊了不少,而 且都提到了 ABC 里的 compounds 类型。compounds 算得上是 Python 元组的鼻祖,它既 支持平行赋值,又可以用在字典(dict)里作为合成键(ABC 里对应字典的类型是表 格,即 table)。但 compounds 不属于序列,它不是迭代类型,也不能通过下标来提取 某个值,更不用说切片了。要么把 compounds 对象当作整体来用,要么用平行赋值把 里面所有的字段都提取出来,仅此而已。

我跟 Guido 说,上面这些限制让 compounds 的作用变得很明确,它只能用作没有字段名 的记录。Guido 回应说,Python 里的元组能当作序列来使用,其实是一个取巧的实现。

这其实体现了 Python 的实用主义,而实用主义是 Python 较之 ABC 更好用也更成功的 原因。从一个语言开发人员的角度来看,让元组具有序列的特性可能需要下点功夫, 结果则是设计出了一个概念上并不如 compounds 纯粹,却更灵活的元组——它甚至能 当成不可变的列表来使用。

说真的,不可变列表这种数据类型在编程语言里真的非常好用(其实 frozenlist 这个 名字更酷),而 Python 里这种类型其实就是一个行为很像序列的元组。

——节选自《Fluent Python》

在 2018年1月19日星期五 UTC+8下午1:46:15,laixintao写道:

Alvin Qi

unread,
Jan 19, 2018, 12:51:31 AM1/19/18
to pyth...@googlegroups.com
这。。。

插句题外话:现在不都是在用Python 3 么?Python 2不是说马上要停止支持了么?除了维护老项目,怎么还会有人用Python 2呢?

你举的这个例子,恰恰是我最开始产生困惑的地方,也就是关于tuple结构里逗号、无效括号的一些注意事项。

不过,("one",,"two")这个并不是合法的语法啊,这种情况写成("one", "three")是不是就可以了呢?

--
邮件来自: `CPyUG`华蟒用户组(中文Python技术邮件列表)
规则: http://code.google.com/p/cpyug/wiki/PythonCn
详情: http://code.google.com/p/cpyug/wiki/CpyUg
严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
---
您收到此邮件是因为您订阅了 Google 网上论坛上“python-cn(华蟒用户组,CPyUG 邮件列表)”群组中的主题。

要退订此主题,请访问https://groups.google.com/d/topic/python-cn/sbB6r3SkTGo/unsubscribe
要退订此群组及其所有主题,请发送电子邮件到python-cn+unsubscribe@googlegroups.com
要向此群组发帖,请发送电子邮件至 pyth...@googlegroups.com
要查看更多选项,请访问 https://groups.google.com/d/optout



--
Alvin Qi

Alvin Qi

unread,
Jan 19, 2018, 1:03:15 AM1/19/18
to pyth...@googlegroups.com
没想到新手的困惑背后还有这样的故事。

我觉得tuple当成可遍历的数据结构是误用


要退订此群组及其所有主题,请发送电子邮件到python-cn+unsub...@googlegroups.com



--
Alvin Qi

依云

unread,
Jan 19, 2018, 2:03:52 AM1/19/18
to pyth...@googlegroups.com
On Fri, Jan 19, 2018 at 01:51:11PM +0800, Alvin Qi wrote:
> 这。。。
>
> 插句题外话:现在不都是在用Python 3 么?Python 2不是说马上要停止支持了么?除了维护老项目,怎么还会有人用Python 2呢?
>
> 你举的这个例子,恰恰是我最开始产生困惑的地方,也就是关于tuple结构里逗号、无效括号的一些注意事项。
>
> 不过,("one",,"two")这个并不是合法的语法啊,这种情况写成("one", "three")是不是就可以了呢?

我的意思是,一开始并没有 set literal,所以大家都用 tuple / list。后来有
了,很多人也没切换过来,就像 Python 2 的长命一样。另外对于少数值,set 的
操作并不一定比 tuple / list 快的(CPython 3.6 上是快一些,但是 3.6 改了
set 的实现吧)。

对啊,从一个元组里删掉一个元素,得看它的数目来决定要不要删逗号。而对于
list / set,删多少个值你就删多少个逗号(只要有),加的时候也一样。不会在
匆忙之中多删了最后一个逗号。

依云

unread,
Jan 19, 2018, 2:08:05 AM1/19/18
to pyth...@googlegroups.com
On Thu, Jan 18, 2018 at 09:46:15PM -0800, 赖信桃 wrote:
> 这并不是误用,而是Python的有意而为之。元组一开始是做记录字段值的,但是Python讲求实用主义,于是也实现了迭代的协议。
>
> Fluent Python这本书有一段杂谈谈到了这个问题,非常符合这个帖子的主题,引用一下全文:

我发现 Python 的元组和 Rust、Haskell、Erlang 等最大的区别,不在于元组本
身,而在于 Python 的列表里的类型是可以不同的。这样一来,tuple 和 list 的
差异一下子小了很多,再加上各种 namedtuple 的出现,tuple 的工作越来越接近
于 frozen list 了。

yegle

unread,
Jan 19, 2018, 2:51:30 AM1/19/18
to pyth...@googlegroups.com

list里保存不同类型对象不是给自己埋坑吗?


--
邮件来自: `CPyUG`华蟒用户组(中文Python技术邮件列表)
规则: http://code.google.com/p/cpyug/wiki/PythonCn
详情: http://code.google.com/p/cpyug/wiki/CpyUg
严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
---
您收到此邮件是因为您订阅了 Google 网上论坛的“python-cn(华蟒用户组,CPyUG 邮件列表)”群组。
要退订此群组并停止接收此群组的电子邮件,请发送电子邮件到python-cn+...@googlegroups.com

赖信桃

unread,
Jan 19, 2018, 3:15:57 AM1/19/18
to pyth...@googlegroups.com
不是,比如list的对象是用来遍历的,那么只要list中保存的对象实现了迭代,那么无论对象的类型是list,tuple,dict或者自定义类型都是无所谓的。

这是动态语言一个方便的地方。
> 您收到此邮件是因为您订阅了Google网上论坛上“python-cn(华蟒用户组,CPyUG 邮件列表)”群组中的主题。
> 要退订此主题,请访问https://groups.google.com/d/topic/python-cn/sbB6r3SkTGo/unsubscribe
> 要退订此群组及其所有主题,请发送电子邮件到python-cn+...@googlegroups.com

依云

unread,
Jan 19, 2018, 3:29:34 AM1/19/18
to pyth...@googlegroups.com
On Fri, Jan 19, 2018 at 07:51:10AM +0000, yegle wrote:
> list里保存不同类型对象不是给自己埋坑吗?

往任何可遍历对象里塞不兼容的东西都是埋坑啊。

本来呢,tuple 和 list 的区别在于,一个用来保存不同类型的,另一个用来保存
相同类型的对象。结果在 Python 这里,这个区别没了,反而多出 tuple 元素不
可重新赋值这么一个奇怪的特性,导致 Python 的 tuple 跟别的语言里的都不太
一样了。

至于保存不同类型的数据,还是用 namedtuple / class 之类的了。

yegle

unread,
Jan 19, 2018, 11:33:55 AM1/19/18
to pyth...@googlegroups.com


On Fri, Jan 19, 2018, 00:15 赖信桃 <laixi...@gmail.com> wrote:
不是,比如list的对象是用来遍历的,那么只要list中保存的对象实现了迭代,那么无论对象的类型是list,tuple,dict或者自定义类型都是无所谓的。

这是动态语言一个方便的地方。

在我看来这属于list里存放了类型相同的对象,具体说应该算 List[Iterable]。我说的不同类型主要是List里放了int和str。

在很多不应该实现Iterable接口的对象上实现了Iterable接口,这是Python的设计错误。比如说,字符串就不应该有Iterable接口,这能避免不知道多少坑。就因为str是Iterable,一个接受Iterable[Text]参数的函数就没办法正确type check了(str也满足这个参数类型)。

kingname

unread,
Jan 19, 2018, 9:21:30 PM1/19/18
to python-cn(华蟒用户组,CPyUG 邮件列表)
从你的回帖来看,你是Java这种静态语言用多了,才会觉得list里面对象不同类型是埋坑。

在 2018年1月19日星期五 UTC+8下午4:29:34,依云写道:

yegle

unread,
Jan 19, 2018, 9:33:15 PM1/19/18
to pyth...@googlegroups.com


2018-01-19 18:21 GMT-08:00 kingname <ylca...@gmail.com>:
从你的回帖来看,你是Java这种静态语言用多了,才会觉得list里面对象不同类型是埋坑。

你给我解释一下Python里一个list同时保存了int和str的目的是啥?

当然你说int和str都实现了__str__所以我要对list每个对象做一次str()操作那无话可说
 

--
邮件来自: `CPyUG`华蟒用户组(中文Python技术邮件列表)
规则: http://code.google.com/p/cpyug/wiki/PythonCn
详情: http://code.google.com/p/cpyug/wiki/CpyUg
严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
---
您收到此邮件是因为您订阅了Google网上论坛上的“python-cn(华蟒用户组,CPyUG 邮件列表)”群组。
要退订此群组并停止接收此群组的电子邮件,请发送电子邮件到python-cn+unsubscribe@googlegroups.com

要发帖到此群组,请发送电子邮件至python-cn@googlegroups.com
要查看更多选项,请访问https://groups.google.com/d/optout



--

screamff

unread,
Jan 22, 2018, 2:58:27 AM1/22/18
to python-cn(华蟒用户组,CPyUG 邮件列表)
A tuple is an object that you use very often without even noticing it. When you look at it initially, it seems like a useless data structure. It's like a list that you can't modify, so why not just use a list? There are a few cases where a tuple offers some really useful functionalities that a list does not. Firstly, they are hashaable. This means that you can use a tuple as a key in a dict, which is something a list can't do.
除了别的还有一个可哈希的特点
set – like a dict without values
dict优点就比较多了 
摘自master python一书
在 2018年1月18日星期四 UTC+8下午2:38:03,Alvin Qi写道:
Reply all
Reply to author
Forward
0 new messages