此篇淺談面向對象理論中的幾個技巧
1:@property
- @property 是一個用在類中的裝飾器,其作用是把本來在類中定義的方法變成屬性,並且在實例化對象中也可以通過屬性的方式調用
- 來看一段代碼
class cat(object):
def __init__(self, name, age):
self.name = name
self.__age = age
def show_info(self):
print('我叫{},年齡是{}歲。'.format(self.name, self.__age))
if __name__ == '__main__':
cat_black = cat('小黑', 2)
cat_black.show_info()
可以看到這是一個很簡單的例子。我們首先定義了一個cat類,然後實例化一隻黑貓。黑貓想顯示信息,所以調用了類中提供的方法show_infor()
- 接下來,在看看使用了@property的用法
class cat(object):
def __init__(self, name, age):
self.name = name
self.__age = age
# 將方法變成屬性,直接調用
@property
def show_info(self):
print('我叫{},年齡是{}歲。'.format(self.name, self.__age))
if __name__ == '__main__':
cat_black = cat('小黑', 2)
cat_black.show_info
爲什麼要使用 @property
- 這樣本來作爲方法的show_info就變成了屬性,可以通過調用屬性的方式來調用方法
2:@setter
- 首先拿一段代碼過來
class cat(object):
def __init__(self, name, age):
self.name = name
self.__age = age
if __name__ == '__main__':
cat_black = cat('小黑', 2)
可以看到這是一個很簡單的cat類,並且實例化了一隻黑貓。
在構造函數中,我們把age屬性設置成了私有屬性,即在age前面加上了兩個下劃線。
所謂私有屬性,即不能通過以下方式獲取和設置的屬性
print(cat_black.name) # 這裏打印出在構造時設置的名稱,小黑
cat_black.name = '小白'# 把名字屬性設置成 小白
print(cat_black.name)# 這裏可以直接取到name屬性,即小白
- 但如果我們想要修改私有屬性改怎麼辦呢?這時就可以使用@setter
class cat(object):
def __init__(self, name, age):
self.name = name
self.__age = age
# 提供在外部通過使用非私有屬性的方法獲得屬性值
@property
def age(self):
print(self.__age)
# 提供在外部通過使用非私有屬性的方法設置屬性值
@age.setter
def age(self, value):
# 通過這種方式,也可以在設置值時對值進行判斷
if not isinstance(value, int):
print("年齡只能是整數")
return 0
if 0 > value or value > 100:
print('年齡只能在0-100之間')
return 0
self.__age = value
if __name__ == '__main__':
cat_black = cat('小黑', 2)
print(cat_black.age)# 輸出2
cat_black.age = 9 #對於私有屬性可以通過像普通屬性一樣的方法進行操作
print(cat_black.age)# 輸出9
在這段代碼中我們可以看到,首先定義了一個age方法,並裝飾了上文提到的@property裝飾器。該裝飾器使得擁有訪問私有屬性功能的方法變成了屬性,這樣就可以直接使用屬性的方式調用該方法,保持了私有屬性和普通屬性調用方法的一致
- 對age進行更改。依舊參考上面的代碼,在定義的第二個age方法前使用了 @age.setter 裝飾器,該裝飾器使得私有屬性age除了被訪問,也具有了被修改的功能
爲什麼要使用 @setter
- 對於取age屬性和修改age屬性的方法定義爲同名,更使得代碼的格式保持了統一,age的使用實現了多態
- 使用 @setter 還可以比普通屬性實現賦值時,對增加對於值的判斷功能。觀察上面的代碼,可以發現age的值被定義在了int類型和0-100之間才能正常賦值
3:@staticmethod
靜態方法,既可以通過類直接調用方法
class cat(object):
tag = '貓科動物'
def __init__(self, name):
self.name = name
@staticmethod
def breath():
"""呼吸"""
print('貓都會呼吸')
if __name__ == '__main__':
cat_black = cat('小黑') # 實例化一個對象。正常運行
cat_black.breath() # 使用對象調用方法。正常運行
cat.breath() # 使用類調用方法。正常運行
爲什麼要使用 @staticmethod
觀察以下幾段代碼
- 一:
class cat(object):
tag = '貓科動物'
def __init__(self, name):
self.name = name
def breath(self):
"""呼吸"""
print('貓都會呼吸')
if __name__ == '__main__':
cat_black = cat('小黑') # 實例化一個對象。正常運行
cat_black.breath() # 使用對象調用方法。正常運行
cat.breath() # 使用類調用方法。 !報錯!
- 二:
class cat(object):
tag = '貓科動物'
def __init__(self, name):
self.name = name
def breath():
"""呼吸"""
print('貓都會呼吸')
if __name__ == '__main__':
cat_black = cat('小黑') # 實例化一個對象。正常運行
cat_black.breath() # 使用對象調用方法。 !報錯!
cat.breath() # 使用類調用方法。正常運行
結合上面的三段代碼,可以發現如果想要讓類和對象能採用相對的代碼格式使用同一個方法的時候,就需要使用 @staticmethod 裝飾器來裝飾這個方法
4:@classmethod
類的方法,即對象不能調用的方法(理論上)
class cat(object):
tag = '貓科動物'
def __init__(self, name):
self.name = name
def show_info(self):
print('類的屬性:{},實例的屬性:{}.'.format(self.tag, self.name))
@classmethod
def test(cls, name):
return cat(name)
- 通過觀察代碼,在 @classmate 修飾的方法中,原本的self變成了cls,表示由對象變成了類,那麼這個方法該怎麼用呢?
if __name__ == '__main__':
cat_black = cat('小黑') # 正常的析構方法
cat_black.show_info()
cat_daju = cat.test('大橘') # 使用類調用test方法
cat_daju.show_info()
c_xiaohua = cat_daju.test('小花') # 使用對象去調用類的方法
c_xiaohua.show_info()
爲什麼要使用 @classmethod
- 不知道
5:slots
slots 爲類設置一個靜態的屬性列表,即不允許出現其他的屬性和方法
class cat(object):
def __init__(self, name, age):
self.name = name
self.age = age
def eat():
print('我喜歡吃魚')
if __name__ == '__main__':
cat_black = cat('小黑',2)
cat_black.color = '黑色'
cat_black.eat = eat
- 可以看到在上面的代碼中,我們向cat類中添加了一個本來不存在的屬性color
- 同時還添加了一個名爲eat的方法
class cat(object):
__slots__ = ('name', 'age')
def __init__(self, name, age):
self.name = name
self.age = age
def eat():
print('我喜歡吃魚')
if __name__ == '__main__':
cat_black = cat('小黑',2)
cat_black.color = '黑色' # !報錯!
cat_black.eat = eat # !報錯!
爲什麼要使用 slots
- 限制對於類的隨意修改
- 節省內存空間