類與物件深度問題與解決技巧(1)

2021-10-01 18:42:01 字數 3862 閱讀 7562

比如我們想定義乙個inttuple類,表示接受引數後,只取其中int型別,且大於0的,然後存為tuple型別

首先我們想到繼承父類tuple,然後修改一下:

class

inttuple

(tuple):

def__init__

(self,iterable)

:for i in iterable:

ifisinstance

(i,int

)and i>0:

super()

.__init__(i)

t = inttuple([1

,-2,

[1,2

],'abc'

])

而當我們這樣執行時,卻會發現報錯了,報錯顯示為typeerror: object.__init__() takes exactly one argument (the instance to initialize),

class

inttuple

(tuple):

def__init__

(self,iterable)

:print

(self)

t = inttuple([1

,-2,

[1,2

],'abc'

])

此時我們將上述迴圈刪除,直接列印,會發現此時,直接輸出的self就是(1,-2,[1,2],『abc』)

此時其實我們應該使用__new__方法,我們可以這樣理解他:__init__()負責將類例項化,__new__()負責製造這樣的乙個例項物件。

然後我們將**改為:

class

inttuple

(tuple):

def__new__

(cls,

*args,

**kwargs)

: f =

(i for i in iterable if

isinstance

(i,int

)and i >0)

return

super()

.__new__(cls, f)

t = inttuple([1

,-2,

[1,2

],'abc'])

print

(t)

此時我們再執行,即可得到我們需要的。

在例項情況多的情況下我們如何降低這些大量例項的記憶體開銷?

我們先定義兩個類

class

player1

(object):

def__init__

(self, uid, name, status=

0, level=1)

: self.uid = uid

self.name = name

self.status = status

self.level = level

class

player2

(object):

__slots__ =

('uid'

,'name'

,'status'

,'level'

)def

__init__

(self, uid, name, status=

0, level=1)

: self.uid = uid

self.name = name

self.status = status

self.level = level

p1 = player1(

'0001'

,'dog'

) p2 = player2(

'0002'

,'cat'

)

__slots__來修飾屬性的話可以減少其記憶體開銷,那麼他具體是怎麼實現的呢。

我們分別用dir()檢視p1,p2的內部屬性,發現相差的有__dict__

__dict__指的是動態繫結屬性,即

p1.x =

3p2.y =

4

執行上述兩條操作的話,第一條是可以執行的,因為類player1無__slots__,可以進行這些動態繫結屬性的操作,而第二條不行,類player2只能修改uid,name,status,level這四個屬性。

而想要查詢記憶體使用情況的話,我們可以匯入sys庫,使用其中的getsizeof函式,

import sys

print

(sys.getsizeof(p1.__dict__)

)

即可

我們在用python執行檔案時應該都寫過with open(『***.txt』, 『r』) as f:這種語句,這種帶with的open語句自帶關閉就不需要我們再自行 f.close()去關閉,那麼with 語句能不能對類這些進行操作呢?

class

sample

(object):

deftext

(self)

:print

('111'

)with sample(

)as s:

s.text(

)

當我們這樣執行時,會報錯,提示我們缺少__enter__,而我們加上__enter__後又提示了我們缺少__exit__,當我們再把__exit__後,誒,就發現ok了。

class

sample

(object):

# 獲取資源

def__enter__

(self)

:print

('start'

)return self

deftext

(self)

:print

('111'

)# 釋放資源

def__exit__

(self, exc_type, exc_val, exc_tb)

:# 異常類

print

(exc_type)

# 異常值

print

(exc_val)

# 追蹤資訊

print

(exc_tb)

print

('end'

)with sample(

)as s:

s.text(

)

講到這就得在提到python中的上下文管理器

contextlib簡化上下文管理器

import contextlib

@contextlib.contextmanager

deffile_open

(filename)

:# *** __enter__ 函式

print

('file open'

)yield

# __exit__ 函式

print

('file close'

)with file_open(

'demo.txt'

)as f:

print

('file operation'

)

在匯入contextlib庫後使用裝飾器@contextlib.contextmanager

在yield{}上面的部分就相當於上個例子中的__enter__函式

而在yield{}下面的部分就相當於上個例子中的__exit__函式

在with部分即為執行的內容

類與物件深度問題

defnew cls 建立乙個類物件,自動執行,當期執行時如果沒有創造物件並且返回則不會執行 init 方法,因為 init 方法是只有物件被建立時才會自動呼叫。一般init會自動呼叫是因為物件被自動建立了,所有類的父類object有這個功能,噹噹你執行了 new 之後object不會在執行,所以假...

類與物件深度問題與解決技巧 3 上下文管理器

首先寫乙個簡單的異常處理 try f open demo.txt w 丟擲異常 raise typeerror 捕獲異常 except typeerror as e print typeerror f.close except valueerror as e print valueerror f.c...

類與物件(1)

類與物件 1 主函式 public class text 這裡定義乙個人的類 class person public void setage int age 建構函式做初始化 public person 當沒有建構函式時,計算機會預設乙個無引數建構函式 當程式設計師寫了乙個有引數的建構函式,系統就不...