文章目录
1.Python 垃圾回收机制
垃圾回收机制是自动帮助我们管理内存,清理垃圾的一种工具
- 1. 引用计数
当一个对象的引用被创建或者复制时,对象的引用计数加1;
当一个对象的引用被销毁时,对象的引用计数减1;
当对象的引用计数减少为0时,就意味着对象已经没有被任何人使用了,可以将其所占用的内存释放了。
优点:
简单、直观
实时性,只要没有了引用就释放资源。
缺点:
维护引用计数需要消耗一定的资源,循环应用时,无法回收。也正是因为这个原因,才需要通过标记-清理和分代收集机制来辅助引用计数机制。
- 2.标记-清除
“标记-清除”不改动真实的引用计数,而是将集合中对象的引用计数复制一份副本,改动该对象引用的副本。对于副本做任何的改动,都不会影响到对象生命周期的维护。
- 3.分代回收
将系统中的所有内存块根据其存活时间划分为不同的集合,每一个集合就成为一个“代”,垃圾收集的频率随着“代”的存活时间的增大而减小。也就是说,活得越长的对象,就越不可能是垃圾,就应该减少对它的垃圾收集频率。那么如何来衡量这个存活时间:通常是利用几次垃圾收集动作来衡量,如果一个对象经过的垃圾收集次数越多,可以得出:该对象存活时间就越长。
2.内存泄露是什么?如何避免?
指由于疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,失去了对该段内存的控制,因而造成了内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。
有 del () 函数的对象间的循环引用是导致内存泄漏的主凶。
不使用一个对象时使用:del object 来删除一个对象的引用计数就可以有效防止内存泄漏问题。通过 Python 扩展模块 gc 来查看不能回收的对象的详细信息。可以通过 sys.getrefcount(obj) 来获取对象的引用计数,并根据返回值是否为 0 来判断是否内存泄漏。
3.如何打乱一个排好序的 list 对象 alist
import random
alist = [1,2,3,45,6]
random.shuffle(alist)
print(alist)
4.如何查找一个字符串中特定的字符?find 和 index 的差异?
1.find()方法:查找子字符串,若找到返回从0开始的下标值,若找不到返回-1。
2.index()方法:在字符串里查找子串第一次出现的位置,类似字符串的find方法,不过比find方法更好的是,如果查找不到子串,会抛出异常,而不是返回-1。
3.rfind和rindex方法用法和上面一样,只是从字符串的末尾(右侧)开始查找。
5.把 aaabbcccd 这种形式的字符串压缩成 a3b2c3d1 这种形式.
a="aaabbcccd"
b={}
c=""
for i in a:
b[i]=b.get(i,0)+1
print(b) # {'a': 3, 'b': 2, 'c': 3, 'd': 1}
for i,t in b.items():
c+=str(i)
c+=str(t)
print(c) # a3b2c3d1
6.enumerate 的作用是什么?
enumerate函数是将一个可迭代对象中元素,按元素顺序每个增加一个索引值,将其组成一个索引序列,利用它可以同时获得索引和值,这样做的目的是为了将一个可迭代对象中元素组成一个“索引,值”对便于后续操作。
alist = ['a','b','c']
for i in enumerate(alist):
print(i)
"""
(0, 'a')
(1, 'b')
(2, 'c')
"""
7.filter函数的作用
== 以pyhton3语法为例 ==
用于过滤序列,过滤掉不符合条件的元素,返回一个迭代器对象,如果要转换为列表,可以使用 list() 来转换。
该函数接收两个参数,第一个为函数,第二个为序列,序列的每个元素作为参数传递给函数进行判,然后返回 True 或 False,最后将返回 True 的元素放到新列表中。
示例:
def is_odd(n):
return n % 2 == 1
newlist = filter(is_odd, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
print(newlist) # <filter object at 0x0000023F8B1AC438>
for i in newlist:
print(i,end=' ') # 1 3 5 7 9
8.map()函数作用
map() 会根据提供的函数对指定序列做映射。
第一个参数 function 以参数序列中的每一个元素调用 function 函数,最终返回一个map类对象。
map() 函数语法:
map(function, iterable, …)
参数 function: 传的是一个函数名,可以是python内置的,也可以是自定义的。
参数 iterable: 传的是一个可以迭代的对象,例如列表,元组,字符串这样的。
这个函数的意思就是将function应用于iterable的每一个元素,结果返回map类对象,可转成列表查看。iterable后面还有省略号,意思就是可以传很多个iterable,如果有额外的iterable参数,并行的从这些参数中取元素,并调用function。如果一个iterable参数比另外的iterable参数要短,将以最短的iterable参数为基准组合其参数元素即返回列表长度与最短的对象相同。
示例:
def add(x, y, z):
return x, y, z
list1 = [1, 2, 3]
list2 = [1, 2, 3, 4]
list3 = [1, 2, 3, 4, 5]
res = map(add, list1, list2, list3)
print(res) # <map object at 0x00000172C93DCF28>
print(list(res)) # [(1, 1, 1), (2, 2, 2), (3, 3, 3)]
9.zip() 函数的作用
zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的对象,这样做的好处是节约了不少的内存。
我们可以使用 list() 转换来输出列表。
如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,利用 * 号操作符,可以将元组解压为列表。
zip 语法:
zip([iterable, …])
参数说明:
iterable – 一个或多个迭代器;
返回值是一个对象。
a = [1,2,3]
b = [4,5,6]
c = [4,5,6,7,8]
zipped1 = zip(a,b)
print(zipped1) # <zip object at 0x0000017A41896F48>
print(list(zipped1)) # [(1, 4), (2, 5), (3, 6)]
zipped2 = zip(a,c) # 元素个数与最短的列表一致
print(zipped2) # <zip object at 0x0000024B7F966FC8>
print(list(zipped2)) # [(1, 4), (2, 5), (3, 6)]
zipped3 = zip(*zip(a,b)) # 与 zip 相反,*zipped 可理解为解压,返回二维矩阵式
print(list(zipped3)) # [(1, 2, 3), (4, 5, 6)]
10.一行代码实现 9*9 乘法表
print('\n'.join(['\t'.join(["%2s*%2s=%2s"%(j,i,i*j) for j in range(1,i+1)]) for i in range(1,10)]))
%2s:字符串长度为2,当原字符串长度超过2时,按原长度打印。