1. 程式人生 > >類中的三個裝飾器方法

類中的三個裝飾器方法

@classmethod

class A:
    __count = 0 #隱藏count屬性
    def __init__(self,name):
        self.name = name
        self.__add_count() #每一次例項化的時候呼叫私有化__count進行累加
    def __add_count(self): #定義一個私有化的方法
        A.__count +=1
    def show_count(self): #定義一個普通方法
        return A.__count  #讓使用者可以從外部檢視__count的值
def eat(self): print('%s在吃飯'%self.name) wl = A('wanglan') print(wl.show_count()) wl.eat() #有的時候,在類中會有一種情況,就是這個方法並不需要使用某一個物件的屬性,因此,這個方法中的self引數是一個完成無用的引數, #show_count是一個檢視類中屬性的方法,這樣的方法和某一個物件並沒有直接聯絡

在上面程式碼中,__add_count 方法和show_count方法並沒有使用self引數,但是我們給它傳了,正常情況下,如果引數不被使用,我們不應該傳入改引數,因此這個方法中的self引數是一個完全無用的引數,我們可以直接刪除,刪除後的報錯也只是Pycharm上的語法報錯,但是python的語法不希望我們這樣做,我們可以使用 @classmethod

裝飾器來解決

class A:
    __count = 0 #隱藏count屬性
    def __init__(self,name):
        self.name = name
        self.__add_count() #每一次例項化的時候呼叫私有化__count進行累加
    @classmethod   #被classmethod 裝飾器裝飾的方法,都用一個預設的引數,這個引數就是當前類
    def __add_count(cls): #定義一個私有化的方法
        print(cls,A)  #兩個值相同
        cls.__count
+=1 # cls 就可以取代A @classmethod def show_count(cls): #定義一個普通方法 return cls.__count #讓使用者可以從外部檢視__count的值 def eat(self): print('%s在吃飯'%self.name) print(A.show_count()) #可以直接呼叫show_count wl = A('wanglan') print(wl.show_count()) wl.eat() 結果: 0 <class '__main__.A'> <class '__main__.A'> 1 wanglan在吃飯

本質上:一個方法不用物件屬性但是使用靜態屬性 -- 類方法(@classmethod)

某一個方法被創造出來,就是為了對靜態變數進行操作,根部不涉及到物件,所以這個方法就應該被定義成:類方法(被@classmethod裝飾),呼叫這個類方法時,可以使用物件呼叫wl.show_count(),也可以使用類呼叫 A.show_count(),但是這個方法的預設引數永遠是當前類的名稱空間,而不是物件

 

 @staticmethod

def login():  #普通函式
    pass
login() #呼叫

純面向物件程式設計

class User(object):
    @staticmethod
    def login(): #是User類中的名字 函式的名字 login就是一個類中的靜態方法,本質上就是一個函式
        pass
ret = User.login()

如果一個類中的方法不用物件屬性也不用靜態熟屬性 -- 靜態方法(@staticmethod),實際上這個方法就是一個普通的函式

小結

               普通的方法             類方法              靜態方法
預設引數          self                 cls                無
操作的變數        操作物件的屬性          操作靜態屬性         既不操作物件屬性,也不操作類的屬性
所屬的名稱空間     類                    類                 類
呼叫方式          物件                  類/物件             類/物件
對應的裝飾器       無                   @classmethod       @staticmethod

@property:

把一個方法偽裝成屬性,和呼叫屬性一樣去呼叫方法()名稱裝飾,動詞就不用了)

某一個屬性如果是通過計算得來的,那麼計算的過程寫在方法裡,把這個方法偽裝成屬性

from math import pi
class Circle:
    def __init__(self,r):
        self.r = r

    @property  # 把一個方法偽裝成屬性 原始碼中有人寫,
    def area(self):   # 被property裝飾器裝飾的方法不能傳遞除self以外的引數
        return pi*self.r**2

    @property
    def perimeter(self):
        return self.r*pi*2

c1 = Circle(5)
# print(c1.area()) #加入@property 方法前的呼叫
print(c1.area) #加入@property 方法後的呼叫
c1.r = 10
print(c1.area)

某一個屬性需要被私有化,又需要能被外部檢視,這種情況,把這個屬性通過方法返回,方法偽裝成屬性

class Person:
    def __init__(self,name):
        self.__name = name  # 不讓外面隨便修改

    @property
    def name(self):
        return self.__name

wl = Person('wanglan')
print(wl.name)

修改屬性值

class Person:
    def __init__(self,name):
        self.__name = name  # 不讓外面隨便修改

    @property
    def name(self):
        return self.__name

    @name.setter   # 之前必須有一個同名的方法被property裝飾過
    def name(self,new_name):
        if type(new_name) is str:
            self.__name = new_name

    @name.deleter
    def name(self):
        del self.__name


wl= Person('wang')
print(wl.name)
wl.name = 'wanglan'
print(wl.name)
del wl.name   # 只是相當於呼叫被deleter裝飾的方法,並不相當於刪除name屬性
print(wl.name)