zoukankan      html  css  js  c++  java
  • python元组

    元组常常称为“不可变列表”,然而这并没有完全概括元组的特点。除 了用作不可变的列表,它还可以用于没有字段名的记录。鉴于后者常常被忽略,我们先来 看看元组作为记录的功用。

    1.元祖和记录

    元组其实是对数据的记录:元组中的每个元素都存放了记录中一个字段的数据,外加这个 字段的位置。正是这个位置信息给数据赋予了意义。 如果只把元组理解为不可变的列表,那其他信息——它所含有的元素的总数和它们的位置 ——似乎就变得可有可无。但是如果把元组当作一些字段的集合,那么数量和位置信息就 变得非常重要了。

    示例 1 把元组用作记录

    >>> positon=(33.9425,-118.408056)
    >>> city,year,pop,chg,area=('东京',2018,32450,0.66,8014)
    >>> traveler_ids=[('美国','31195855'),('巴西','ce342567'),('西班牙','xda205856')]
    >>> for passport in sorted(traveler_ids):
    ...     print('%s/%s' % passport)
    ... 
    巴西/ce342567
    美国/31195855
    西班牙/xda205856
    >>> for country,_ in traveler_ids:
    ...     print(country)
    ... 
    美国
    巴西
    西班牙
    >>> 

    东京市的一些信息:市名、年份、人口(单位:百万)、人口变化(单位:百分比) 和面积(单位:平方千米)。

    for 循环可以分别提取元组里的元素,也叫作拆包(unpacking)。因为元组中第二个 元素对我们没有什么用,所以它赋值给“_”占位符

    2.元组拆包

    示例 1 中,我们把元组 ('东京',2018,32450,0.66,8014) 里的元素分别赋值 给变量 city、year、pop、chg 和 area,而这所有的赋值我们只用一行声明就写完了。 同样,在后面一行中,一个 % 运算符就把 passport 元组里的元素对应到了 print 函数 的格式字符串空档中。这两个都是对元组拆包的应用。

    元组拆包可以应用到任何可迭代对象上,唯一的硬性要求是,被可迭代对象中 的元素数量必须要跟接受这些元素的元组的空档数一致。除非我们用 * 来表示忽略 多余的元素

    最好辨认的元组拆包形式就是平行赋值,也就是说把一个可迭代对象里的元素,一并赋 值到由对应的变量组成的元组中。就像下面这段代码:

    >>> position=('上海','徐汇')
    >>> city,area=position
    >>> city
    '上海'
    >>> area
    '徐汇'

    另外一个很优雅的写法当属不使用中间变量交换两个变量的值:

    >>> b, a = a, b

    还可以用 * 运算符把一个可迭代对象拆开作为函数的参数

    >>> divmod(20, 8)  
    (2, 4)
    >>> t = (20, 8)
    >>> divmod(*t)
    (2, 4)
    >>> quotient, remainder = divmod(*t)
    >>> quotient, remainder
    (2, 4)

    下面是另一个例子,这里元组拆包的用法则是让一个函数可以用元组的形式返回多个值, 然后调用函数的代码就能轻松地接受这些返回值。比如 os.path.split() 函数就会返回 以路径和最后一个文件名组成的元组 (/home/admin/.ssh/,idsrsa.pub): 

    >>> import os
    >>> _, filename=os.path.split('/home/admin/.ssh/idrsa.pub')
    >>> filename
    'idrsa.pub'

    在进行拆包的时候,我们不总是对元组里所有的数据都感兴趣,_ 占位符能帮助处理这种 情况,上面这段代码也展示了它的用法。

    除此之外,在元组拆包中使用 * 也可以帮助我们把注意力集中在元组的部分元素上。 用*来处理剩下的元素 在 Python 中,函数用 *args 来获取不确定数量的参数算是一种经典写法了。 于是 Python 3 里,这个概念被扩展到了平行赋值中

    >>> a, b, *rest = range(5)
    >>> a, b, rest
    (0, 1, [2, 3, 4])
    >>> a, b, *rest = range(3)
    >>> a, b, rest
    (0, 1, [2])
    >>> a, b, *rest = range(2)
    >>> a, b, rest
    (0, 1, [])

    在平行赋值中,* 前缀只能用在一个变量名前面,但是这个变量可以出现在赋值表达式的 任意位置:

    >>> a, *body, c, d = range(5)
    >>> a, body, c, d
    (0, [1, 2], 3, 4)
    >>> *head, b, c, d = range(5)
    >>> head, b, c, d
    ([0, 1], 2, 3, 4)

    另外元组拆包还有个强大的功能,那就是可以应用在嵌套结构中。

    3.嵌套元组拆包

    接受表达式的元组可以是嵌套式的,例如 (a, b, (c, d))。只要这个接受元组的嵌套结 构符合表达式本身的嵌套结构,Python 就可以作出正确的对应。

    示例 2 就是对嵌套元组 拆包的应用。

    用嵌套元组来获取经度

    metro_areas = [
     ('Tokyo','JP',36.933,(35.689722,139.691667)), #
     ('Delhi NCR', 'IN', 21.935, (28.613889, 77.208889)),
     ('Mexico City', 'MX', 20.142, (19.433333, -99.133333)),
     ('New York-Newark', 'US', 20.104, (40.808611, -74.020386)),
     ('Sao Paulo', 'BR', 19.649, (-23.547778, -46.635833)),
    ]
    print('{:15} | {:^9} | {:^9}'.format('', 'lat.', 'long.'))
    fmt = '{:15} | {:9.4f} | {:9.4f}'
    for name, cc, pop, (latitude, longitude) in metro_areas: #
     if longitude <= 0: #
     print(fmt.format(name, latitude, longitude))

    ❶ 每个元组内有 4 个元素,其中最后一个元素是一对坐标。

    ❷ 我们把输入元组的最后一个元素拆包到由变量构成的元组里,这样就获取了坐标。

    ❸ if longitude <= 0: 这个条件判断把输出限制在西半球的城市。

    输出是这样的:

     | lat. | long.
    Mexico City | 19.4333 | -99.1333
    New York-Newark | 40.8086 | -74.0204
    Sao Paul | -23.5478 | -46.6358

    元组已经设计得很好用了,但作为记录来用的话,还是少了一个功能:我们时常会需要给 记录中的字段命名。namedtuple 函数的出现帮我们解决了这个问题。

    4.具名元组

    collections.namedtuple 是一个工厂函数,它可以用来构建一个带字段名的元组和一 个有名字的类——这个带名字的类对调试程序有很大帮助。

     用 namedtuple 构建的类的实例所消耗的内存跟元组是一样的,因为字段名都 被存在对应的类里面。这个实例跟普通的对象实例比起来也要小一些,因为 Python 不会用 __dict__ 来存放这些实例的属性。

    示例 3 定义和使用具名元组

    >>> 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))
    >>> tokyo.population ➌
    36.933
    >>> tokyo.coordinates
    (35.689722, 139.691667)
    >>> tokyo[1]
    'JP'

    ❶ 创建一个具名元组需要两个参数,一个是类名,另一个是类的各个字段的名字。后者 可以是由数个字符串组成的可迭代对象,或者是由空格分隔开的字段名组成的字符串。

    ❷ 存放在对应字段里的数据要以一串参数的形式传入到构造函数中(注意,元组的构造 函数却只接受单一的可迭代对象)。

    ❸ 你可以通过字段名或者位置来获取一个字段的信息。 除了从普通元组那里继承来的属性之外,具名元组还有一些自己专有的属性。

    示例 4 中就展示了几个最有用的:_fields 类属性、类方法 _make(iterable) 和实例方法 _asdict()。

    示例 4 具名元组的属性和方法(接续前一个示例)

    >>> City._fields ➊
    ('name', 'country', 'population', 'coordinates')
    >>> LatLong = namedtuple('LatLong', 'lat long')
    >>> delhi_data = ('Delhi NCR', 'IN', 21.935, LatLong(28.613889, 77.208889))
    >>> delhi = City._make(delhi_data) ➋
    >>> delhi._asdict() ➌
    OrderedDict([('name', 'Delhi NCR'), ('country', 'IN'), ('population',
    21.935), ('coordinates', LatLong(lat=28.613889, long=77.208889))])
    >>> for key, value in delhi._asdict().items():
     print(key + ':', value)
    name: Delhi NCR
    country: IN
    population: 21.935
    coordinates: LatLong(lat=28.613889, long=77.208889)

     ❶ _fields 属性是一个包含这个类所有字段名称的元组。

    ❷ 用 _make() 通过接受一个可迭代对象来生成这个类的一个实例,它的作用跟 City(*delhi_data) 是一样的。

    ❸ _asdict() 把具名元组以 collections.OrderedDict 的形式返回,我们可以利用它 来把元组里的信息友好地呈现出来。 现在我们知道了,元组是一种很强大的可以当作记录来用的数据类型。它的第二个角色则 是充当一个不可变的列表。下面就来看看它的第二重功能。

  • 相关阅读:
    jQuery学习(三)
    HTML基础
    对于跨域问题的解决
    Spring boot 默认静态资源路径与手动配置访问路径
    json:java中前台向后台传对象数据
    javascrit常用互动方法
    java IO流
    HTML中data* 属性
    java中一些对象(po,vo,dao,pojo)等的解释
    使用mybatis generator插件,自动生成dao、dto、mapper等文件
  • 原文地址:https://www.cnblogs.com/benjamin77/p/10007116.html
Copyright © 2011-2022 走看看