程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

30.Python面向對象(三)【類方法和靜態方法、動態綁定屬性和__slots__限制綁定、@property】

編輯:Python

目錄:

  • 每篇前言:
  • Python面向對象(三)
    • 1.1 類方法和靜態方法
      • 1.1.1 類方法
      • 1.1.2 靜態方法
      • 1.1.3 總結
    • 2.1 動態綁定與限制
      • 2.1.1 動態綁定屬性
      • 2.1.2 `__slots__` 限制綁定
    • 3.1 使用@property將方法變成屬性調用
    • 3.2 mro算法

每篇前言:

  • 作者介紹:【孤寒者】—CSDN全棧領域優質創作者、HDZ核心組成員、華為雲享專家Python全棧領域博主、CSDN原力計劃作者

  • 本文已收錄於Python全棧系列專欄:《Python全棧基礎教程》
  • 熱門專欄推薦:《Django框架從入門到實戰》、《爬蟲從入門到精通系列教程》、《爬蟲高級》、《前端系列教程》、《tornado一條龍+一個完整版項目》。
  • ​本專欄面向廣大程序猿,為的是大家都做到Python從入門到精通,同時穿插有很多很多習題,鞏固學習。
  • 訂閱專欄後可私聊進一千多人Python全棧交流群(手把手教學,問題解答);進群可領取Python全棧教程視頻 + 多得數不過來的計算機書籍:基礎、Web、爬蟲、數據分析、可視化、機器學習、深度學習、人工智能、算法、面試題等。
  • 加入我一起學習進步,一個人可以走的很快,一群人才能走的更遠!

Python面向對象(三)

1.1 類方法和靜態方法

1.1.1 類方法

  • 是類對象所擁有的方法,需要用修飾器@classmethod來標識其為類方法,對於類方法,第一個參數必須是類對象,一般以cls作為第一個參數(當然可以用其他名稱的變量作為其第一個參數,但是大部分人都習慣以’cls’作為第一個參數的名字,就最好用’cls’了),能夠通過實例對象和類對象去訪問。
# -*- coding: utf-8 -*-
""" __author__ = 小小明-代碼實體 """
class People(object):
country = 'china'
#類方法,用classmethod來進行修飾
@classmethod
def getCountry(cls):
return cls.country
p = People()
print(p.getCountry()) #可以用過實例對象引用
print(People.getCountry()) #可以通過類對象引用

  • 類方法還有一個用途就是可以對類屬性進行修改:
# -*- coding: utf-8 -*-
""" __author__ = 小小明-代碼實體 """
class People:
country = 'china'
#類方法,用classmethod來進行修飾
@classmethod
def getCountry(cls):
return cls.country
@classmethod
def setCountry(cls,country):
cls.country = country
p = People()
print(p.getCountry()) #可以用過實例對象引用
print(People.getCountry()) #可以通過類對象引用
p.setCountry('japan')
print(p.getCountry())
print(People.getCountry())

  • 結果顯示在用類方法對類屬性修改之後,通過類對象和實例對象訪問都發生了改變。

1.1.2 靜態方法

需要通過修飾器@staticmethod來進行修飾,靜態方法不需要多定義參數。

# -*- coding: utf-8 -*-
""" __author__ = 小小明-代碼實體 """
class People:
country = 'china'
# 靜態方法
@staticmethod
def getCountry():
return People.country
print(People.getCountry())

1.1.3 總結

從類方法和實例方法以及靜態方法的定義形式就可以看出來,類方法的第一個參數是類對象cls,那麼通過cls引用的必定是類對象的屬性和方法;而實例方法的第一個參數是實例對象self,那麼通過self引用的可能是類屬性、也有可能是實例屬性(這個需要具體分析),不過在存在相同名稱的類屬性和實例屬性的情況下,實例屬性優先級更高。靜態方法中不需要額外定義參數,因此在靜態方法中引用類屬性的話,必須通過類對象來引用

2.1 動態綁定與限制

2.1.1 動態綁定屬性

# -*- coding: utf-8 -*-
""" __author__ = 小小明-代碼實體 """
class Student(object):
pass
s = Student()
s.name = 'Michael' # 動態給實例綁定一個屬性
def set_age(self, age): # 定義一個函數作為實例方法
self.age = age
from types import MethodType
s.set_age = MethodType(set_age, s) # 給實例綁定一個方法
s.set_age(25) # 調用實例方法
print(s.age) # 測試結果

但是,給一個實例綁定的方法,對另一個實例是不起作用的:

s2 = Student() # 創建新的實例
s2.set_age(25)
Traceback (most recent call last):
File "D:/******/test.py", line 17, in <module>
s2.set_age(25)
AttributeError: 'Student' object has no attribute 'set_age'

為了給所有實例都綁定方法,可以給class綁定方法:

def set_score(self, score):
self.score = score
Student.set_score = MethodType(set_score, Student)

給class綁定方法後,所有實例均可調用:

s.set_score(100)
print(s.score)
s2 = Student()
s2.set_score(99)
print(s2.score)

通常情況下,上面的set_score方法可以直接定義在class中,但動態綁定允許我們在程序運行的過程中動態給class加上功能,這在靜態語言中很難實現。

2.1.2 __slots__ 限制綁定

  • 如果我們想要限制class的屬性,比如只允許對Student實例添加name和age屬性。
  • 為了達到限制的目的,Python允許在定義class的時候,定義一個特殊的__slots__變量,來限制該class能添加的屬性:
class Student(object):
__slots__ = ('name', 'age')
  • 然後,我們就試試:
s = Student() # 創建新的實例
s.name = 'xiaoming' # 綁定屬性'name'
s.age = 25 # 綁定屬性'age'
s.score = 99 # 綁定屬性'score'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute 'score'
  • 由於’score’沒有被放到__slots__中,所以不能綁定score屬性,試圖綁定score將得到AttributeError的錯誤。
  • 使用__slots__要注意,__slots__定義的屬性僅對當前類起作用,對繼承的子類是不起作用的:
    除非在子類中也定義__slots__,這樣,子類允許定義的屬性就是自身的__slots__加上父類的__slots__

3.1 使用@property將方法變成屬性調用

語法:

  • class property([fget[, fset[, fdel[, doc]]]])

參數:

  • fget – 獲取屬性值的函數
  • fset – 設置屬性值的函數
  • fdel – 刪除屬性值函數
  • doc – 屬性描述信息

返回新式類屬性。
將 property 函數用作裝飾器可以很方便的創建只讀屬性:

# -*- coding: utf-8 -*-
""" __author__ = 小小明-代碼實體 """
class Parrot(object):
def __init__(self):
self._voltage = 100000
@property
def voltage(self):
"""Get the current voltage."""
return self._voltage
  • 上面的代碼將 voltage() 方法轉化成同名只讀屬性的 getter 方法。
  • property 的 getter,setter 和 deleter 方法同樣可以用作裝飾器:
# -*- coding: utf-8 -*-
""" __author__ = 小小明-代碼實體 """
class C(object):
def __init__(self):
self._x = None
@property
def x(self):
"""I'm the 'x' property."""
return self._x
@x.setter
def x(self, value):
self._x = value
@x.deleter
def x(self):
del self._x

3.2 mro算法

  • mro順序/算法,目的是保證程序能夠按序執行。

mro順序的作用:

  • 保證所有的類在用(構造)他的時候只被用(構造)一次!
    保證多繼承的時候,每個類只出現一次。
    super().__init__() 相當於使用了mro。

前面說要講,但是在基礎階段如果深入講的話,我怕大家一時接受不了,所以就先這樣淺顯有個認識即可!有機會我會細講。


  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved