Python 核心技术与实战 --01 列表与元祖

Posted 小飞Python

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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:\\Users\\qf>python -m timeit \'x=(1,2,3,4,5,6)\'
20000000 loops, best of 5: 12.5 nsec per loop

C:\\Users\\qf>python -m timeit \'x=[1,2,3,4,5,6]\'(少量数据的时候)
20000000 loops, best of 5: 12.2 nsec per loop

 

python 3.7.0   索引操作 列表 优于元组了
:\\Users\\qf>python -m timeit -s \'x=[1,2,3,4,5,6]\'
0000000 loops, best of 5: 12.2 nsec per loop

:\\Users\\qf>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()排序后返回一个新的列表或元组

以上是关于Python 核心技术与实战 --01 列表与元祖的主要内容,如果未能解决你的问题,请参考以下文章

Python核心技术与实战——十三|Python中参数传递机制

Python 核心技术与实战 --02 字典和集合

开发技术--Python核心知识A

python列表与元祖

python中的元祖与字典

精通Python网络爬虫 核心技术框架与项目实战