zoukankan      html  css  js  c++  java
  • Python 核心技术与实战 --01 列表与元祖

    2019-12-21

    本文章主要讲述Python的列表元组

    高级内容:

    列表与元组存储方式的差异

    了解 dir() 函数的概念:

       dir() 函数不带参数时,返回当前范围内的变量、方法和定义的类型列表;带参数时,返回参数的属性、方法列表。

    l = [1,3,3,4,8]
    print(dir(l))
    
    
    ['__add__', '__class__', '__contains__',  

    '__delattr__', '__delitem__', '__dir__',

    '__doc__', '__eq__', '__format__', '__ge__',

    '__getattribute__', '__getitem__', '__gt__',

    '__hash__', '__iadd__', '__imul__', '__init__',

    '__init_subclass__', '__iter__', '__le__',

    '__len__', '__lt__', '__mul__', '__ne__',

    '__new__', '__reduce__', '__reduce_ex__',

    '__repr__', '__reversed__', '__rmul__',

    '__setattr__', '__setitem__', '__sizeof__',

    '__str__', '__subclasshook__', 'append', 'clear',

    'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
    #list 的详细内容
    
    l = [1,2,3]
    print(l.__sizeof__())
    
    
    64

    tup =(1,2,3)
    print(tup.__sizeof__())

    48

    列表和元组内的元素相同,但是 元组比列表少了 16 个字节, 为什么呢?

    由于列表是动态的,所以它需要存储指针,来指向对应的元素(上述例子中,对于int类型,8个字节)。另外由于列表可变,所以需要额外存储已经分配的长度大小(8字节),这样才能实时追踪列表空间的使用情况,当空间不足时,及时分配额外空间。

    可以看一下 python list  C 源码:

          https://blog.csdn.net/qq_33339479/article/details/81807096

    #define PyObject_VAR_HEAD      PyVarObject ob_base;
    #define Py_INVALID_SIZE (Py_ssize_t)-1
    
    /* Nothing is actually declared to be a PyObject, but every pointer to
     * a Python object can be cast to a PyObject*.  This is inheritance built
     * by hand.  Similarly every pointer to a variable-size Python object can,
     * in addition, be cast to PyVarObject*.
     */
    typedef struct _object {
        _PyObject_HEAD_EXTRA
        Py_ssize_t ob_refcnt;                                       // 引用计数值
        struct _typeobject *ob_type;                                // 基本的类型 type
    } PyObject;
    
    typedef struct {
        PyObject ob_base;                                           // 对象基本信息
        Py_ssize_t ob_size; /* Number of items in variable part */  // 变长对象的元素个数
    } PyVarObject;
    ...
    typedef struct {
        PyObject_VAR_HEAD                                           // 变量头部信息
        /* Vector of pointers to list elements.  list[0] is ob_item[0], etc. */
        PyObject **ob_item;                                         // 元素指向具体指
    
        /* ob_item contains space for 'allocated' elements.  The number
         * currently in use is ob_size.
         * Invariants:
         *     0 <= ob_size <= allocated
         *     len(list) == ob_size
         *     ob_item == NULL implies ob_size == allocated == 0
         * list.sort() temporarily sets allocated to -1 to detect mutations.
         *
         * Items must normally not be NULL, except during construction when
         * the list is not yet visible outside the function that builds it.
         */
        Py_ssize_t allocated;                                       // 当前空间
    } PyListObject;
    l = []
    print(l.__sizeof__())
    
    l.append(1)
    print(l.__sizeof__())
    
    l.append(2)
    print(l.__sizeof__())
    
    
    
    40 
    72
    72

    列表的空间分配的过程可以看到,为了减小每次增加/删除的开销,python每次分配空间的时候都会多分配一点,这样的机制保证了其操作的高效性:增加/删除的时间复杂度均为O(1)

    因为元组是静态的所以Python对于小量的静态内存就会放到缓存里面,下次分配同样多的元组时,就不用向操作系统发出请求了,就直接分配之前的缓存的内存空间。这样程序的运行速度就得到保证

    初始化过程 python 3.7.0  列表优于元组(少量数据的时候)
    
    C:Usersqf>python -m timeit 'x=(1,2,3,4,5,6)'
    20000000 loops, best of 5: 12.5 nsec per loop
    
    C:Usersqf>python -m timeit 'x=[1,2,3,4,5,6]'(少量数据的时候)
    20000000 loops, best of 5: 12.2 nsec per loop
    python 3.7.0   索引操作 列表 优于元组了
    :Usersqf>python -m timeit -s 'x=[1,2,3,4,5,6]'
    0000000 loops, best of 5: 12.2 nsec per loop
    
    :Usersqf>python -m timeit -s 'x=(1,2,3,4,5,6)'
    0000000 loops, best of 5: 13.7 nsec per loop

    列表和元组的使用场景

    1. 如果存储的数据和数量不变,比如你有一个函数,需要返回的是一个地点的经纬度,然后直接传给前端渲染,那么肯定选用元组更合适。

    2.如果存储的数据或数量是可变的,比如社交平台上的一个日志功能,是统计一个用户在一周之内看了哪些用户的帖子,那么则用列表更合适

    以下为基础内容:

    1. 列表与元组基础

             共同点: 列表和元组都是一个可以放置任意数据类型的有序集合。

             不同点:1. 列表 是动态的,长度大小不固定,可以随意增加/删除 改变元素(mutable)

                               元组是静态的,长度大小固定,无法增加删减或者改变(immutable)

    例子1:

    1 # 列表的例子
    2 l = [1, 2, 3, 4]
    3 l[0] = 2
    4 print(l)
    [2, 2, 3, 4]

    1 # 元组的例子
    2 tup = (1, 2, 3, 4)
    3 tup[0] = 2
    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
    <ipython-input-4-77cf1f9285bd> in <module>
          1 # 元组的例子
          2 tup = (1, 2, 3, 4)
    ----> 3 tup[0] = 2
          4 
    
    TypeError: 'tuple' object does not support item assignment

    但是你想对已有的元组做修改该怎么办呢?

    答案:开辟一块新的内存,创建新的元组

    # 元组和列表增加的例子
    tup = (1, 2, 3, 4)
    new_tup = tup + (5,)
    print(new_tup)
    
    l = [1,2,3,4]
    l.append(5)
    print(l)

    执行结果: (
    1, 2, 3, 4, 5) [1, 2, 3, 4, 5]

    2.列表和元组的索引

    python 的列表和元组都支持负索引切片

    列表和 元组支持任意嵌套

    l = [[1,2,3],[4,5,6]]
    tup =((1,2,3),(4,5,6))

    通过 list() 和 tuple() 可以将两者相互转换.

    3. 列表和元组常用的内置函数

    (1) count()

    # 元组和列表增加的例子
    tup = (1, 2, 3, 4)
    new_tup = tup + (5,)
    print(new_tup.count(1))
    
    l = [1,2,3,4]
    l.append(5)
    print(l.count(1))
    
    执行结果
    1
    1

    (2) index(item) 给出第一次出现的item 的索引

    (3) list.reverse() 原地倒转列表 (元组没有)

    l = [1,3,3,4,8]
    l.append(5)
    l.reverse()
    print(l)
    
    
    
    [5, 8, 4, 3, 3, 1]

    (4) list.sort() 排序列表 (元组没有)

    l = [1,3,3,4,8]
    l.append(5)
    l.reverse()
    l.sort()
    print(l)
    
    
    [1, 3, 3, 4, 5, 8]

    (5)reserved() 翻转后返回一个新的列表或元组

    (6) sorted()排序后返回一个新的列表或元组

  • 相关阅读:
    02-链路层
    01-TCP/IP概述
    ARM Cortex-A9 (tiny 4412)
    STM32 f407 温湿度采集报警
    arduino mega 避障报距小车
    归纳法调试
    python 数据类型Ⅲ(字典)
    Python 数据类型Ⅱ(列表,元祖)
    Python 数据类型(str,int,bool)
    Python while循环&格式化输出&运算符
  • 原文地址:https://www.cnblogs.com/qifei-liu/p/12076976.html
Copyright © 2011-2022 走看看