1. 程式人生 > >Python中類方法定義及常用的實現方式

Python中類方法定義及常用的實現方式

1. python類的屬性和方法檢視

class Person_1:
    mind = '有思想'
    belif = '有信仰'
    animal = '高階動物'


    def tt():
        pass

print(Person_1.__dict__)  #查詢類Person中所有的內容,表現形式是字典.
print(Person_1.__dict__['belif'])  #查詢類Person中的變數'belif'


class Person_2:
    mind = '有思想'
    belif = '有信仰'
    animal =
'高階動物' def work(): print('666') def money(): print('777') print(Person_2.animal) #高階動物 print(Person_2.mind) #有思想 Person_2.mind = '沒有思想' #修改變數'mind'的值,可以通過__dicy__檢視修改後的內容 Person_2.pay = '貨幣交換' #增加變數'pay'和它的值,可以通過__dicy__檢視增加後的內容 Person_2.say = '語言交流' print
(Person_2.work()) #也可以呼叫類中的方法(函式),工作中不用類名去操作 print(Person_2.__dict__) #檢視類中所有的內容

執行:

{'__module__': '__main__', 'mind': '有思想', 'belif': '有信仰', 'animal': '高階動物', 'tt': <function Person_1.tt at 0x10f243f28>, '__dict__': <attribute '__dict__' of 'Person_1' objects>, '__weakref__': <
attribute '__weakref__' of 'Person_1' objects>, '__doc__': None} 有信仰 高階動物 有思想 666 None {'__module__': '__main__', 'mind': '沒有思想', 'belif': '有信仰', 'animal': '高階動物', 'work': <function Person_2.work at 0x1114429d8>, 'money': <function Person_2.money at 0x1114421e0>, '__dict__': <attribute '__dict__' of 'Person_2' objects>, '__weakref__': <attribute '__weakref__' of 'Person_2' objects>, '__doc__': None, 'pay': '貨幣交換', 'say': '語言交流'}

2. python物件方法、類方法、靜態方法:

下面是簡單的幾個例子:

class Person(object):
    
    grade=6     # 類變數
    
    def __init__(self):
        self.name = "king"
        self.age=20
        
    def sayHi(self):    #加self區別於普通函式
        print ('Hello, your name is?',self.name)
        
    def sayAge(self):
        print( 'My age is %d years old.'%self.age)
        
        
    @staticmethod     # 靜態方法不能訪問類變數和例項變數,也不能使用self
    def sayName():
        print ("my name is king") 
        
          
    @classmethod     #類方法可以訪問類變數,但不能訪問例項變數
    def classMethod(cls):  
        #print('cls:',cls)
        print('class grade:',cls.grade)        
        #print("class method")
            
        
class Child(object):
    
    def __init__(self):
        self.name = "小明"
        self.age=20
     
        
    def sayName(self,obj):
        print('child name is:',self.name)
        print(obj.sayName)
        print(obj.sayName()) # 這裡要特別注意帶括號和不帶括號的區別:一個是物件,一個是方法
        

p = Person()    # 例項化物件
print('p.grade:',p.grade)  # 例項物件呼叫類變數
p.grade=9
print(p.classMethod(),p.grade) # 例項改變類變數時,其grade變數只會在例項中改變


print(Person().grade) # 類物件呼叫類變數
p.sayHi()       # 例項物件呼叫類成員函式 
Person().sayAge() # 類物件呼叫類成員函式


p.sayName()    # 例項物件呼叫類靜態方法
m=Person()
m.sayName()    # 多個例項共享此靜態方法
Person().sayName() # 類物件呼叫靜態方法


p.classMethod()  # 例項物件呼叫類方法
Person.classMethod() # 類物件呼叫類方法

# 呼叫類
tt=Child()
tt.sayName(Person()) 

執行結果:

p.grade: 6
class grade: 6
None 9
6
Hello, your name is? king
My age is 20 years old.
my name is king
my name is king
my name is king
class grade: 6
class grade: 6
child name is: 小明
<function Person.sayName at 0x10f1cc598>
my name is king
None

小小總結下:

python中實現靜態方法和類方法都是依賴於python的裝飾器來實現的。 物件方法有self引數,類方法有cls引數,靜態方法不需要這些附加引數。

  • 靜態方法

要在類中使用靜態方法,需在類成員函式前面加上@staticmethod標記符,以表示下面的成員函式是靜態函式。使用靜態方法的好處是,不需要定義例項即可使用這個方法。另外,多個例項共享此靜態方法(靜態方法無法訪問類屬性、例項屬性,相當於一個相對獨立的方法,跟類其實沒什麼關係,簡單講,靜態方法就是放在一個類的作用域裡的函式而已)。

  • 類方法

類方法與普通的成員函式和靜態函式有不同之處。定義: 一個類方法就可以通過類或它的例項來呼叫的方法, 不管你是用類來呼叫這個方法還是類例項呼叫這個方法,該方法的第一個引數總是定義該方法的類物件。 也即是方法的第一個引數都是類物件而不是例項物件. 按照習慣,類方法的第一個形參被命名為 cls。任何時候定義類方法都不是必須的(類方法能實現的功能都可以通過定義一個普通函式來實現,只要這個函式接受一個類物件做為引數就可以了)。同時,類方法可以訪問類屬性,無法訪問例項屬性。上述的變數grade,在類裡是類變數,在例項中又是例項變數,所以使用的時候要注意,使用好的話功能很強大,使用不好容易混淆。

3. 類方法之間的呼叫

class Person(object):
    
    # 不加任何引數直接定義,也是類方法
    def Work():
        print(" I am working!")
                
    # 類方法       第一種方法:加裝飾器方法
    @classmethod   
    def Think(cls,b):    #類方法Think必須要帶至少1個引數,第一個引數預設為類名,後面可以引用。
        cls.Eat(b)       #在類方法Think中,呼叫類方法Eat類方法。
        cls.Work()       #在類方法Think中,呼叫Work類方法。        
        print(b,",I am Thinking!")
    

    # 屬於第二種方法,先定義類方法,至少1個引數,第一個預設為類名。
    def Eat(cls,b):      
        print(b+",I am eating")
    Eat=classmethod(Eat)    #第二種方法:通過內建函式classmethod()來建立類方法。  
    
    # 靜態方法,引用時直接用類名.Sleep()即可。
    @staticmethod            
    def Sleep():
        print("I am sleeping")
                        
    # 這種方法是:例項物件呼叫方法
    def __scolia__(self):         
        print("scola")
        return "scola"
               
    # 例項物件可以訪問的私有方法,在類方法中可以相互呼叫和使用。類不能直接訪問或者外部訪問。
    def __good(self):           
        print("good")
        return "good"
    
    
Person.Think("li")
Person.Eat("jcy")
Person.Work() 
# a.Work()  報錯,例項物件不能呼叫類方法
Person.Sleep()

a=Person()
a.__colia__() # 魔術方法,沒有私有化。
#a.__good()   # 私有方法:報錯了!

執行:

li,I am eating
 I am working!
li ,I am Thinking!
jcy,I am eating
 I am working!
I am sleeping
scola

4. python使用@property @x.setter @x.deleter

  • 只有@property表示只讀。
  • 同時有@property和@x.setter表示可讀可寫。
  • 同時有@property和@x.setter和@x.deleter表示可讀可寫可刪除。

方法必須要先經過 property()函式的裝飾後,才有後面兩個裝飾器的用法。

直接看例項:

class student(object):  #新式類
    
    def __init__(self,id):  
        self.__id=id  
        
    @property  #只讀  
    def score(self):  
        return self._score 
    
    @score.setter #只寫  
    def score(self,value):          
        if not isinstance(value,int):  
            raise ValueError('score must be an integer!')    
        if value<0 or value>100:  
            raise ValueError('score must between 0 and 100')   
        self._score=value  
               
    @property #只讀
    def get_id(self):  
        return self.__id  
    
  
s=student('123456')  
s.score=100 # 寫  
print(s.score) #讀  
print(s.__dict__)
print (s.get_id) #只讀
#s.get_id=456 #只能讀,不可寫:AttributeError: can't set attribute


class A(object): # 新式類(繼承自object類)
    
    def __init__(self):
        self.__name=None
        
    def getName(self):
        return self.__name
    
    def setName(self,value):
        self.__name=value
        
    def delName(self):
        del self.__name
        
    name=property(getName,setName,delName)
 
a=A()
print(a.name) #讀
a.name='python' #寫
print(a.name) #讀
del a.name #刪除
#print a.name #a.name已經被刪除 AttributeError: 'A' object has no attribute '_A__name'

執行結果:

100
{'_student__id': '123456', '_score': 100}
123456
None
python

經典類和新式類的對比:

class test1:#經典類:沒有繼承object    
    def __init__(self):    
        self.__private='alex 1' #私有屬性以2個下劃線開頭 
        
    #讀私有屬性    
    @property    
    def private(self):    
        return self.__private 
    
    #嘗試去寫私有屬性(對於經典類而言,“寫”是做不到的)  
    @private.setter    
    def private(self,value):    
        self.__private=value
        
    #嘗試去刪除私有屬性(對於經典類而言,“刪除”也是做不到的)  
    @private.deleter  
    def private(self):  
        del self.__private  
 

     
class test2(object):# 新式類:繼承了object    
    def __init__(self):    
        self.__private='alex 2' #私有屬性以2個下劃線開頭 
        
    #讀私有屬性    
    @property    
    def private(self):    
        return self.__private   
    
    #寫私有屬性    
    @private.setter    
    def private(self,value):    
        self.__private=value  
        
    #刪除私有屬性  
    @private.deleter  
    def private(self):  
        del self.__private  
      
t1=test1()    
#print t1.__private # 外界不可直接訪問私有屬性    
print (t1.private) # 讀私有屬性
print (t1.__dict__) 
t1.private='change 1' #對於經典類來說,該語句實際上是改變了例項t1的例項變數private  
print (t1.__dict__)
print (t1.private) # 輸出剛剛新增的例項變數private  

t1.private='change 2'  
print (t1.__dict__)  
del t1.private # 刪除剛剛新增的例項變數private  
print (t1.__dict__) 
#print (t1.private) #讀私有屬性,因為已經刪除,所以這裡會報錯

print ('-------------------------------------------------------')
t2=test2()    
print (t2.__dict__)  
print (t2.private) # 繼承了object,新增@private.setter後,才可以寫    
t2.private='change 2' # 修改私有屬性    
print (t2.__dict__)   
print (t2.private)  
del t2.private #刪除私有變數  
#print t2.private #私有變數已經被刪除,執行“讀”操作會報錯:AttributeError: 'test2' object has no attribute '_test2__private'    
print (t2.__dict__) 

執行:

alex 1
{'_test1__private': 'alex 1'}
{'_test1__private': 'change 1'}
change 1
{'_test1__private': 'change 2'}
{}
-------------------------------------------------------
{'_test2__private': 'alex 2'}
alex 2
{'_test2__private': 'change 2'}
change 2
{}

貌似差別也不是很大。

參考:
https://blog.csdn.net/sxingming/article/details/52916249

5. “魔術方法”的使用

可以參考:https://blog.csdn.net/NightCharm/article/details/79357559