1,python
# 面向對象的三大特性:繼承,多態和封裝 # 繼承: # 單繼承: **** # 父類(超類,基類) # 子類(派生類) 派生方法和派生屬性 # 子類的對象在調用方法和屬性:先用本身的,本身沒有,採用父類的 # 多繼承:(面試) # 不會超過三個父類,不要超過三層 *** # 若是子類本身有用本身的,若是沒有就用離子類最近的那個父類的 # 抽象類和接口類 ** # 經典類和新式類 繼承規則不一樣,深度優先和廣度優先 ***** (面試) # super 只有在python3中使用 mro **** # super 是根據mro 廣度優先順序找上一個類 # 多態:(面試) # 多態和鴨子類型 # 封裝:***(面試) # 私有的 #__名字 # 只能在類的內部調用,子類都沒法繼承 # 三個裝飾器 # @property **** 規範 面試 # @name.setter # @staticmethod *** # @classmethod ***** 當一個方法使用了類的靜態變量時,就給這個方法加上@classmethod裝飾器,默認傳cls參數
2,面試
class Goods(): __discount = 0.8 @classmethod def change_discount(cls): cls.__discount = 0.5 Goods.change_discount()
3,組合:表達的是什麼有什麼的關係 五顆星,一個類的屬性是另一個類的對象安全
4,面向對象的進階app
# isinstance() 和 issubclass() *** # 反射 ****** 很是很是的重要,高級的設置,JAVA裏面也有反射,會讓程序變得很簡潔,任何地方均可以用,模塊函數均可以 # setattr() # delattr() # getattr() # hasattr() # __str__ 和__repr__ ** 全部雙下方法,知道有這麼個方法就行,主要是不少人用不太好這些雙下方法 # __del__ # item系列 # __getitem__ # __setitem__ # __delitem__
5,isinstance 檢查一個obj是不是一個類的對象ide
class Foo():pass class Foo1():pass obj = Foo() print(isinstance(obj,Foo)) print(isinstance(obj,Foo1))
6,issubclass(sub,super) 檢查sub類是不是super類的派生類函數
class A():pass class B(A):pass print(issubclass(B,A))
7,反射,很是很是重要的知識點,反射是用字符串類型的名字去操做變量,和eval有點相似spa
8,反射對象的屬性code
name = 1 eval('print(name)') # eval會有很大的安全隱患,由於你不知道你執行的代碼是什麼來自哪裏,除非寫死了,否則有很大的安全隱患 # 可是反射就不會有安全問題,他不是真的拿到了一段python代碼,他是操做內存中已經存在的變量 # 第一種:反射對象中的屬性和方法 class A: def func(self): print('in func') a = A() a.name = 'Alex' # 反射對象的屬性 ret = getattr(a,'name') # 經過變量名的字符串形式取到值 print(ret) print(a.__dict__) 變量名 = input(">>>") print(getattr(a,變量名)) print(a.__dict__[變量名]) # 至關於這樣,可是咱們通常不這麼用
9,反射對象的方法對象
class A: def func(self): print('in func') ret = getattr(a,'func') ret()
10,反射類的屬性,方法和靜態方法blog
class A: price = 20 def __init__(self,name): self.name = name def func(self): print('in func') @classmethod def func2(cls): print('classmethod') @staticmethod def func3(): print('staticmethod') a = A('lisa') # 反射對象的屬性 if hasattr(a,'name'): ret = getattr(a,'name') print(ret) # 反射對象的方法 if hasattr(a,'func'): ret = getattr(a,'func') ret() # 反射類的屬性 if hasattr(A,'price'): ret = getattr(A,'price') print(ret) # 反射類的方法 if hasattr(A,'func2'): ret = getattr(A,'func2') ret() # 反射靜態的方法 if hasattr(A,'func3'): ret = getattr(A,'func3') ret()
11,反射模塊的屬性和方法
# 模塊my的代碼 day = "monday" def func():print('func in module my.py')
import my # 反射模塊的屬性和方法 print(getattr(my,'day')) print(getattr(my,'func'))
12,反射本身模塊中的變量,另外本身模塊的函數也是能夠的
import sys year = 2019 print(sys.modules['__main__'].year) print(sys.modules['my']) def qqxing():print('qqxing') # 反射本身模塊中的變量 ret = getattr(sys.modules['__main__'],'qqxing') # 這樣寫實際上是有坑的,由於若是我不是在這個模塊開始運行的,他就不叫__main__了 ret()
print(getattr(sys.modules[__name__],變量名)) # 這樣就能夠了
13,應用time模塊的一個小實例,要反射的函數有參數如何處理?下面的例子給出瞭解答
import time print(time.strftime('%Y-%m-%d %H:%M:%S')) print(getattr(time,'strftime')('%Y-%m-%d %H:%M:%S'))
14,一個模塊中的類能不能反射獲得
import my print(getattr(my,"C")) # 拿到類 print(getattr(my,"C")()) # 實例化
15,總結:什麼.什麼的形式均可以用反射來獲得,目前咱們沒有用到太多應用他的場景,可是後面用到他的地方很是多
16,getattr和hasattr 是一對兒,夫妻檔要一塊兒用
17,setattr,delattr幾乎不會用到的,不佔用星,用的很是少
class A: pass a = A() setattr(A,'name','nezha') setattr(a,'name','alex') print(A.name) print(a.name) delattr(a,'name') # 刪掉對象的會用類的name print(A.name) print(a.name)
18,類裏面內置的雙下方法,__str__ 和__repr__ 之前有講過str()和repr()
class A(object):pass # def __str__(self): # 只要是str方法,必定要返回一個字符串 # return 'str方法' a = A() print(str(a)) 若是類裏面的str方法沒有實現,那麼會去調用object類裏面的str方法,返回類的字符串 object裏面有一個__str__,一旦被調用,就返回調用這個方法的對象的內存地址 運行結果: <__main__.A object at 0x1072d6320>
class A(object): def __str__(self): # 只要是str方法,必定要返回一個字符串 return 'str方法' # 本身實現了str方法會用本身的 a = A() print(str(a)) # 會自動調用類裏面的雙下str方法
運行結果: str方法
19,str print str %s
class A(object): def __str__(self): # 本身寫會定義一個比較人性化的結果 return "A's object" a = A() print(str(a)) print(a) # 默認打印一個對象,就是打印出這個對象的地址,調用a.__str__ # 這個不涉及原理或者什麼,只是python的一種規定 l = [1,2,3,4,5] # 實例化了一個列表類的對象 print(l) # 爲什麼打印l就會顯示出裏面的每個元素,這就是他作了處理 # [1, 2, 3, 4, 5]
class A(object): def __str__(self): # 本身寫會定義一個比較人性化的結果 return "A's object" a = A() print('%s:%s'%(A,a)) %s實際上走的也是雙下str方法 運行結果: <class '__main__.A'>:A's object
20,__repr__,調用repr和%r方法會自動調用類裏面的雙下repr方法
class Teacher(object): def __init__(self,name,salary): self.name = name self.salary = salary def __str__(self): # 本身寫會定義一個比較人性化的結果, 若是不返回str會報錯的 return "A's object" def __repr__(self): return str(self.__dict__) lisa = Teacher('lisa',100) print(lisa) print(repr(lisa)) 運行結果: A's object {'name': 'lisa', 'salary': 100}
21,總結一下
# 本身沒有定製雙下repr方法,那麼會調用父類的repr方法,輸出對象的內存地址, # repr方法是str方法的備胎,本身沒有定製str方法,那麼會找repr方法,若是也沒有repr方法,那麼會調用父類的str方法。
22,repr是 str的備胎,str不能作repr的備胎
23,雙下len方法,這些雙下方法又稱爲魔法方法,是調用其餘的自動來觸發的
class A: def __len__(self): return 100 # 返回值必須是整數,小數也不行 a = A() print(len(a))
23,__len__,這個方法必須實現了,才能夠在下面調用,object類並無定義全部的雙下__len__方法,不必定全部的內置方法都被object收錄了,比方說數字。有一些模塊,好比說時間,不具有len,也沒有意義,因此只能是全部的類都有的,會被object收錄。定製對象的長度
class Classes: def __init__(self,name): self.name = name self.student = [] def __len__(self): return len(self.student) s9 = Classes('python') s9.student.append('lisa') s9.student.append('lucy') print(len(s9)) # 2
24,__del__雙下del方法,析構方法,del 既執行了方法,又刪除了變量,析構函數,在刪除一個對象以前,在作一些收尾工做
class A:pass # def __del__(self): # print('執行我啦!') a = A() del a # 會自動調用雙下del方法 print(a) # 提示出錯,NameError: name 'a' is not defined # 須要注意的是a 雙下del 即便咱們不定製,那麼調用的時候也會自動去調用父類的雙下del刪除
25,del 被刪除的狀況,引用計數,達到零了會被刪除,這是第一種狀況,第二種狀況,
26,雙下__call__方法
class A: def __init__(self,name,age): self.name = name self.age = age # def __call__(self): # print('執行我啦lala') def __call__(self, *args, **kwargs): for k in self.__dict__: print(k,end=' ') a = A('lisa',22) a() # TypeError: 'A' object is not callable ,不實現call方法會報出這個錯誤 A('lisa',22)() # 見到這樣的不要不認識,實際上就是調用雙下call方法