前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python核心类型总结

Python核心类型总结

作者头像
zy010101
发布2021-11-15 16:48:13
4240
发布2021-11-15 16:48:13
举报
文章被收录于专栏:程序员

Python核心类型总结

Python内置的核心数据类型如下表所示。

对象类型

分类

是否可变

数字

数值

字符串

序列

元组

序列

列表

序列

集合

集合

字典

映射

在使用的时候,需要我们注意的是python中的一切变量都是引用赋值的,除非你显示进行复制操作。变量本身没有数据类型,有数据类型的是对象。变量就是一个void *类型的指针。

  1. 列表,元组,字典可以包含任何种类的对象,可以任意嵌套。
  2. 集合只能包含不可变类型的对象

因为Python中的复合对象类型可以嵌套任意的对象类型,因此它们几乎可以表示任意的复杂数据。

嵌套对象在内部实际上被表示为指向不同内存区域的指针。

引用和复制

通常情况下,变量的引用赋值是符合我们预期的。如果你确实需要复制对象,那么可以使用下面的方法来实现。

浅拷贝

浅拷贝是指只对顶层进行复制操作,嵌套在内部的数据结构不会被复制。

  • 不带有任何参数的分片,例如:
代码语言:javascript
复制
>>> l = [1, 2, 3]
>>> l2=l[:]         # 复制
>>> l3=l[::]        # 复制
>>> l4=l            # 引用
>>> id(l)
138078511943584
>>> id(l2)
138078511943344
>>> id(l3)
138078511943184
>>> id(l4)
138078511943584

可以看到l和l4的id值是相同的,而使用不带有任何参数的分片进行赋值操作,结果是引用赋值。因此l2和l3的id值是新的,和l不相同。

  • 字典,集合,列表拥有的copy()方法 例如newX = X.copy(),这样就完成了把X复制到newX的操作。
  • 使用构造函数进行复制 内置类型实际上也都是类,可以使用它们构造函数完成复制操作。例如:list(l),dict(d),set(s)

深拷贝

不仅仅复制顶层,也会复制嵌套的数据结构。这将是完整的,完全的独立的复制。可以使用标准库的copy模块来做到深拷贝。

代码语言:javascript
复制
>>> import copy
>>> L1 = [1,2, [1,2]]
>>> L2 = copy.deepcopy(L1)
>>> L2
[1, 2, [1, 2]]
>>> id(L1[-1])
130018979552256
>>> id(L2[-1])
130018978665408

可以看到,使用copy.deepcopy()方法复制对象,会将嵌套的数据结构也进行复制。

深拷贝是极少出现的情况,如果你需要使用深拷贝,必须要慎重考虑。

比较

比较也是非常重要的一部分内容。因为对于不同分类而言,比较的方式是不同的。

深拷贝和比较

下面是一个例子,其中的a列表包含了它自己的引用。

代码语言:javascript
复制
>>> a = [1]
>>> a.append(a)
>>> a
[1, [...]]
>>> b = copy.deepcopy(a)    # 深拷贝a
>>> b
[1, [...]]
>>> a == b      # 对比a和b
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RecursionError: maximum recursion depth exceeded in comparison
>>> 

我们深拷贝了a,但是并没有触发堆栈溢出,这是因为深度拷贝函数 deepcopy 中会维护一个字典,记录已经拷贝的对象与其 ID。拷贝过程中,如果字典里已经存储了将要拷贝的对象,则会从字典直接返回。

代码语言:javascript
复制
# python3.8中的deepcopy源码
def deepcopy(x, memo=None, _nil=[]):
    """Deep copy operation on arbitrary Python objects.

    See the module's __doc__ string for more info.
    """

    if memo is None:
        memo = {}           # 空字典

    d = id(x)               # 查询x的id
    y = memo.get(d, _nil)   # 查询字典中是否存在id
    if y is not _nil:       # 如果存在这个id,直接返回对应的值
        return y

    cls = type(x)

    copier = _deepcopy_dispatch.get(cls)
    if copier is not None:
        y = copier(x, memo)
    else:
        if issubclass(cls, type):
            y = _deepcopy_atomic(x, memo)
        else:
            copier = getattr(x, "__deepcopy__", None)
            if copier is not None:
                y = copier(memo)
            else:
                reductor = dispatch_table.get(cls)
                if reductor:
                    rv = reductor(x)
                else:
                    reductor = getattr(x, "__reduce_ex__", None)
                    if reductor is not None:
                        rv = reductor(4)
                    else:
                        reductor = getattr(x, "__reduce__", None)
                        if reductor:
                            rv = reductor()
                        else:
                            raise Error(
                                "un(deep)copyable object of type %s" % cls)
                if isinstance(rv, str):
                    y = x
                else:
                    y = _reconstruct(x, memo, *rv)

    # If is its own copy, don't memoize.
    if y is not x:
        memo[d] = y
        _keep_alive(x, memo) # Make sure x lives at least as long as d
    return y

在执行 == 操作时,因为a中存储了自身的引用,会无限的递归与b比较,从而造成RecursionError异常,因为最大递归深度有一定的限制。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/11/12 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Python核心类型总结
    • 引用和复制
      • 浅拷贝
    • 深拷贝
      • 比较
        • 深拷贝和比较
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档