首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >曾经,我被这些陷阱坑的找不着北...

曾经,我被这些陷阱坑的找不着北...

作者头像
编程文青李狗蛋
发布2019-06-18 18:17:58
2870
发布2019-06-18 18:17:58
举报

人人都想去天堂,那怎么行?总得有人做人,有人当动物吧,所以,撒旦必须挖许多各种各样的陷阱,就让迷糊的人糊里糊涂往里钻,钻进某个陷阱,就失去了生命的自由,就没有机会去天堂了。

00.写在之前

在我的系列文章 零基础学习 Python 中我介绍完了 Python 的基本对象类型,表面看上去这些东西都很简单,就是看一看背一背敲一敲洒洒水就可以搞定的东西,但是很多时候往往就是这些简单的东西会给你挖个大大的坑,做一点拙劣的掩饰,等着 45 度仰望星空的你蹦蹦跳跳的掉进去。

这一篇文章就让我们来列举一下“简单“的基本对象类型可能会让我们头疼的一些常见问题,顺便讨论一下对于这些问题我们该如何规避解决。可能有的我在以前的文章中已经提到过了,但鉴于它们真的很重要,值得我再一次提到。

01.赋值生成引用

对于这个非常核心的问题,我必须再提及它一次。你需要理解「共享引用」是怎么回事。为了更好的回忆,我们来看一个例子:

>>> lst1 = [1,2,3]
>>> lst2 = ['A','B',lst1]
>>> lst2
['A', 'B', [1, 2, 3]]
>>> lst1[0] = 0
>>> lst2
['A', 'B', [0, 2, 3]]

上面例子中赋值给 lst1 的列表对象不但被 lst1 引用,也被赋值为 lst2的内部列表引用,同时在原处修改了 lst1 的同时也修改了 lst2 的引用。这种影响在小的程序中不显山露水,通常正在大型程序中才显得重要,而这里面「共享引用」才是我们真正想要的。

如果你不想对象共享的话,可以对它们先进行拷贝。就上面例子中的列表,你可以对它们进行切片生成一个拷贝:

>>> lst1 = [1,2,3]
>>> lst2 = ['A','B',lst1[:]]
>>> lst1[0] = 0
>>> lst1
[0, 2, 3]
>>> lst2
['A', 'B', [1, 2, 3]]

上面的切片就是将列表中的每一项抽取出来,生成了一个新的无共享的对象。

02.不可变类型的修改

不可变对象不能在原处修改。如果需要改变的话,我们只能采用迂回战术,通过切片、合并等操作创建一个新的对象,最后再赋值给原引用。具体操作如下所示:

>>> t = (1,2,3)
>>> t[0] = 0
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> t = (0,)+t[1:]
>>> t
(0, 2, 3)

这样做看起来很不 Pythonist,做了很多多余的工作。但是我们换个角度来看,这样用元组、数字等不可变对象其实是有好处的,因为无法在原处修改,不会出现上一小节中列表 lst1 和 lst2 中出现的那种问题。

03.列表重复

「列表重复」表面上看起来就是自己多次加上自己。这是事实,但是当列表被嵌套的时候产生的效果就不见得是我们想的那样。我们来看下面这个例子:

>>> lst = [1,2,3]
>>> l1 = lst * 3
>>> l2 = [lst] * 3
>>> l1
[1, 2, 3, 1, 2, 3, 1, 2, 3]
>>> l2
[[1, 2, 3], [1, 2, 3], [1, 2, 3]]

上面 l1 赋值给重复四次的 lst,l2 赋值给包含重复四次 lst的。由于 lst 在 l2 的那行代码中是嵌套的,返回赋值为 lst 的原始列表,所以会出现在「赋值生成引用」这一节中出现的那种问题:

>>> lst[0] = 0
>>> l1
[1, 2, 3, 1, 2, 3, 1, 2, 3]
>>> l2
[[0, 2, 3], [0, 2, 3], [0, 2, 3]]

解决上面问题和之前我们说过的一样,比如用切片的方法形成一个新的无共享的对象,因为这个的确是以另一种生成共享可变对象的方法。

04.循环对象

「循环对象」就是一个复合对象包含指向自身的引用。无论何时何地 Python 对象中检测到了循环,都会打印成 [...] 的形式,而不是陷入无限循环的境地。我们还是先看一个例子:

>>> lst = ['Rocky']
>>> lst.append(lst)
>>> lst
['Rocky', [...]]

我们除了要知道上面的 [...] 代表对象中带有循环之外,还有一种容易造成误会的情况也该知道:「循环结构可能会导致程序代码陷入到无法预期的循环当中」。

至于这句话我们现在不去细究,你需要知道的是除非你真的需要,否则不要使用循环引用,我相信你肯定不想让自己陷入某些“玄学“的麻烦中。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-04-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Python空间 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档