對(duì)於簡(jiǎn)單的控制語(yǔ)句來(lái)說(shuō),
x = 1
if x > 0:
print('true')
else:
print('false')
我們都知道當(dāng)判定 x > 0時(shí),else的語(yǔ)句是不會(huì)執(zhí)行的,
# filename test.py
def test1():
pass
# test1()
以下是我不知道正確與否的理解:
1,對(duì)於java而言,如果沒(méi)有對(duì)於test1() 這一行程式碼執(zhí)行對(duì)函數(shù)test1 的呼叫的話,那就整個(gè)程式基本上沒(méi)有意義,不會(huì)有記憶體分配,也不會(huì)有執(zhí)行
2,但是對(duì)於python 而言,會(huì)創(chuàng)建test1 函數(shù)對(duì)象,然後保存test1 中的一系列操作,這些操作不會(huì)被執(zhí)行,即使整個(gè)程序沒(méi)有對(duì)test1 有任何的調(diào)用操作,但是只要程序沒(méi)有結(jié)束,那麼test1就會(huì)一直存在於記憶體中。
至於原因,是函數(shù) test1 在程式執(zhí)行後,會(huì)成為目前模組對(duì)象,也就是 module __main__
的屬性。
3,而對(duì)於 ‘test1’ 這個(gè)函數(shù)名稱而言,他引用了這個(gè)函數(shù)對(duì)象,所以就算沒(méi)有呼叫該函數(shù),垃圾回收機(jī)制不會(huì)將其回收
# filename test.py
def test1():
def test2():
pass
# return test2()
# test1()
>>> class A(object):
a = []
def test1(self):
pass
@classmethod
def test2(cls):
print('cls.a', sys.getrefcount(cls.a))
print('cls.test1:', sys.getrefcount(cls.test1))
>>> A.test2()
('cls.a', 2)
('cls.test1:', 1)
>>> def test3():
def test4():
pass
>>> sys.getrefcount(test3)
2
>>> dir(test3)
['__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__doc__', '__format__', '__get__', '__getattribute__', '__globals__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name']
# sys.getrefcount(test4) NameError: name 'test4' is not defined
def test3():
def test4():
pass
return test4 # return test4()
建議以後這問(wèn)題拆成兩個(gè)不同問(wèn)題。
(1)沒(méi)有呼叫該函數(shù), Python還有另一個(gè)記憶體管理策略reference counting:「原理: 記錄一個(gè)物件被其他物件引用的次數(shù). 當(dāng)對(duì)這個(gè)物件的引用移除了, 引用計(jì)數(shù)也減小了.要是減到0了, 這個(gè)物件也就被釋放了」。所以我猜,應(yīng)該是在reference counting 時(shí)已經(jīng)回收了。
(2)有沒(méi)有呼叫就是看某個(gè)物件的參考是否移除了,還有是否有reference cycle,這裡的郵件討論串有一個(gè)類近的討論,不知道算不算回答了你這個(gè)問(wèn)題。