今日摘要函數
今天主要整理一下這倆天學習的內容,面向對象也快學完了,深入的認識到面向對象就是一個思想,怎麼把思想理解了,其餘也就不是什麼事了工具
1.類的約束學習
2.類的類方法與靜態方法spa
3.類的反射code
4.類的內置方法以及雙下方法orm
開始今日份總結對象
1.類的約束blog
類的約束,就是對類進行一些正確的引導,約束,統一規範,知足正確的開發方式接口
1.1類的約束的第一種方式ip
class A: def pay(self,money):#規定都必須有pay方法 raise Exception('未定義指定函數') class Alipay(A): def pay(self,money): print('本次消費%s'%money) class JDpay(A): def pay(self,money): print('本次消費%s'%money) class Wechatpay(A): def zhifu(self,money): print('本次消費%s'%money) w1 = Wechatpay() def pay(obj,money):#約束一下,約定全部人的支付必須是使用統一的接口,可是這樣也沒又很強烈的約束功能 obj.pay(money) pay(w1,100) #這種事若是沒有定義指定的方法會拋出錯誤
1.2類的約束的第二種方式
from abc import ABCMeta,abstractmethod class A(metaclass=ABCMeta): def pay(self,money): print('請建立正確的方法') @abstractmethod class Alipay(A): def pay(self,money): print('本次消費%s'%money) class JDpay(A): # def zhifu(self,money): # print('本次消費%s'%money) def pay(self, money): print('這次消費%s' % money) def pay(obj,money): obj.pay(money) j1 = JDpay() pay(j1,100) #第二種方式就是調用abc模塊,可是這種在平常使用中,不多用到,通常都是用第一種。
2.綁定方法與非綁定方法
在類內部通常包含倆種方法,一種爲綁定方法,一種爲非綁定方法
2.1綁定方法
綁定方法:綁定給誰,就由誰來執行,誰用就會把調用者當作第一個方法傳入
綁定給對象的方法:類內沒有被任何裝飾器修飾的方法
綁定給類的方法:類內定義的裝飾器裝飾的classmethod修飾的方法
看了一圈以及源碼對於怎麼用,或者是使用場景都沒有說,真的是一頭霧水,寫一點本身能理解的把
#本來 class Test_time(): def __init__(self,year,month,day): self.year = year self.month = month self.day = day def out_data(self): print('如今日期爲{}年{}月{}日'.format(self.year,self.month,self.day)) t1 = Test_time(2018,12,28) t1.out_data() 若是傳入數據爲不是正確的數據,例如‘2018-12-28’,就須要其餘函數對數據進行整理 class Test_time(): def __init__(self,year,month,day): self.year = year self.month = month self.day = day def out_data(self): print('如今日期爲{}年{}月{}日'.format(self.year,self.month,self.day)) @classmethod def data_solite(cls,msg): year, month, day = map(int, msg.split('-')) ret = cls(year,month,day) return ret msg ='2018-12-28' t2 =Test_time.data_solite(msg) t2.out_data()
這樣的好處就是你之後重構類的時候沒必要要修改構造函數,只須要額外添加你要處理的函數,而後使用裝飾符
在個人理解中,類方法就是將一個類在沒有實例化對象以前調用類裏面的方法,或者是先行修改內容,這樣就不須要修改構造函數,至關於重置構造函數。
2.2非綁定方法
沒有自動傳值這麼一個說法,就是一個普通函數,一個普通的工具,對於對象和類均可以調用。不與類或者對象進行綁定
就是在方法上加@staticmethod
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()) t = TimeTest(2, 10, 10) nowTime = t.showTime() print(nowTime) #類與對象均可以調用,使用對應的方法
3.類的反射
類的反射也是類的內置方法,也是一個特別重要的點
3.1 hasattr 判斷對象或者類是否存在指定的屬性,看代碼以及結果
class people: def __init__(self,name,age): self.name = name self.age = age def talk(self): print("%s is talking."%self.name) p1 = people('alex',18) print(hasattr(p1,'name')) print(hasattr(p1,'sex')) 結果 True False
hasattr判斷完成後,會返回一個布爾值,有就返回True,無就返回False
3.2getattr 獲取到一個對象或者類的屬性,加()就是執行,看代碼
class people: def __init__(self,name,age): self.name = name self.age = age def talk(self): print("%s is talking."%self.name) p1 = people('alex',18) print(getattr(p1,'name')) print(getattr(p1,'sex','man')) print(getattr(p1,'sex')) 結果 alex man File "D:/PycharmProjects/s2018/day6/test.py", line 13, in <module> print(getattr(p1,'sex')) AttributeError: 'people' object has no attribute 'sex'
對於getattr,若是對象或者是類有輸入的屬性,則,返回正確屬性。無則報錯,若是咱們指定默認值,則返回默認值,在看一下其餘
class people: def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex def talk(self): print("%s is talking."%self.name) p1 = people('alex',18,'woman') getattr(p1,'talk')()#getattr獲取到方法後加()就是執行 print(getattr(p1,'sex','man'))#類內若是對屬性已經確認過,顯示對象已經確認的值,而不顯示默認值 結果 alex is talking. woman
3.3setattr 是修改已有的屬性或者是新加一個屬性,看代碼
class people: def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex def talk(self): print("%s is talking."%self.name) p1 = people('alex',18,'woman') print('修改前',p1.age) setattr(p1,'age',20) print('修改後',p1.age) setattr(p1,'country','China') print(p1.__dict__) 結果 修改前 18 修改後 20 {'country': 'China', 'name': 'alex', 'sex': 'woman', 'age': 20}
3.4delattr就是對現有的對象或者類的屬性就行刪除,這個比較簡單,看代碼
class people: def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex def talk(self): print("%s is talking."%self.name) p1 = people('alex',18,'woman') print('修改前',p1.__dict__) delattr(p1,'name') print('修改後',p1.__dict__) 結果 修改前 {'age': 18, 'name': 'alex', 'sex': 'woman'} 修改後 {'age': 18, 'sex': 'woman'}
3.5類的反射其餘用法
在說一下在類的反射中其餘用法
#能夠用於反射的方面有實例化對象, 類,其餘py文件 本py文件 # 1.操做類的角度 class A: country = 'China' area = '深圳' def __init__(self,name,age): self.name = name self.age = age def func(self): print(666) print(getattr(A,'country')) print(getattr(A,'area')) print(getattr(A,'name')) getattr(A,'func')(23) print(hasattr(A,'func2')) # 2.其餘py文件(模塊) # 不用反射以前: import attr print(attr.flag) ret = attr.func # print(ret(10)) print(attr.B.name_list) obj = attr.B('barry','男') # print(obj.name_list) print(obj.name) ret = 'B' # 用反射的方法: import attr print(getattr(attr,'flag')) # 1,找到func 並執行 ret = getattr(attr,'func') print(ret(10)) #2,找到B類並調用 name_list func函數 b = getattr(attr,'B') print(b.name_list) print(getattr(attr.B,'name_list')) getattr(attr.B,'func')(1) #3,找到B類實例化對象在找 name,name_list func函數 b = getattr(attr,'B') obj = b('alex','男') print(obj.name) print(obj.name_list) # 4,本模塊的反射 import sys obj = sys.modules[__name__] print(obj) def func(): print(666) ret = input('>>>') # ret() getattr(obj,ret)() def func1(): print('in func1') def func2(): print('in func2') def func3(): print('in func3') l1 = [func1,func2,func3] for i in l1: i() import sys obj = sys.modules[__name__] l1 = ['func%s' % i for i in range(1,4)] # print(l1) for i in l1: getattr(obj,i)()
到底什麼對象能夠反射
4.類的內置方法以及雙下方法
類的內置方法其實包含類的反射中四個方法,上面已經寫了就不在描述
4.1其餘內置方法
# isinstance 判斷此對象是否是該類(或者是該類的子類)實例化的對象 class A: pass class B(A): pass obj = B() s1 = 'afds' print(isinstance(obj,B)) #True print(isinstance(obj,A)) #True print(isinstance(s1,str)) #True # issubclass 判斷的是此類是否是後面類的派生類 class D: pass class A(D): pass class B(A): pass abj = B() print(issubclass(B,A)) #True print(issubclass(B,D)) #True
4.2雙下方法
# 特殊雙下方法 # __init__ # len # s1 = 'fdsafdsa' # l1 = [1,2,3] # dic = {'name':'alex','age': 12} # i = 12 # # print(len(s1)) # int # # print(len(l1)) # list # print(len(dic)) # print(len(i)) # # class A: # # def __init__(self,name,age): # # self.name = name # # self.age = age # # self.sex = '男' # # # # def __len__(self): # # # print(666) # # return len(self.__dict__) # # a = A('barry', 18) # # # len(a) # len(對象) 若是此類中有__len__ 就_方法會自動執行__len_ # # print(len(a)) # print(hash('fsdaf')) # class A: # def __init__(self,name,age): # self.name = name # self.age = age # self.sex = '男' # # def __len__(self): # # print(666) # return len(self.__dict__) # # def __hash__(self): # return 1 # def __str__(self): # print(555) # return 'fdsaf' # object # a = A('barry', 18) # print(hash(a)) # print(a) # 對一個對象打印時,自動觸發類中的__str__方法 # print(a,type(a)) # __call__方法 # class Foo: # # def __init__(self): # print(11) # # def __call__(self, *args, **kwargs): # pass # obj = Foo() # obj() # 對象() 觸發 __call__方法 # __new__ 構造方法 # class A: # def __init__(self,name): # self.name = name # print('in A __init__') # object # obj = A('alex') # object # class A: # def __init__(self,name): # self.name = name # print('in A __init__') # def __new__(cls, *args, **kwargs): # print('in A __new__') # return object.__new__(cls) # # a = A('春哥') # print(a.name) # 1, 類名() 執行object.__new__方法,開闢的對象空間並返回 # 2,自動執行__init__方法,將空間創給self # 3,在__init__給對象封裝屬性。
__call__的三件事
單例模式,比較重要!
class A: __instance = None def __init__(self,name,age): self.name =name self.age = age def __new__(cls, *args, **kwargs): if cls.__instance is None: obj = object.__new__(cls) cls.__instance = obj return cls.__instance ret1 = A('alex',123) ret2 = A('wusir',22) ret3 = A('barry',18) print(ret1) print(ret2) print(ret3) #結果 <__main__.A object at 0x01702470> <__main__.A object at 0x01702470> <__main__.A object at 0x01702470> #就會發現單例模式就是不管怎麼實例化,生成的都是同一個,這樣節省名稱空間