- python的垃圾回收是什么 ?
- python的迭代器是什么?
- python 的return与yeild的区别?
- python的全局变量调用顺序?
- python的lambda表达式是什么?怎么写?
- python的多线程与多进程是怎么回事?
目录
3.2 编写跳转表(jump table)行为的列表或者字典
一、垃圾回收
1.1 垃圾回收
一些程序中,会出现内存泄露的问题。比如c++的malloc之后忘记了free。
内存泄漏没有将相应的内存释放给操作系统,导致无用内存越来越多。
所以一些语言引入了垃圾回收机制,例如ruby和java,python等
1.2 整数对象池及intern
https://www.cnblogs.com/alexzhang92/p/9416692.html
整数对象池
- 小整数对象池,数值范围是[-5, 257],在一个 Python 的程序中,所有位于这个范围内的整数使用的都是同一个对象.
- 大整数对象池:大整数均创建一个对象。
intern机制
几个相同的变量,例如下面:
a1 = "HelloWorld"
a2 = "HelloWorld"
a3 = "HelloWorld"
a4 = "HelloWorld"
a5 = "HelloWorld"
a6 = "HelloWorld"
a7 = "HelloWorld"
a8 = "HelloWorld"
a9 = "HelloWorld"
只有9个,但是用下面
print(sys.getrefcount(a1))会输出12,不知是什么原因
intern机制
- 让他只占用一个”HelloWorld”所占的内存空间。靠引用计数去维护何时释放。
1.3 引用计数
通过引用计数可以实现循环引用。
- 每个对象有新的引用的时候,其引用计数会增加,删除的时候,引用计数会减少。
- 当引用计数为0的时候,内存释放。
- 优点:简单,实时性。实时性还带来一个好处:处理回收内存的时间分摊到了平时。
导致引用计数+1的情况
- 对象被创建,例如a=23
- 对象被引用,例如b=a
- 对象被作为参数,传入到一个函数中,例如func(a)
- 对象作为一个元素,存储在容器中,例如list1=[a,a]
导致引用计数-1的情况
- 对象的别名被显式销毁,例如del a
- 对象的别名被赋予新的对象,例如a=24
- 一个对象离开它的作用域,例如f函数执行完毕时,func函数中的局部变量(全局变量不会)
- 对象所在的容器被销毁,或从容器中删除对象
查看一个对象的引用计数
import sys
a = "hello world"
sys.getrefcount(a)
#输出是4
可以查看a对象的引用计数,但是比正常计数大1,因为调用函数的时候传入a,这会让a的引用计数+1
循环引用会导致内存泄漏:
list1 = []
list2 = []
list1.append(list2)
list2.append(list1)
二、python迭代器与生成器
https://www.runoob.com/python3/python3-iterator-generator.html
2.1 迭代器
迭代是Python最强大的功能之一,是访问集合元素的一种方式。
- 迭代器是一个可以记住遍历的位置的对象。
- 迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
- 迭代器有两个基本的方法:iter() 和 next(),StopIteration
- 字符串,列表或元组对象都可用于创建迭代器
#!/usr/bin/python3
list=[1,2,3,4]
it = iter(list) # 创建迭代器对象
for x in it:
print (x, end=" ")
运行结果:
1 2 3 4
2.2 生成器
在 Python 中,使用了 yield 的函数被称为生成器(generator)。
- 跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。
- 在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。
- 调用一个生成器函数,返回的是一个迭代器对象。
import sys
def fibonacci(n): # 生成器函数 - 斐波那契
a, b, counter = 0, 1, 0
while True:
if (counter > n):
return
yield a
a, b = b, a + b
counter += 1
f = fibonacci(10) # f 是一个迭代器,由生成器返回生成
while True:
try:
print (next(f), end=" ")
except StopIteration:
sys.exit()
输出:
0 1 1 2 3 5 8 13 21 34 55
三、lambda表达式
https://www.cnblogs.com/mxh1099/p/5386529.html
lambda的一般形式是关键字lambda后面跟一个或多个参数,紧跟一个冒号,以后是一个表达式。
- lambda是一个表达式而不是一个语句。
- 它能够出现在Python语法不允许def出现的地方。
- 作为表达式,lambda返回一个值(即一个新的函数)。
- lambda用来编写简单的函数,而def用来处理更强大的任务。
3.1 使用
f = lambda x, y, z :x+y+z
print(f(1,2,3)) #6
输出:6
3.2 编写跳转表(jump table)行为的列表或者字典
L = [lambda x: x+2, lambda x: x*2, lambda x: x**2]
print("L=", L[0](1), L[1](2), L[2](3))
# L= 3 4 9
D = {"d1": lambda x: x**1, "d2": lambda x: x**2, "d3": lambda x: x**3 }
print("D=", D["d1"](2), D["d2"](2), D["d3"](2))
# D= 2 4 8
四、python的多线程
4.1 进程与线程
线程在执行过程中与进程还是有区别的。
- 每个独立的进程有一个程序运行的入口、顺序执行序列和程序的出口。
- 线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
- 每个线程都有他自己的一组CPU寄存器,称为线程的上下文,该上下文反映了线程上次运行该线程的CPU寄存器的状态。
- 指令指针和堆栈指针寄存器是线程上下文中两个最重要的寄存器,线程总是在进程得到上下文中运行的,这些地址都用于标志拥有线程的进程地址空间中的内存。
- 线程可以被抢占(中断)。
- 在其他线程正在运行时,线程可以暂时搁置(也称为睡眠) -- 这就是线程的退让。
4.2 创建线程
Python中使用线程有两种方式:函数或者用类来包装线程对象。
函数式:调用thread模块中的start_new_thread()函数来产生新线程。语法如下:
thread.start_new_thread ( function, args[, kwargs] )
参数说明:
- function - 线程函数。
- args - 传递给线程函数的参数,他必须是个tuple类型。
- kwargs - 可选参数。
import thread
import time
# 为线程定义一个函数
def print_time( threadName, delay):
count = 0
while count < 5:
time.sleep(delay)
count += 1
print "%s: %s" % ( threadName, time.ctime(time.time()) )
# 创建两个线程
try:
thread.start_new_thread( print_time, ("Thread-1", 2, ) )
thread.start_new_thread( print_time, ("Thread-2", 4, ) )
except:
print "Error: unable to start thread"
while 1:
pass
五、python的zip函数
zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。
注意:
- 一 一对应的返回
- 只返回最小的list的个数
>>>a = [1,2,3]
>>> b = [4,5,6]
>>> c = [4,5,6,7,8]
>>> zipped = zip(a,b) # 打包为元组的列表
[(1, 4), (2, 5), (3, 6)]
>>> zip(a,c) # 元素个数与最短的列表一致
[(1, 4), (2, 5), (3, 6)]
>>> zip(*zipped) # 与 zip 相反,*zipped 可理解为解压,返回二维矩阵式。
# 注意,加一个星号表示元组格式
[(1, 2, 3), (4, 5, 6)]
思考程序:
A=[1,2,3]
B=[3,2,1,5,3,2]
zipped=zip(A,B)
for item in zipped:
print(item)
输出:
(1, 3)
(2, 2)
(3, 1)
六、__del__:
6.1 del作用
python的del函数,
- 与 __init__() 方法对应的是 __del__() 方法
- __init__() 方法用于初始化 Python 对象
- 而 __del__() 则用于销毁 Python 对象
- 即在任何 Python 对象将要被系统回收之时,系统都会自动调用该对象的 __del__() 方法。
6.2 程序及结果
class Item:
def __init__ (self, name, price):
self.name = name
self.price = price
# 定义析构函数
def __del__ (self):
print('del删除对象')
# 创建一个Item对象,将之赋给im变量
im = Item('鼠标', 29.8)
x = im # ①
# 打印im所引用的Item对象
del im
print('end program')
运行结果:
end program
del删除对象
因为有x=im语句,因此只要X不被释放,则不会调用del函数。
如果想要调用del函数,需要如下两种方法:
- 删掉x=im语句
- 加入代码 del x
七、上面问题及答案
python的垃圾回收是什么 ?
- 见一、大整数池,小整数池,引用技术,循环引用的内存泄漏。
python的迭代器是什么?
python 的return与yeild的区别?
- 见二,迭代器是针对集合元素的一种遍历。生成器是加了yeild的函数。可以看作迭代器,用next继续调用
python的lambda表达式是什么?怎么写?
- 见三