Python類的成員 一、細分類的組成成員 類大致分為兩大部分: 1. 靜態屬性 2. 動態方法 每個區域詳細劃分又可以分為: 二、類的私有成員 對於每一個類的成員而言都有兩種形式: 公有成員,在任何地方都能訪問 私有成員,只有在類的內部才能方法 私有成員和公有成員的訪問限制不同 : 靜態屬性 公有 ...
Python類的成員
一、細分類的組成成員
類大致分為兩大部分:
- 靜態屬性
- 動態方法
class A:
# 靜態屬性部分
name = "dogfa"
age = 18
# 動態方法部分
def __init__(self, name, age):
self.name = name
self.age = age
每個區域詳細劃分又可以分為:
class A:
name = "dogfa" # 靜態屬性
__age = 18 # 私有靜態屬性
def __init__(self, name, gender): # 雙下方法(內置方法)
self.name = name # 對象屬性
self.__gender = gender # 私有對象屬性
def __func(self): # 私有方法
pass
def func(self): # 普通方法
pass
@classmethod
def classfunc(cls): # 類方法
pass
@staticmethod
def staticfunc(): # 靜態方法
pass
@property
def prop(self): # 屬性
pass
二、類的私有成員
對於每一個類的成員而言都有兩種形式:
- 公有成員,在任何地方都能訪問
- 私有成員,只有在類的內部才能方法
私有成員和公有成員的訪問限制不同:
靜態屬性
- 公有靜態屬性:類可以訪問;類內部可以訪問;派生類中可以訪問
- 私有靜態屬性:僅類內部可以訪問;
對象屬性
- 公有對象屬性:對象可以訪問;類內部可以訪問;派生類中可以訪問
- 私有對象屬性:僅類內部可以訪問;
方法:
- 公有方法:對象可以訪問;類內部可以訪問;派生類中可以訪問
- 私有方法:僅類內部可以訪問;
總結:對於這些私有成員來說,他們只能在類的內部使用,不能再類的外部以及派生類中使用。
tips:非要訪問私有成員的話,可以通過 對象._類__屬性名,但是絕對不允許!!
為什麼可以通過._類__私有成員名訪問呢?因為類在創建時,如果遇到了私有成員它會將其保存在記憶體時自動在前面加上_類名。
三、類的其它成員
這裡的其他成員主要就是類方法:
方法包括:普通方法、靜態方法和類方法,三種方法在記憶體中都歸屬於類,區別在於調用方式不同。
實例方法
定義:第一個參數必須是實例對象,該參數名一般約定為“self”,通過它來傳遞實例的屬性和方法(也可以傳類的屬性和方法);
調用:只能由實例對象調用。
類方法
定義:使用裝飾器@classmethod。第一個參數必須是當前類對象,該參數名一般約定為“cls”,通過它來傳遞類的屬性和方法(不能傳實例的屬性和方法);
調用:實例對象和類對象都可以調用。
靜態方法
定義:使用裝飾器@staticmethod。參數隨意,沒有“self”和“cls”參數,但是方法體中不能使用類或實例的任何屬性和方法;
調用:實例對象和類對象都可以調用。
雙下方法
定義:雙下方法是特殊方法,他是解釋器提供的由雙下劃線加方法名加雙下劃線 __方法名__的具有特殊意義的方法,比如__init__
調用:不同的雙下方法有不同的觸發方式,就好比盜墓時觸發的機關一樣,不知不覺就觸發了雙下方法,例如:__init__
類方法
應用場景:
類中有些方法是不需要對象參與
class A: name = "dogfa" index = 0 @classmethod def func(cls): return cls.name + str(cls.index) print(A.func())
對類中的靜態變數進行改變,要用類方法
class A: name = "dogfa" index = 0 @classmethod def func(cls, name): cls.name = name return cls.name print(A.func("oldniu"))
繼承中,父類得到子類的類空間,然後可以對子類為所欲為
class A: name = "dogfa" index = 0 @classmethod def func(cls): print(cls) # 獲取B類的類空間(<class '__main__.B'>) cls.name = "djb" # 給B類添加靜態屬性 class B(A): pass B.func() print(B) # <class '__main__.B'> print(B.__dict__) # {'__module__': '__main__', '__doc__': None, name': 'djb'}
靜態方法
靜態方法是類中的函數,不需要實例。靜態方法主要是用來存放邏輯性的代碼,邏輯上屬於類,但是和類本身沒有關係,也就是說在靜態方法中,不會涉及到類中的屬性和方法的操作。可以理解為,靜態方法是個獨立的、單純的函數,它僅僅托管於某個類的名稱空間中,便於使用和維護。
import time class TimeTest(object): def __init__(self, hour, minute, second): self.hour = hour self.minute = minute self.second = second @staticmethod def showTime(): return time.strftime("%H:%M:%S", time.localtime()) print(TimeTest.showTime()) # 12:07:02 t = TimeTest(2, 10, 10) nowTime = t.showTime() print(nowTime) # 12:07:02
如上,使用了靜態方法(函數),然而方法體中並沒使用(也不能使用)類或實例的屬性(或方法)。若要獲得當前時間的字元串時,並不一定需要實例化對象,此時對於靜態方法而言,所在類更像是一種名稱空間。
其實,我們也可以在類外面寫一個同樣的函數來做這些事,但是這樣做就打亂了邏輯關係,也會導致以後代碼維護困難。
屬性
屬性 : 將一個方法偽裝成一個 屬性,在代碼的級別上沒有本質的提升,但是讓其看起來跟合理。
什麼是特性property
property是一種特殊的屬性,訪問它時會執行一段功能(函數)然後返回值
為什麼要用property
將一個類的函數定義成特性以後,對象再去使用的時候obj.name,根本無法察覺自己的name是執行了一個函數然後計算出來的,這種特性的使用方式遵循了統一訪問的原則
class Goods: def __init__(self, original_price, discount): self.original_price = original_price self.discount = discount @property def price(self): new_price = float(self.original_price) * float(self.discount) return new_price # 修改原價 @price.setter def price(self, value): if isinstance(value, int): self.original_price = value else: raise TypeError("{0} must be in int".format(value)) # 刪除原價 @price.deleter def price(self): del self.original_price good = Goods(100, 0.8) # 獲取商品價格 print(good.price) # 80.0 # 修改商品價格 good.price = 89 print(good.price) # 71.2
四、類的約束
抽象類:抽象類是一個介於類和介面之間的一個概念,同時具備類和介面的部分特性,可以用來實現歸一化設計。
Python中沒有介面類這種東西。
引入抽象類的概念對類進行約束:
from abc import ABCMeta, abstractmethod
class Payment(metaclass=ABCMeta): # 抽象類 規範和約束 metaclass指定的是一個元類
@abstractmethod
def pay(self): pass # 抽象方法
class WeChatPay(Payment):
def pay(self, money):
print("使用微信支付了{0}元".format(money))
class AliPay(Payment):
def pay(self, money):
print("使用支付寶支付了{0}元".format(money))
class JdPay(Payment):
pass
# def pay(self, money):
# print("使用京東支付了{0}元".format(money))
def pay(obj, money):
obj.pay(money)
ali = AliPay()
wechat = WeChatPay() # 歸一化設計:不管是哪一個類的對象,都調用同一個函數去完成相似的功能
jd = JdPay() # JdPay沒有實現父類中的抽象類pay方法,在實例化對象時會報錯
pay(ali, 300)
pay(wechat, 500)