__slots__
初肉,封裝屬性
__slots__
常見的的用法是用來封裝屬性,限制對實(shí)例胡亂添加屬性。然而他還有一個重要的作用是可以減少內(nèi)存使用垃它。
當(dāng)定義了__slots__
屬性時碱妆,Python就會針對實(shí)例采用一種更加緊湊的內(nèi)部表示肉盹。不在讓每個實(shí)例都創(chuàng)建一個__dict__
字典,現(xiàn)在的實(shí)例是圍繞著一個固定長度的小型數(shù)組來構(gòu)建的疹尾,這和一個元組或者列表很相似上忍。在__slots__
中列出的屬性名會在內(nèi)部映射到這個數(shù)組的特定索引上。使用__slots__
所帶來的副作用是我們沒法在對實(shí)例添加任何新的屬性了——我們被限制在只允許使用__slots__
中列出的那些屬性名纳本。
class Date(object):
__slots__ = ['year', 'month', 'day']
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
d = Date('2017', '11', '21')
print(d.year+'-'+d.month+'-'+d.day)
#輸出
2017-11-21
#設(shè)置屬性hour
d.hour = '19'
#報錯
AttributeError: 'Date' object has no attribute 'hour'
@property窍蓝,創(chuàng)建可管理的屬性
在對實(shí)例屬性的獲取和設(shè)定上,如果希望能夠增加一些額外的處理過程(如類型檢查或者驗(yàn)證)繁成,一種簡單的方式是將其定義為property(也即把類中定義的函數(shù)當(dāng)做一種屬性來使用)吓笙。
class A(object):
def __init__(self, name):
self.name = name
# 將name定義為property屬性,此處增加了增加了對name屬性的修飾
@property
def name(self):
return 'my name is: ' + self._name
# 將可選方法setter綁定到name屬性上,設(shè)定屬性時做類型檢查
@name.setter
def name(self, value):
if not isinstance(value, str):
raise TypeError('Expect a string')
self._name = value
# 將可選方法deleter綁定到name屬性上巾腕,此處設(shè)置為屬性不可刪除
@name.deleter
def name(self):
raise AttributeError('Cannot delet attribute!')
a = A('a')
a.name = 'shexuan'
print(a.name)
#輸出
my name is: shexuan
#設(shè)置name屬性為int(10)
a.name = 10
#報錯
TypeError: Expect a string