python基础知识及应用(三)垃圾回收|迭代器与生成器| lambda表达式|多线程| zip | del

  • python的垃圾回收是什么 ?
  • python的迭代器是什么?
  • python 的return与yeild的区别?
  • python的全局变量调用顺序?
  • python的lambda表达式是什么?怎么写?
  • python的多线程与多进程是怎么回事?

目录

一、垃圾回收

1.1 垃圾回收

1.2 整数对象池及intern

1.3 引用计数

二、python迭代器与生成器

2.1 迭代器

2.2 生成器

三、lambda表达式

3.1 使用

3.2 编写跳转表(jump table)行为的列表或者字典

四、python的多线程

4.1 进程与线程

4.2 创建线程

五、python的zip函数

六、__del__:

6.1 del作用

6.2 程序及结果

七、上面问题及答案


一、垃圾回收

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

五、pythonzip函数

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表达式是什么?怎么写?

  • 见三

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

发布了210 篇原创文章 · 获赞 584 · 访问量 30万+

猜你喜欢

转载自blog.csdn.net/weixin_36474809/article/details/100182979
今日推荐