- 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表達式是什麼?怎麼寫?
- 見三