前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >python 序列的高级用法

python 序列的高级用法

作者头像
用户3147702
发布2022-06-27 13:25:59
8560
发布2022-06-27 13:25:59
举报
文章被收录于专栏:小脑斧科技博客

1. 引言

本文我们详细介绍一下 Python 中现有的全部序列类型以及一些较为高级的用法。

2. 序列的分类

2.1. 按照存储内容

2.1.1. 存储引用的序列

  • list
  • tuple
  • colletions.deque

以上这些序列中存储的是对象的引用,因此他们不关心所引用的存储对象的类型,也就是说,在一个序列中可以放入不同类型的对象。

2.1.2. 存储对象的值

  • str
  • bytes
  • bytearray
  • memoryview
  • array.array

上述这些序列类型存储的是对象的值,他们是一段连续的存储空间,只能容纳一种类型。

2.2. 按照存储内容是否可改变

2.2.1. 可变序列

  • list
  • bytearray
  • array.array
  • collections.deque
  • memoryview

2.2.2. 不可变序列

  • tuple
  • str
  • bytes

3. 列表推导 — listcomps

3.1. 介绍

下面的代码把一个字符串转换成 unicode 码存储在 list 中并输出:

代码语言:javascript
复制
>>> symbols = '$¢£¥€¤'
>>> codes = []
>>> for symbol in symbols:
...     codes.append(ord(symbol))
...
>>> codes
[36, 162, 163, 165, 8364, 164]

下面我们将他改成列表推导的形式:

代码语言:javascript
复制
>>> symbols = '$¢£¥€¤'
>>> codes = [ord(symbol) for symbol in symbols]
>>> codes
[36, 162, 163, 165, 8364, 164]

显然,列表推导的方法大大简化了上述代码,逻辑更加清晰简练,他可以十分简洁的实现可迭代类型的元素过滤或加工,并创建出一个新列表。

3.2. 多重循环

列表推导中我们是可以放入多个循环的,例如下面这个生成笛卡尔积的例子:

代码语言:javascript
复制
>>> colors = ['black', 'white']
>>> sizes = ['S', 'M', 'L']
>>> tshirts = [(color, size) for color in colors for size in sizes]
>>> tshirts
[('black', 'S'), ('black', 'M'), ('black', 'L'), ('white', 'S'),
 ('white', 'M'), ('white', 'L')]

3.3. 注意

但需要注意的是,不要滥用列表推导:

  1. 只把创建新列表的工作交给列表推导
  2. 如果列表推导超过两行,不如改为使用 for 循环

4. lambda 表达式 — filter 与 map

filter 与 map 结合 lambda 表达式也可以做到和列表推导相同的功能,但可读性大为下降。 下面的例子将 Unicode 值大于 127 的字符对应的 Unicode 值加入列表中:

代码语言:javascript
复制
>>> symbols = '$¢£¥€¤'
>>> beyond_ascii = [ord(s) for s in symbols if ord(s) > 127]
>>> beyond_ascii
[162, 163, 165, 8364, 164]
>>> beyond_ascii = list(filter(lambda c: c > 127, map(ord, symbols)))
>>> beyond_ascii
[162, 163, 165, 8364, 164]

5. 生成器表达式

上面所有例子中,我们都只生成了列表,如果我们要生成其他类型的序列,列表推导就不适用了,此时生成器表达式成为了更好的选择。 简单地说,把列表推导的方括号变成圆括号就是生成器表达式,但在用法上,生成器表达式通常用于生成序列作为方法的参数。 下面的例子用生成器表达式计算了一组笛卡尔积:

代码语言:javascript
复制
>>> colors = ['black', 'white']
>>> sizes = ['S', 'M', 'L']
>>> for tshirt in ('%s %s' % (c, s) for c in colors for s in sizes):
...     print(tshirt)

生成器与列表推导存在本质上的不同,生成器实际上是一种惰性实现,他不会一次产生整个序列,而是每次生成一个元素,这与迭代器的原理非常类似,如果列表元素非常多,使用列表生成器可以在很大程度上节约内存的开销。

6. 元组的拆包

上一篇文章中,我们介绍了元组作为不可变列表的用法,但一个同样重要的用法是把元组用作信息的记录。

代码语言:javascript
复制
>>> city, year, pop, chg, area = ('Tokyo', 2003, 32450, 0.66, 8014)

可以看到,上面的例子中只用一行代码,就让元组中的每个元素都被赋值给不同的变量,这个过程就被称为元组拆包。

6.1. 通过元组拆包实现变量交换

下面就是一个通过元组拆包实现的十分优雅的变量交换操作:

代码语言:javascript
复制
>>> b, a = a, b

除了给变量赋值,只要可迭代对象的元素数与元组中元素数量一致,任何可迭代对象都可以用元组拆包来赋值。

6.2. 可迭代对象的拆包

可以用 * 运算符将任何一个可迭代对象拆包作为方法的参数:

代码语言:javascript
复制
>>> divmod(20, 8)
(2, 4)
>>> t = (20, 8)
>>> divmod(*t)
(2, 4)

6.3. 不确定拆分结果的获取

Python 允许被拆包赋值的一系列变量中最多存在一个以 开始的变量,他用来接收所有拆包赋值后剩下的变量。args 用来获取不确定参数是最经典的写法了。

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

6.4. 元组拆包的嵌套

元组拆包是可以嵌套的,只要接受元组嵌套结构符合表达式本身的嵌套结构,Python 就可以做出正确的处理。

6.5. 具名元组 — collections.namedtuple

具名元组就是带有名字和字段名的元组,他用元组模拟了一个简易的类。 我们通过 collections.namedtuple 方法就可以构建一个具名元组:

代码语言:javascript
复制
>>> from collections import namedtuple
>>> City = namedtuple('City', 'name country population coordinates')
>>> tokyo = City('Tokyo', 'JP', 36.933, (35.689722, 139.691667))
>>> tokyo
City(name='Tokyo', country='JP', population=36.933, coordinates=(35.689722, 139.691667))

本质上,具名元组仍然是元组用于记录元素的一种用法。

6.5.1. 具名元组的属性和方法

除了所有元组具有的属性和方法,具名元组还具有下面三个有用的属性和方法。

  • 【_fields】 — 类属性,包含具名元组所有字段名称的元组
  • 【_make()】 — 通过接受一个可迭代对象生成类实例,如 City._make(*delphi_data)
  • 【_asdict()】 — 把具名元组以 collections.OrderedDict 类型返回,可以用于友好的展示

7. 序列类型的比较

序列类型有很多,虽然大部分人在大部分时间都喜欢使用 list,但要知道某些时候你还有更好的选择:

  • list — 最常用的序列类型,使用方便,尤其在元素的添加、随机读取和遍历等方面
  • tuple — 元组,不可变的序列类型
  • set — 不重复的元素集合,对包含操作(如检查一个元素是否在集合中)有着特殊优化,这类操作的效率会非常高
  • array.array — 对于 float 对象存储的是字节码表述,存储效率比 list 高得多,如果元素是大量的数字,他将会是优于 list 的选择
  • collections.deque — 可以非常方便的实现序列两端元素的进出操作,对于栈和队列数据结构实现了原生的支持

8. 参考资料

《流畅的 python》。

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

本文分享自 小脑斧科技博客 微信公众号,前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 引言
  • 2. 序列的分类
    • 2.1. 按照存储内容
      • 2.1.1. 存储引用的序列
      • 2.1.2. 存储对象的值
    • 2.2. 按照存储内容是否可改变
      • 2.2.1. 可变序列
      • 2.2.2. 不可变序列
  • 3. 列表推导 — listcomps
    • 3.1. 介绍
      • 3.2. 多重循环
        • 3.3. 注意
        • 4. lambda 表达式 — filter 与 map
        • 5. 生成器表达式
        • 6. 元组的拆包
          • 6.1. 通过元组拆包实现变量交换
            • 6.2. 可迭代对象的拆包
              • 6.3. 不确定拆分结果的获取
                • 6.4. 元组拆包的嵌套
                  • 6.5. 具名元组 — collections.namedtuple
                    • 6.5.1. 具名元组的属性和方法
                • 7. 序列类型的比较
                • 8. 参考资料
                相关产品与服务
                对象存储
                对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档