精华内容
下载资源
问答
  • 主要介绍了python实现对象列表根据某个属性排序的方法,结合具体实例形式详细分析了Python对象列表遍历、排序的两种常见操作技巧,需要的朋友可以参考下
  • 主要介绍了Python List列表对象内置方法,结合实例形式详细分析了Python列表list各种常用内置方法的功能与使用技巧,需要的朋友可以参考下
  • 使用环境:需要先安装PyCharm(请自己百度下载安装),以及然后官网上下载Python 2.7版本,以及Python 3.7版本后,安装在自己的电脑上。 使用步骤: ...目的:帮助理解列表对象Python中的创建使用。
  • 主要介绍了Python列表对象实现原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • 使用环境:需要先安装PyCharm(请自己百度下载安装),以及然后官网上下载Python 2.7版本,以及Python 3.7版本后,安装在自己的电脑上。...目的:帮助理解列表对象的下标访问在Python中的具体使用。
  • Python中的列表基于PyListObject实现,列表支持元素的插入、删除、更新操作,因此PyListObject是一个变长对象列表的长度随着元素的增加和删除而变长和变短),同时它还是一个可变对象列表中的元素根据列表的操作...

    转载于https://foofish.net/python-list-implements.html


    Python中的列表基于PyListObject实现,列表支持元素的插入、删除、更新操作,因此PyListObject是一个变长对象(列表的长度随着元素的增加和删除而变长和变短),同时它还是一个可变对象(列表中的元素根据列表的操作而发生变化,内存大小动态的变化),PyListObject的定义:

    typedef struct {
        # 列表对象引用计数
        int ob_refcnt;  
        # 列表类型对象      
        struct _typeobject *ob_type;
        # 列表元素的长度
        int ob_size; /* Number of items in variable part */
        # 真正存放列表元素容器的指针,list[0] 就是 ob_item[0]
        PyObject **ob_item;
        # 当前列表可容纳的元素大小
        Py_ssize_t allocated;
    } PyListObject;
    

    咋一看PyListObject对象的定义非常简单,除了通用对象都有的引用计数(ob_refcnt)、类型信息(ob_type),以及变长对象的长度(ob_size)之外,剩下的只有ob_item,和allocated,ob_item是真正存放列表元素容器的指针,专门有一块内存用来存储列表元素,这块内存的大小就是allocated所能容纳的空间。alloocated是列表所能容纳的元素大小,而且满足条件:

    • 0 <= ob_size <= allocated
    • len(list) == ob_size
    • ob_item == NULL 时 ob_size == allocated == 0

    pylistobject

    列表对象的创建

    PylistObject对象的是通过函数PyList_New创建而成,接收参数size,该参数用于指定列表对象所能容纳的最大元素个数。

    // 列表缓冲池, PyList_MAXFREELIST80
    static PyListObject *free_list[PyList_MAXFREELIST];
    //缓冲池当前大小
    static int numfree = 0;
    
    PyObject *PyList_New(Py_ssize_t size)
    {
        PyListObject *op; //列表对象
        size_t nbytes;    //创建列表对象需要分配的内存大小
    
        if (size < 0) {
            PyErr_BadInternalCall();
            return NULL;
        }
        /* Check for overflow without an actual overflow,
         *  which can cause compiler to optimise out */
        if ((size_t)size > PY_SIZE_MAX / sizeof(PyObject *))
            return PyErr_NoMemory();
        nbytes = size * sizeof(PyObject *);
        if (numfree) {
            numfree--;
            op = free_list[numfree];
            _Py_NewReference((PyObject *)op);
    
        } else {
            op = PyObject_GC_New(PyListObject, &PyList_Type);
            if (op == NULL)
                return NULL;
    
        }
        if (size <= 0)
            op->ob_item = NULL;
        else {
            op->ob_item = (PyObject **) PyMem_MALLOC(nbytes);
            if (op->ob_item == NULL) {
                Py_DECREF(op);
                return PyErr_NoMemory();
            }
            memset(op->ob_item, 0, nbytes);
        }
        # 设置ob_size
        Py_SIZE(op) = size;
        op->allocated = size;
        _PyObject_GC_TRACK(op);
        return (PyObject *) op;
    }
    

    创建过程大致是:

    1. 检查size参数是否有效,如果小于0,直接返回NULL,创建失败
    2. 检查size参数是否超出Python所能接受的大小,如果大于PY_SIZE_MAX(64位机器为8字节,在32位机器为4字节),内存溢出。
    3. 检查缓冲池free_list是否有可用的对象,有则直接从缓冲池中使用,没有则创建新的PyListObject,分配内存。
    4. 初始化ob_item中的元素的值为Null
    5. 设置PyListObject的allocated和ob_size。

    PYLISTOBJECT对象的缓冲池

    free_list是PyListObject对象的缓冲池,其大小为80,那么PyListObject对象是什么时候加入到缓冲池free_list的呢?答案在list_dealloc方法中:

    static void
    list_dealloc(PyListObject *op)
    {
        Py_ssize_t i;
        PyObject_GC_UnTrack(op);
        Py_TRASHCAN_SAFE_BEGIN(op)
        if (
            i = Py_SIZE(op);
            while (--i >= 0) {
                Py_XDECREF(op->ob_item[i]);
            }
            PyMem_FREE(op->ob_item);
        }
        if (numfree < PyList_MAXFREELIST && PyList_CheckExact(op))
            free_list[numfree++] = op;
        else
            Py_TYPE(op)->tp_free((PyObject *)op);
        Py_TRASHCAN_SAFE_END(op)
    }
    

    当PyListObject对象被销毁的时候,首先将列表中所有元素的引用计数减一,然后释放ob_item占用的内存,只要缓冲池空间还没满,那么就把该PyListObject加入到缓冲池中(此时PyListObject占用的内存并不会正真正回收给系统,下次创建PyListObject优先从缓冲池中获取PyListObject),否则释放PyListObject对象的内存空间。

    列表元素插入

    设置列表某个位置的值时,如“list[1]=0”,列表的内存结构并不会发生变化,而往列表中插入元素时会改变列表的内存结构:

    static int
    ins1(PyListObject *self, Py_ssize_t where, PyObject *v)
    {
        // n是列表元素长度
        Py_ssize_t i, n = Py_SIZE(self);
        PyObject **items;
        if (v == NULL) {
            PyErr_BadInternalCall();
            return -1;
        }
        if (n == PY_SSIZE_T_MAX) {
            PyErr_SetString(PyExc_OverflowError,
                "cannot add more objects to list");
            return -1;
        }
    
        if (list_resize(self, n+1) == -1)
            return -1;
    
        if (where < 0) {
            where += n;
            if (where < 0)
                where = 0;
        }
        if (where > n)
            where = n;
        items = self->ob_item;
        for (i = n; --i >= where; )
            items[i+1] = items[i];
        Py_INCREF(v);
        items[where] = v;
        return 0;
    }
    

    相比设置某个列表位置的值来说,插入操作要多一次PyListObject容量大小的调整,逻辑是list_resize,其次是挪动where之后的元素位置。

    // newsize 列表新的长度
    static int  
    list_resize(PyListObject *self, Py_ssize_t newsize)
    {
        PyObject **items;
        size_t new_allocated;
        Py_ssize_t allocated = self->allocated;
    
    
        if (allocated >= newsize && newsize >= (allocated >> 1)) {
            assert(self->ob_item != NULL || newsize == 0);
            Py_SIZE(self) = newsize;
            return 0;
        }
    
        new_allocated = (newsize >> 3) + (newsize < 9 ? 3 : 6);
    
        /* check for integer overflow */
        if (new_allocated > PY_SIZE_MAX - newsize) {
            PyErr_NoMemory();
            return -1;
        } else {
            new_allocated += newsize;
        }
    
        if (newsize == 0)
            new_allocated = 0;
        items = self->ob_item;
        if (new_allocated <= (PY_SIZE_MAX / sizeof(PyObject *)))
            PyMem_RESIZE(items, PyObject *, new_allocated);
        else
            items = NULL;
        if (items == NULL) {
            PyErr_NoMemory();
            return -1;
        }
        self->ob_item = items;
        Py_SIZE(self) = newsize;
        self->allocated = new_allocated;
        return 0;
    }
    

    满足 allocated >= newsize && newsize >= (allocated /2)时,简单改变list的元素长度,PyListObject对象不会重新分配内存空间,否则重新分配内存空间,如果newsize<allocated/2,那么会减缩内存空间,如果newsize>allocated,就会扩大内存空间。当newsize==0时内存空间将缩减为0。!python_list_resize

    总结

    • PyListObject缓冲池的创建发生在列表销毁的时候。
    • PyListObject对象的创建分两步:先创建PyListObject对象,然后初始化元素列表为NULL。
    • PyListObject对象的销毁分两步:先销毁PyListObject对象中的元素列表,然后销毁PyListObject本身。
    • PyListObject对象内存的占用空间会根据列表长度的变化而调整。

    参考:


    展开全文
  • python对象

    2019-09-27 13:39:54
    python全景--python程序结构 程序由模块构成; 模块包含语句; 语句包含表达式; 表达式建立并处理对象。 每个对象都有一个身份,一个类型,一个数值 ... 列表,字典 如果对象值不可以修改,成为不可变对象 --&g...

    python全景--python程序结构

    程序由模块构成;
    模块包含语句;
    语句包含表达式;
    表达式建立并处理对象。
    1114822-20170228193839876-591574264.png

    每个对象都有一个身份,一个类型,一个数值

    强类型语言,类型不符合,报错 python
    弱类型语言,bash,计算时隐式转换
    1114822-20170228193552360-1894468728.png

    实例创建之后,身份类型都不可以改变
    如果对象值可以修改,成为可变对象 --> 列表,字典
    如果对象值不可以修改,成为不可变对象 --> 数值,字符串,元组
    对象值的修改实际上是对象值内存指针指向的修改

    类型属于对象,而不是变量。
    python变量是在特定的时间引用了特定的对象
    对象的头部信息:类型标识符来标记对象类型,引用计数器用来决定是否可以回收。

    如果某个对象包含对其他对象的引用,称其为容器.

    对象比较

    比较方式 含义 比较方法
    类型比较 两个对象的类型是否相同 type(a) is type(b) <==>type(a) == type(b)
    数值比较 存储的数据是否相同 a == b
    身份比较 两个变量名引用的是否为同一内存对象 a is b <==> id(a) == id(b)

    转载于:https://www.cnblogs.com/hiavatar/p/6480606.html

    展开全文
  • 使用环境:需要先安装PyCharm(请自己百度下载安装),以及然后官网上下载Python 2.7版本,以及Python 3.7版本后,安装在自己的电脑上。 使用步骤: ...目的:帮助理解列表对象切片在Python中的具体使用。
  • python对象特殊方法列表

    千次阅读 2015-04-16 16:29:51
    名称(省略双划线) 说明 ...为实例添加调用方法,如实例x是Class C的实例,则调用x()时会调用Class的call方法 ...垃圾回收之前会调用,开发的时候要小心使用这个方法,因为这个方法可能会引起不会进行GC ...
    名称(省略双划线) 说明
    call 为实例添加调用方法,如实例x是Class C的实例,则调用x()时会调用Class的call方法
    cmp 比较方法
    del 垃圾回收之前会调用,开发的时候要小心使用这个方法,因为这个方法可能会引起不会进行GC
    delattr 当要求解除绑定关系时,会调用这个方法
    eq
    ge
    gt
    le
    lt
    ne
    x==y
    x>=y
    x>y
    x<y
    x<=y
    x<>y
    getattr x.y的时候调用(当getattribute找到该属性的时候调用)
    getattribute x.y的时候被调用(无条件被调用)
    get 当实例x中包括其他类的实例的时候被调用。
    init 当实例化之后被调用,进行初始化工作
    new 在实例化之前调用,在C()时被触发,可以在这个方法中进行一些工作,如实现单例模式
    nonzero 当调用bool(x)的时候会调用这个方法
    setattr 这个实际上是对getattribute的对应,而不是getattr的对应
    repr 若str不存在的时候将调用该方法
    str 当使用str方法的时候会优点调用
    unicode 当使用unicode(x)的时候会调用
    展开全文
  • 列表 列表是一个任意类型的对象的位置相关的有序集合,没有固定的大小。...python列表没有固定类型的约束,列表中可以包含不同类型 的对象列表也没有固定大小,可以根据需要来随意增加或减少列表大小: appen...

    列表

    列表是一个任意类型的对象的位置相关的有序集合,没有固定的大小。与字符串不同的是列表是可变的通过对相应偏移量进行赋值可以定位地对列表进行修改
    序列操作
    列表支持之前讨论到对字符创的所有的序列操作。唯一的区别是结果是列表而不是字符串。
    特定类型的操作
    python的列表没有固定类型的约束,列表中可以包含不同类型 的对象;列表也没有固定大小,可以根据需要来随意增加或减少列表大小:
    在这里插入图片描述
    在这里插入图片描述
    append方法增加列表的大小,并在列表尾部插入一项。pop方法(或者del语句)移除给定偏移量的一项等,因为列表是可变的,大多数的列表方法都会原位置改变列表对象,而不是创建一个新的列表。
    边界检查
    尽管python中列表没有固定的大小,但是python不允许引用不存在的元素。超出列表末尾之外的索引总是会导致错误,对末尾范围之外赋值也是如此。
    在这里插入图片描述
    为了让一个列表增大,我们可以调用append这样的列表方法。
    嵌套
    pytho核心数据类型的一个优秀特性就是它们支持任意的嵌套。能以任意的组合对其进行嵌套,并可以多个层次进行嵌套。这种特性的一个直接应用就是实现矩阵。
    在这里插入图片描述
    推导
    除了序列操作和列表方法外,python还支持一种更高级的列表推导表达式操作,可以用来处理矩阵,因为python中的矩阵是按照行来进行储存的,因此可以很简单的利用索引就可以获得矩阵的行,而要获得矩阵的列往往就需要通过列表推导表达式。(NumPy)
    在这里插入图片描述
    列表推导源自数学中集合的概念。它是通过一种对序列中的每一项运行一个表达式来创建一个新列表的方法,每次一个,从左到右。列表推导是编写在方括号中的,并使用了同一个变量名表达式和循环结构组成,它在实际中的运用可以变得更复杂。
    在这里插入图片描述
    这些表达式同样可以用于储存对个数值,只要将这些值包在一个嵌套的集合中。下面的代码展示了原生函数range生成连连续整数的功能。
    在这里插入图片描述
    列表推导能在python中的任何序列类型中发挥作用,甚至一些不属于序列的类型。会在后续学习中详细了解。

    字典

    字典不是序列,而是一种映射。它同样是一个其他对象的集合,但它是通过键(key)而不是通过相对位置来储存对象的。字典也是python中唯一的一种映射类型,具有可变性。同列表一样,可以就地改变并随着需求增大或者减小。
    映射操作
    字典作为常量编写时,编写在大括号中,并包含一系列的“键:值”对,我们可以通过键对这个字典进行索引来读取或者改变键所关联的值。字典的索引操作使用的适合序列相同的语法,但是在方括号中的元素是键,而不是相对位置。

    在这里插入图片描述
    字典还有其他几种创建方法:
    在这里插入图片描述
    先创建一个空的字典,然后再向里面填充。与列表中禁止边界外的赋值不同,对一个新的字典的键赋值会创建该键。
    还有dict类型名传递键值参数对,或者zip配对来创建。
    在这里插入图片描述
    再次强调字典的键从左到右的顺序是被打乱的!映射并不是按位置排列的,就算返回值和输入的值顺序一样也仅仅是概率问题。

    重返嵌套
    在这里插入图片描述
    嵌套允许直接并轻松地建立复杂的信息结构。此外方便的是,python中当最后一次引用对象后(例如这个变量用其他的值进行赋值),这个对象所占用的内存空间将会自动清理掉。python的垃圾回收特性可以在运行时可以清理不再会用的内容。这部分内容会在后续内容介绍。

    不存在的键:if测试
    如同映射,字典只支持通过键访问对象,但除此之外,它们也支持通过方法调用进行指定类型的操作。虽然能够通过给新的键赋值来扩充字典,但访问一个不存在的键仍然是一个错误。
    在这里插入图片描述
    在我们访问一个不存在的东西往往会是一个程序错误,但我们并不希望得到一个错误。此时,一个技巧就是在这之前进行测试。字典的in关系表达式允许我们查询其中一个键是否存在,并可以通过python的if语句对查询的结果进行分支处理。
    在这里插入图片描述
    此处代码有错误,暂时没明白是什么原因(没有缩进)
    在这里插入图片描述
    在这里插入图片描述除了in测试,还有其他方法进行测试,如get方法(带有一个默认值的条件索引)、try语句(一个捕捉异常并从异常中恢复的工具)、if/else三元表达式(实质上是挤在一行的一条if语句)。
    在这里插入图片描述

    键的排序:for循环
    因为字典不是序列,所以我们不能要求打印我们建立的字典中键的顺序会和输入时一样,但当我们确实需要字典按字典出现的时候,一个常用的方法就是通过字典的key方法收集一个键的列表,使用列表sort方法进行排序,然后用for循环逐个进行显示结果。
    在这里插入图片描述
    (python3.7这默认就是有序的,不知道是巧合还是改进过了。。)
    这个三步骤的过程可以由sorted内置函数一步完成:
    在这里插入图片描述
    for循环以及与其作用相近的while循环,是在脚本中编写重复性任务语句的主要方法。for循环是一个序列操作(其实是迭代操作),可以作用于任何一个序列对象上,并且就像列表推导一样,甚至可以作用于一些不是序列的对象。while循环虽然更为常见,且不局限于逐一访问序列,但通常需要更多的代码:
    在这里插入图片描述

    ## 迭代和优化
    for循环和列表表达式都是真正的通用迭代工具,事实上,它们都能够工作于遵守迭代协议的任意可迭代对象。
    一个可迭代的对象可以实内存中物理储存的序列,也可以是一个在迭代操作情况下每次产生的一个对象(一种“虚拟”的序列)。它们都被认为是可迭代的对象。之前的推导表达式生成器(generator)就是后者,python文件对象则是前者(文件内容不是在一个列表中,而是按需取出)。
    任何一个从左到右扫描一个对象的python工具都使用迭代协议。因为字典是可迭代的对象,因此之前的sorted调用可以直接作用于字典对象而不是使用sort方法来得到一个序列。
    也意味着任何的列表推导表达式都可以编写成一个等价的for循环,通过在运行时手动添加列表来创建最终的列表。
    在这里插入图片描述
    两种工具在迭代协议内部发挥作用,并产生相同的作用,但运行的速度在不同情况下有差异,后面再进行详细学习。

    展开全文
  • 文章目录Python常用对象列表操作手册之列表方法与运算符运算符 Python常用对象列表操作手册之列表方法与运算符 运算符 运算符部分以后不再讲解 (除非遇到特殊的对象行为: 如字符串的%运算符) 运算符 说明 ...
  • 列表末尾添加新的对象 2 list.count(obj) 统计某个元素在列表中出现的次数 3 list.extend(obj) 在列表末尾一次性追加另一个序列中的多个值(用新列表扩展原来的列表) 4 ...
  • Python对象类型

    2015-04-11 23:21:42
    Python对象类型 Python进阶(二)——Python对象类型 上一章中我们主要讲了Python的安装与Python基本命令行,IDLE的应用。本章中我们将讲述Python的对象类型,包括数字、字符串、列表、字典、元组、...
  • python对象类型

    2019-03-27 20:36:54
    python中常用的内置对象:数字、字符串、列表、字典、元组、文件、集合等 python程序中处理的每一样东西都是对象,而使用内置对象使python编程更加简单。 在python中没有类型声明,运行的表达式的语法决定了创建和...
  • python列表,字典及对象的排序方法

    千次阅读 2019-02-20 22:42:29
    python 列表内元素及对象排序相关整理 今天工作中遇到一个合并excel后需要根据每一列长度降序的方式将内容(列表嵌套)写入.其中涉及到将外层列表根据每一个嵌套列表的长度进行排序,因此回到家后整理一下python列表...
  • Python 对象赋值踩坑

    2020-11-24 21:28:54
    Python 对象赋值实际上...python对象赋值实际上是对象的引用,与之类似,列表类型的对象进行append操作时,实际上追加的也是该对象的引用,而不是直接拷贝该对象。 list.append(nums) list.append(nums.copy) ...
  • Python对象内存地址

    万次阅读 多人点赞 2018-08-02 16:58:59
    这里我们只简单看下python对象内存地址的相关基础知识,以及编码过程中一些注意事项,关于python解释器的内存管理机制,涉及到解释器内核的内存池原理,这里不做深入探讨,有兴趣的朋友可以去阅读解释器源代...
  • Python学习2--Python对象

    2018-07-13 16:13:41
    1. Python对象定义、类型、分类 2. Python常见内建函数 所有python对象都有三个特性 - 身份:每一个对象都有一个唯一的身份标识自己,可以使用内建函数id()获取 - 类型:可以使用内建函数type()获取 - 值 ...
  • 一、什么是python对象 在python中,构造的任何类型的值都是一个对象。比如一个整数类型的值,一个字符串,一个列表等,都可以看做是对象。 所有的对象分为三部分: (1)身份。每个对象都有个标识自己的id。可用...
  • x = [3,5,4,2,1] x.sort() print(x) 运行结果: [1, 2, 3, 4, 5]

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 19,394
精华内容 7,757
关键字:

python对象列表

python 订阅