前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python 列表小技巧

Python 列表小技巧

作者头像
岂不美哉Frost
发布2019-11-30 14:31:27
3280
发布2019-11-30 14:31:27
举报
文章被收录于专栏:Frost's BlogFrost's Blog

Python中的列表和字典一样,都是可变数据类型,与字符串和整型相比,它具有一些独特的特性。在平常使用中, 也会经常遇到一些坑,本文试着举一些例子并说明。

列表的拷贝

直接赋值

Python

代码语言:javascript
复制
>>> a = [1,2,3]
>>> b = a
>>> a is b
True
>>> a[0]=5
>>> a
[5, 2, 3]
>>> b
[5, 2, 3]

在此例中,直接通过赋值将a赋给了b,此时,仅仅是为该列表增加了一个引用bab指向内存中同一个区域,通过a改变列表的值也同时影响b。请注意,这里有一个坑,很多人在初始化语句中写a = b = [],这是错误的,会导致任意一个变动都会在ab中同步,而且会很难debug。正确写法应该是分别初始化。

使用list工厂函数

为了创建一个a的拷贝,可以使用list工厂函数,这也是Python Cookbook中的推荐做法。

Python

代码语言:javascript
复制
>>> a = [1,2,3]
>>> b = list(a)
>>> a is b
False
>>> a[0]=5
>>> a
[5, 2, 3]
>>> b
[1, 2, 3]

完美,ab是两个不同的列表了!除了使用工厂函数,切片也可以达到同样的效果:

Python

代码语言:javascript
复制
>>> b = a[:]
>>> b is a
False

使用copy模块

一切看起来都很美好,真的是这样吗?

Python

代码语言:javascript
复制
>>> a = [1,[1,2],3]
>>> b = list(a)
>>> a[0] = 5
>>> a[1][1] = 5
>>> a
[5, [1, 5], 3]
>>> b
[1, [1, 5], 3]

What?!b的第二个元素子列表中的值还是被改变了!原来,list[:]都是在内存中创建了一个新的对象并赋给了b,但是子列表仍然只有一份。也就是说,只复制了「一层」。

为了解决这个问题,python中自带了一个copy模块专门做拷贝的事情,使用模块下的deepcopy函数来深层次拷贝一个对象,调用它试试看:

Python

代码语言:javascript
复制
>>> import copy
>>> b = copy.deepcopy(a)
>>> a[0] = 5
>>> a[1][1] = 5
>>> a
[5, [1, 5], 3]
>>> b
[1, [1, 2], 3]

妈妈再也不用担心我的列表交叉影响的问题了!

列表作为函数参数

参数的默认值

python的函数参数传递方法都是引用传递,而不是值传递,对于列表与字典这种可变类型就要特别小心了,可能会出现以下的错误:

Python

代码语言:javascript
复制
>>> def foo(a=[]):
...     a.append(1)
...     print a
...
>>> foo()
[1]
>>> foo()
[1, 1]

a列表会保存上次调用之后的内容!因为这个列表在内存中创建以后就一直存在,参数a默认指向这个对象。所以,要避免使用列表或字典作为函数的默认参数。使用下面的方法代替,只多一行,而且非常pythonic:

Python

代码语言:javascript
复制
def foo(a=None, b=None):
    a = a or []
    b = b or {}
    ...

更改传入列表的内容。

由于列表是可变的,你可以在函数体内增删元素,更改元素的值,从而影响到原列表。

Python

代码语言:javascript
复制
>>> def foo(array):
...     array.append(1)
...
>>> a=[0]
>>> foo(a)
>>> a
[0, 1]

然而有些时候,我们希望整体更新列表,比如去重操作array = list(set(array),这时用上面的方法就不行了,因为这里创建了一个新的列表list(set(array))并将其引用重新赋给了array,而函数内的局部变量array的更改是无法影响全局变量的,这与上一例不同的时上个例子并没有改变array的值,只是改变了array指向的对象的值。

这时候,我们又要搬出切片了。只需要改成array[:] = list(set(array))就可以了!因为切片本质上是对array中元素的操作,意思是把list(set(array))赋给array中的所有元素。

Python

代码语言:javascript
复制
>>> def unique(array):
...     array[:]=list(set(array))
...
>>> a = [1, 2, 2, 3]
>>> unique(a)
>>> a
[1, 2, 3]
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016-06-13T,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 列表的拷贝
    • 直接赋值
      • 使用list工厂函数
        • 使用copy模块
        • 列表作为函数参数
          • 参数的默认值
            • 更改传入列表的内容。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档