Python中深浅拷贝 垃圾回收与 super继承(六)

1 python拷贝

深拷贝,浅拷贝 与引用三者的区别

import copy
a = [1, 2, 3, 4, [‘a‘, ‘b‘]]  #原始对象

b = a  #赋值,传对象的引用
c = copy.copy(a)  #对象拷贝,浅拷贝
d = copy.deepcopy(a)  #对象拷贝,深拷贝

a.append(5)  #修改对象a
a[4].append(‘c‘)  #修改对象a中的[‘a‘, ‘b‘]数组对象

print(‘a = ‘, a)
print( ‘b = ‘, b)
print( ‘c = ‘, c)
print(‘d = ‘, d)

输出结果:
a =  [1, 2, 3, 4, [‘a‘, ‘b‘, ‘c‘], 5]  #a执行两次值追加操作
b =  [1, 2, 3, 4, [‘a‘, ‘b‘, ‘c‘], 5]  #赋值是对象的引用,b指向仍然是a,因此与a内容保持一致
c =  [1, 2, 3, 4, [‘a‘, ‘b‘, ‘c‘]]  #对象的浅拷贝外部list重新生成新的空间,但是嵌套数组的内存地址不变
d =  [1, 2, 3, 4, [‘a‘, ‘b‘]]  #深拷贝是所有的数组都新生成一个内存空间,与原来的脱离关系

2 python的垃圾回收机制

Python GC主要使用引用计数(reference counting)来跟踪和回收垃圾。在引用计数的基础上,通过“标记-清除”(mark and sweep)解决容器对象可能产生的循环引用问题,通过“分代回收”(generation collection)以空间换时间的方法提高垃圾回收效率。

1 引用计数

? PyObject是每个对象必有的内容,其中ob_refcnt就是做为引用计数。当一个对象有新的引用时,它的ob_refcnt就会增加,当引用它的对象被删除,它的ob_refcnt就会减少.引用计数为0时,该对象生命就结束了。

优点:

  1. 简单
  2. 实时性

缺点:

  1. 维护引用计数消耗资源
  2. 循环引用
2 标记-清除机制

基本思路是先按需分配,等到没有空闲内存的时候从寄存器和程序栈上的引用出发,遍历以对象为节点、以引用为边构成的图,把所有可以访问到的对象打上标记,然后清扫一遍内存空间,把所有没标记的对象释放。

3 分代技术

分代回收的整体思想是:将系统中的所有内存块根据其存活时间划分为不同的集合,每个集合就成为一个“代”,垃圾收集频率随着“代”的存活时间的增大而减小,存活时间通常利用经过几次垃圾回收来度量。

Python默认定义了三代对象集合,索引数越大,对象存活时间越长。

举例:

当某些内存块M经过了3次垃圾收集的清洗之后还存活时,我们就将内存块M划到一个集合A中去,而新分配的内存都划分到集合B中去。当垃圾收集开始工作时,大多数情况都只对集合B进行垃圾回收,而对集合A进行垃圾回收要隔相当长一段时间后才进行,这就使得垃圾收集机制需要处理的内存少了,效率自然就提高了。在这个过程中,集合B中的某些内存块由于存活时间长而会被转移到集合A中,当然,集合A中实际上也存在一些垃圾,这些垃圾的回收会因为这种分代的机制而被延迟。

3 python中 is与 == var与let

is比较的是两者的内存地址 ==基本比较的是两者的数值

is判定
    判定值相等,内存地址也相等
a = 10
b = 10
a is b
Ture    常用的1-256计算机共用一个内存地址

a = 9999999
b = 9999999
a is b
False    数值较大的数类似长整型,计算机会生成新的内存地址

var与let
    var 定义的变量可以重新被定义
    let 定义的变量不能重新被定义

4 Python中 read readline readlines

read() 每次读取整个文件,它通常用于将文件内容放到一个字符串变量中

readline 读取下一行,使用生成器方法,返回字符串的对象

readlines 读取整个文件到一个迭代器以供我们遍历

#read
f = open("a.txt")
lines = f.read()
print(lines)
print(type(lines))
f.close()
#输出
# hello
# python!
<type ‘str‘> #字符串类型  

#readline
f = open("a.txt")
line = f.readline()
print(type(line))
while line:
  print line,
  line = f.readline()
f.close()
#输出
#<type ‘str‘>
<type ‘str‘> #字符串类型
# hello
# python!

#readlines
f = open("a.txt")
lines = f.readlines()
print(type(lines))
for line in lines:
   print(line)
f.close()
#输出
<type ‘list‘>
# hello
# python!

5 python2 与 python3 的区别

contents python3 说明
print函数 python3 打印带括号
整除 / 可以得到浮点数
Unicode Unicode (utf-8) 字符串
xrange模块 统一使用range,并新增__contains__
Raising exceptions/Handling exceptions raise 与 as 关键字
next()函数 只保留next(), .next() 抛出属性异常
for循环 for 循环变量不会再导致命名空间泄漏
比较不可排序类型 python不支持不同类型的比较
输入input 只允许input,取消了raw_input

6 Python必须学会的super

(1) super() 继承方法

在类的继承中,如果重定义某个方法,该方法会覆盖父类的同名方法,但有时,我们希望能同时实现父类的功能,这时,我们就需要调用父类的方法了,可通过使用 super 来实现

class Animal(object):   #Animal为父类
    def __init__(self, name):
        self.name = name
    def greet(self):
        print ‘Hello, I am %s.‘ % self.name

class Dog(Animal):  #Dog为子类
    def greet(self):  #Dog重定义了greet方法并继承了父类的方法
        super(Dog, self).greet()   # Python3 可使用 super().greet()
        print ‘WangWang...‘

>>> dog = Dog(‘dog‘)  #实例化
>>> dog.greet()   #调用greet方法
Hello, I am dog.
WangWang..

(2) super初始化

super 的一个最常见用法可以说是在子类中调用父类的初始化方法

class Base(object):
    def __init__(self, a, b):
        self.a = a
        self.b = b

class A(Base):
    def __init__(self, a, b, c):
        super(A, self).__init__(a, b)  # 初始化子类继承父类super(子类名,self).__init__(父类参数)
        self.c = c
    

Python3 可使用 super().__init__(a, b),这样子类继承父类的属性的同时,有保持了自身独有的属性.

(3) 深入super

super其实与父类没有实质的关联

class Base(object):
    def __init__(self):
        print "enter Base"
        print "leave Base"

class A(Base):  #继承base
    def __init__(self):
        print "enter A"
        super(A, self).__init__()
        print "leave A"

class B(Base):  #继承base
    def __init__(self):
        print "enter B"
        super(B, self).__init__()
        print "leave B"

class C(A, B):  #多重继承自A,B
    def __init__(self):
        print "enter C"
        super(C, self).__init__()  #super第一个参数可以是继承链中任意类名字
        print "leave C"

#输出
>>> c = C()
enter C
enter A
enter B
enter Base
leave Base
leave B
leave A
leave C

按我们的理解,enter A下面输出应该是基类base中enter base,为什么是enter B ?? 原因是super跟父类没有什么关联,因此执行的顺序是A-->B-->Base

执行过程是:

初始化C()时,先会去调用A的构造方法中的 super(A, self).__init__()super(A, self)返回当前类的继承顺序中A后的一个类B;然后再执行super(B,self).__init()__,这样顺序执行下去。

super方法可以看出:super()的第一个参数可以是继承链中任意一个类的名字,

1 如果是本身就会依次继承下一个类;

2 如果是继承链里之前的类便会无限递归下去;

3 如果是继承链里之后的类便会忽略继承链汇总本身和传入类之间的类;

原文地址:https://www.cnblogs.com/why957/p/9207016.html

时间: 2024-08-01 00:25:54

Python中深浅拷贝 垃圾回收与 super继承(六)的相关文章

python闭包&amp;深浅拷贝&amp;垃圾回收&amp;with语句

1.1 闭包 1.闭包概念 1. 在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用,这样就构成了一个闭包 2. 一般情况下,在我们认知当中,如果一个函数结束,函数的内部所有东西都会释放掉,还给内存,局部变量都会消失. 3. 但是闭包是一种特殊情况,如果外函数在结束的时候发现有自己的临时变量将来会在内部函数中用到,就把这个临时变量绑定给了内部函数,然后自己再结束.   2.闭包特点 1. 必须有一个内嵌函数 2. 内嵌函数必须引用外部函数中的变量 3

python中深浅拷贝

在python中,对象赋值实际上是对象的引用.当创建一个对象,然后把它赋给另一个变量的时候,python并没有拷贝这个对象,而只是拷贝了这个对象的引用 一般有三种方法, alist=[1,2,3,["a","b"]] (1)直接赋值,默认浅拷贝传递对象的引用而已,原始列表改变,被赋值的b也会做相同的改变 >>> b=alist>>> print b[1, 2, 3, ['a', 'b']]>>> alist.ap

针对Python的深浅拷贝问题

前些天做了个小程序,遇到了Python的深浅拷贝问题 感觉自己基础不够扎实,就翻了翻教程,真的是非常基础的知识...(各位大佬下手轻点2333) 下面简单说说: 首先有个字典a 1 a = {'A':1,'B':2,'C':3,'D':4} 然后我们把它赋值给另外一个空字典b 1 b = {} 2 b = a 当我们输出b时,可以看到a和b直观上看好像是相等了 按照常理,我们会认为a和b现在是两个值相等的字典,如果我们对其中一个操作,另外一个应该不会受到影响才对,所以我们试一下: 我们尝试删除b

python之深浅拷贝(基础四)

第六章python之深浅拷贝(基础四) 6.1 小数据池 小数据池就是Python中一种提高效率的方式,固定数据类型使用同一个内存地址 小数池 -- 支持: str,int,bool a = 1 b = 1 id 查看空间的内存地址 获取开辟空间的一种地址 print(id(a)) print(id(b)) 小数据池数字支持范围: -5 ~ 256 *记住 a = 300 b = 300 print(id(a)) print(id(b)) 代码块: 一个文件,一个模块,一个函数,一个类,终端中每

JavaScript中的的垃圾回收机制

JavaScript中的的垃圾回收机制 javascript的垃圾回收原理 (1).在javascript中,如果一个对象不再被引用,那么这个对象就会被GC回收: (2).如果两个对象互相引用,而不再被第3者所引用,那么这两个互相引用的对象也会被回收.

【python之路13】python的深浅拷贝

深浅拷贝 一.数字和字符串 对于 数字 和 字符串 而言,赋值.浅拷贝和深拷贝无意义,因为其永远指向同一个内存地址. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import copy # ######### 数字.字符串 ######### n1 = 123 # n1 = "i am alex age 10" print(id(n1)) # ## 赋值 ## n2 = n1 print(id(n2)) # ## 浅拷贝 ## n2 = copy.copy(

python 赋值 深浅拷贝

深浅拷贝 一.数字和字符串 对于 数字 和 字符串 而言,赋值.浅拷贝和深拷贝无意义,因为其永远指向同一个内存地址. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import copy # ######### 数字.字符串 ######### n1 = 123 # n1 = "i am alex age 10" print(id(n1)) # ## 赋值 ## n2 = n1 print(id(n2)) # ## 浅拷贝 ## n2 = copy.copy(

python笔记--深浅拷贝

深浅拷贝 1.对于数字.字符串和元组而言,赋值.浅拷贝和深拷贝无意义,因为其永远指向同一个内存地址,例如: >>> n1=123 >>> import copy >>> n2=n1    #赋值 >>> print(id(n2)) 31427456 >>> print n2 123 >>> n2=copy.copy(n1)    #浅拷贝 >>> print(id(n2)) 314

我要学python之深浅拷贝原理

前言 在c++中参数传递有两种形式:值传递和引用传递.这两种方式的区别我不在此说,自行补上,如果你不知道的话.我先上python代码,看完我们总结一下,代码如下: # copy module import import copy # number and string a = 12 a1 = a a2 = copy.copy(a) a3 = copy.deepcopy(a) # look addr print("==========number=======") print(id(a)