面向對象高級語法部分 通過@staticmethod裝飾器即可把其裝飾的方法變為一個靜態方法,什麼是靜態方法呢?其實不難理解,普通的方法,可以在實例化後直接調用,並且在方法里可以通過self.調用實例變數或類變數,但靜態方法是不可以訪問實例變數或類變數的,一個不能訪問實例變數和類變數的方法,其實相當 ...
面向對象高級語法部分
通過@staticmethod裝飾器即可把其裝飾的方法變為一個靜態方法,什麼是靜態方法呢?其實不難理解,普通的方法,可以在實例化後直接調用,並且在方法里可以通過self.調用實例變數或類變數,但靜態方法是不可以訪問實例變數或類變數的,一個不能訪問實例變數和類變數的方法,其實相當於跟類本身已經沒什麼關係了,它與類唯一的關聯就是需要通過類名來調用這個方法。
class SchoolMember(object): def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex member_nums = 0 def introduce(self): print("My name is %s,and I am %s year old." %(self.name,self.age)) @staticmethod def talk(): print("I like to study python") class Teacher(SchoolMember): def __init__(self,name,age,sex,course,salary): super(Teacher,self).__init__(name,age,sex) self.course = course self.salary = salary def Teaching(self): print("Teacher %s is teaching %s." %(self.name,self.course)) s1 = Teacher("alex",22,"Femal","python",10000) print("before:",s1.member_nums) SchoolMember.member_nums = 12 print("before:",s1.member_nums) s1.member_nums = 666 #是在類中重新生成一個變數 print("after:",s1.member_nums) SchoolMember.member_nums = 12 print("after:",s1.member_nums)
在上面代碼中,member_nums是類變數,如果直接調用s1.member_nums的話,調用的是類裡面的值;如果s1.member_nums = 666,等於在實例裡面增加了一個新的變數,這個時候,修改類的值的時候,是不會影響實例裡面變數的值的。上面代碼的輸出結果如下:
before: 0
before: 12
after: 666
after: 666
類的靜態方法@staticmethon:
class SchoolMember(object): def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex member_nums = 0 def introduce(self): print("My name is %s,and I am %s year old." %(self.name,self.age)) @classmethod #類方法,不能訪問實例變數 def talk(self): print("%s like to study python" %SchoolMember.member_nums) @staticmethod def walk(self): print("%s is walking......" %self.name) #SchoolMember.talk() #不能調用,類是沒有辦法訪問實例變數,只能訪問自己 s1 = SchoolMember("Alex",22,"Female") #實例化 s1.walk()
運行結果如下:
Traceback (most recent call last):
File "/home/zhuzhu/day7/staticmethon方法.py", line 22, in <module>
s1.walk()
TypeError: walk() missing 1 required positional argument: 'self'
上面代碼中,如果沒有@staticmethon的話,代碼執行肯定沒有問題,但是當有了@staticmethod的時候,系統提示少了一個參數。如果我們把一個方法變成了一個靜態方法,那麼這個方法與實例就沒有太大的關係了。
class SchoolMember(object): def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex member_nums = 0 def introduce(self): print("My name is %s,and I am %s year old." %(self.name,self.age)) @classmethod #類方法,不能訪問實例變數 def talk(self): print("%s like to study python" %SchoolMember.member_nums) @staticmethod #讓方法在類中剝離,與類沒有關係,調用要傳遞參數 def walk(self): print("%s is walking......" %self) #SchoolMember.talk() #不能調用,類是沒有辦法訪問實例變數,只能訪問自己 s1 = SchoolMember("Alex",22,"Female") #實例化 s1.walk("alex")
@staticmethod靜態方法是讓類中的方法與類沒有關聯,調用的時候要傳遞參數才能調用。
類方法
類方法通過@classmethod裝飾器實現,類方法和普通方法的區別是, 類方法只能訪問類變數,不能訪問實例變數
class SchoolMember(object): def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex member_nums = 0 def introduce(self): print("My name is %s,and I am %s year old." %(self.name,self.age)) #@classmethod #類方法,不能訪問實例變數 def talk(self): print("%s like to study python" %self.name) SchoolMember.member_nums #SchoolMember.talk() #不能調用,類是沒有辦法訪問實例變數,只能訪問自己 s1 = SchoolMember("Alex",22,"Female") #實例化 s1.talk()
上面代碼中,(1)類是不能直接訪問實例裡面的屬性的;(2)@classmethod的作用是讓程式只能訪問類中的變數,比如上面代碼中的SchoolMember.member_nums,這個是類的方法,我們可以在talk中進行訪問,但是不能訪問self.name,因為@classmethod只能訪問類屬性。
class SchoolMember(object): def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex member_nums = 0 def introduce(self): print("My name is %s,and I am %s year old." %(self.name,self.age)) @classmethod #類方法,不能訪問實例變數 def talk(self): print("%s like to study python" %self.name) SchoolMember.member_nums #SchoolMember.talk() #不能調用,類是沒有辦法訪問實例變數,只能訪問自己 s1 = SchoolMember("Alex",22,"Female") #實例化 s1.talk() 運行結果如下: Traceback (most recent call last): File "/home/zhuzhu/day7/staticmethon方法.py", line 18, in <module> s1.talk() File "/home/zhuzhu/day7/staticmethon方法.py", line 13, in talk print("%s like to study python" %self.name) AttributeError: type object 'SchoolMember' has no attribute 'name'
從上面可以看出,上面的代碼@classmethon禁止了類中的實例變數,只能使用類變數。即不能使用self.name、self.age和self.sex,只能使用self.nember_nums和SchoolMember.member_nums類的變數。如下:
class SchoolMember(object): def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex member_nums = 0 def introduce(self): print("My name is %s,and I am %s year old." %(self.name,self.age)) @classmethod #類方法,不能訪問實例變數 def talk(self): print("%s like to study python" %SchoolMember.member_nums) SchoolMember.member_nums #SchoolMember.talk() #不能調用,類是沒有辦法訪問實例變數,只能訪問自己 s1 = SchoolMember("Alex",22,"Female") #實例化 s1.talk() 運行結果如下: 0 like to study python
屬性方法
屬性方法的作用就是通過@property把一個方法變成一個靜態屬性
class SchoolMember(object): def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex member_nums = 0 def introduce(self): print("My name is %s,and I am %s year old." %(self.name,self.age)) @classmethod #類方法,不能訪問實例變數 def talk(self): print("%s like to study python" %SchoolMember.member_nums) @property #把類的方法變成一個屬性,調用要使用s1.walk不加括弧直接調用,稱為一個屬性 def walk(self): print("%s is walking......" %self.name) #SchoolMember.talk() #不能調用,類是沒有辦法訪問實例變數,只能訪問自己 s1 = SchoolMember("Alex",22,"Female") #實例化 s1.walk()
運行結果如下:
Traceback (most recent call last):
File "/home/zhuzhu/day7/staticmethon方法.py", line 22, in <module>
s1.walk()
TypeError: 'NoneType' object is not callable
如果不添加@property的話,程式是能夠正常運行的,但是添加了@property之後,程式運行出現錯誤,是什麼原因呢?因為@property是將類的方法變成了類的屬性,調用的時候我們只需執行s1.walk()無需添加括弧即可執行,如下:
class SchoolMember(object): def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex member_nums = 0 def introduce(self): print("My name is %s,and I am %s year old." %(self.name,self.age)) @classmethod #類方法,不能訪問實例變數 def talk(self): print("%s like to study python" %SchoolMember.member_nums) @property #把類的方法變成一個屬性,調用要使用s1.walk不加括弧直接調用,稱為一個屬性 def walk(self): print("%s is walking......" %self.name) #SchoolMember.talk() #不能調用,類是沒有辦法訪問實例變數,只能訪問自己 s1 = SchoolMember("Alex",22,"Female") #實例化 s1.walk
運行結果如下:
Alex is walking......
上面代碼中,@property是將類的方法變成了成員的屬性,我們可以直接使用s1.walk即可調用。
經典類vs新式類
class A: #經典類的寫法,新式類是A(object)儘量少用經典類,都用新式類現在 def __init__(self,name): self.name = name def f1(self): print("f1,搞基") class B(A): def __init__(self,name): super(B,self).__init__(name) # def f1(self): # print("f1,來呀") class C(A): def __init__(self,name): super(C,self).__init__(name) #def f1(self): #print("f1,一起搞!") class D(B,C): pass d = D("Alex") d.f1()
上面代碼中,D類繼承了B類和C類,當我們執行D類中的方法是,首先是在B類中進行查找,這個經典類和新式類都是一樣的,如果查找不到,經典類是去A類中進行查找,而新式類是去C類中查找,實例如下:(備註:必須去2.X版本中運行才有差別,3.X進行優化,B類中查找不到都去C類中查找)
下麵是經典類和新式類的執行順序:
(新式類)先執行同級的類
(2)經典類(先執行上一級的類)