Python之面向对象四
面向對象進階
一、關于面向對象的兩個內置函數
isinstance?? 判斷類與對象的關系????isinstance(obj,cls)檢查obj是否是類 cls 的對象,返回值是bool值
issubclass???? 判斷類與類的關系?????????????issubclass(sub, super)檢查sub類是否是 super 類的派生類,返回值是bool值
class A:pass class B(A):pass a = A() print(isinstance(a,A)) print(issubclass(B,A)) print(issubclass(A,B))>>> True True False 關于類的內置函數二、反射
什么是反射?
反射的概念是由Smith在1982年首次提出的,主要是指程序可以訪問、檢測和修改它本身狀態或行為的一種能力(自省)。這一概念的
提出很快引發了計算機科學領域關于應用反射性的研究。它首先被程序語言的設計領域所采用,并在Lisp和面向對象方面取得了成績。
?
2 python面向對象中的反射:通過字符串的形式操作對象相關的屬性。python中的一切事物都是對象(都可以使用反射)
ps:
eval? 的功能和反射有點類似,但是 eval 在操作字符串時有很大的安全隱患,反射沒有安全隱患。
四個可以實現自省的函數
下列方法適用于類和對象(一切皆對象,類本身也是一個對象)
1、getattr(object, name[,default])
獲取對象object的屬性或者方法,如果存在打印出來,如果不存在,打印出默認值,默認值可選。
需要注意的是,如果是返回的對象的方法,返回的是方法的內存地址,如果需要運行這個方法,
可以在后面添加一對括號。
?2、hasattr(object, name)
判斷一個對象里面是否有name屬性或者name方法,返回BOOL值,有name特性返回True, 否則返回False。
需要注意的是name要用括號括起來
3、setattr(object, name, values)
給對象的屬性賦值,若屬性不存在,先創建再賦值。
4、delattr(object, name)
刪除一個變量,刪除指定對象的指定名稱的屬性,和setattr函數作用相反,當屬性不存在的時候,會報錯,不能刪除對象的方法。
class A:pass a = A() setattr(a,'name','nezha') setattr(A,'name','alex')delattr(a,'name') print(a.name) delattr(A,'name') print(a.name)》》》 alex Traceback (most recent call last):File "D:/Python學習/Python/學習資料/學習視頻/day27/2.反射.py", line 122, in <module>print(a.name) AttributeError: 'A' object has no attribute 'name' View Code在刪除時,注意作用域。對象的屬性里沒有可以去找類的屬性,但不能去object這個父類找
三、雙下方法
內置的類方法 和 內置的函數之間有著千絲萬縷的聯系
__str__和__repr__
改變對象的字符串顯示__str__,__repr__
自定制格式化字符串__format__
#_*_coding:utf-8_*_ format_dict={'nat':'{obj.name}-{obj.addr}-{obj.type}',#學校名-學校地址-學校類型'tna':'{obj.type}:{obj.name}:{obj.addr}',#學校類型:學校名:學校地址'tan':'{obj.type}/{obj.addr}/{obj.name}',#學校類型/學校地址/學校名 } class School:def __init__(self,name,addr,type):self.name=nameself.addr=addrself.type=typedef __repr__(self):return 'School(%s,%s)' %(self.name,self.addr)def __str__(self):return '(%s,%s)' %(self.name,self.addr)def __format__(self, format_spec):# if format_specif not format_spec or format_spec not in format_dict:format_spec='nat'fmt=format_dict[format_spec]return fmt.format(obj=self)s1=School('oldboy1','北京','私立') print('from repr: ',repr(s1)) print('from str: ',str(s1)) print(s1)''' str函數或者print函數--->obj.__str__() repr或者交互式解釋器--->obj.__repr__() 如果__str__沒有被定義,那么就會使用__repr__來代替輸出 注意:這倆方法的返回值必須是字符串,否則拋出異常 ''' print(format(s1,'nat')) print(format(s1,'tna')) print(format(s1,'tan')) print(format(s1,'asfdasdffd')) View Code?
class B:def __str__(self):return 'str : class B'def __repr__(self):return 'repr : class B'b=B() print('%s'%b) print('%r'%b)%s和%r View Code # obj.__str__ str(obj) # obj.__repr__ repr(obj)class Teacher:def __init__(self,name,salary):self.name = nameself.salary = salarydef __str__(self):return "Teacher's object :%s"%self.namedef __repr__(self):return str(self.__dict__)def func(self):return 'wahaha' nezha = Teacher('哪吒',250) print(nezha) # 打印一個對象的時候,就是調用a.__str__ print(repr(nezha)) print('>>> %r'%nezha)#a.__str__ --> object # object 里有一個__str__,一旦被調用,就返回調用這個方法的對象的內存地址 # l = [1,2,3,4,5] # 實例化 實例化了一個列表類的對象 # print(l) # %s str() 直接打印 實際上都是走的__str__ # %r repr() 實際上都是走的__repr__ # repr 是str的備胎,但str不能做repr的備胎# print(obj)/'%s'%obj/str(obj)的時候,實際上是內部調用了obj.__str__方法,如果str方法有,那么他返回的必定是一個字符串 # 如果沒有__str__方法,會先找本類中的__repr__方法,再沒有再找父類中的__str__。 # repr(),只會找__repr__,如果沒有找父類的?ps:
?內建函數str()和repr() (representation,表達,表示)或反引號操作符(``)可以方便地以字符串的方式獲取對象的內容、類型、數值屬性等信息。str()函數得到的字符串可讀性好(故被print調用),而repr()函數得到的字符串通常可以用來重新獲得該對象,通常情況下 obj==eval(repr(obj)) 這個等式是成立的。這兩個函數接受一個對象作為其參數,返回適當的字符串。
事實上repr()和``做一樣的事情,返回一個對象的“官方”字符串表示。其結果絕大多數情況下(不是所有)可以通過求值運算(內建函數eval())重新得到該對象。
str()則不同,它生成一個對象的可讀性好的字符串表示,結果通常無法用eval()求值,但適合print輸出。
__del__
析構方法,當對象在內存中被釋放時,自動觸發執行。
注:此方法一般無須定義,因為Python是一門高級語言,程序員在使用時無需關心內存的分配和釋放,因為此工作都是交給Python解釋器來執行,
所以,析構函數的調用是由解釋器在進行垃圾回收時自動觸發執行的。
class Foo:def __del__(self):print('執行我啦')f1=Foo() del f1 print('------->')#輸出結果 執行我啦 ------->簡單示范__call__
Python中的__call__允許程序員創建可調用的對象(實例),默認情況下, __call__()方法是沒有實現的,這意味著大多數實例是不可調用的。然而,如果在類定義中覆蓋了這個方法,那么這個類的實例就成為可調用的。
class A:def __init__(self,name):self.name = namedef __call__(self):'''打印這個對象中的所有屬性:return:'''for k in self.__dict__:print(k,self.__dict__[k]) a = A('alex')() #后面的括號可以直接讓__call__(self)函數執行 》》》 name alex View Code?__len__
在執行len()時會自動觸發內部的__len__方法
class A:def __init__(self):self.a = 1self.b = 2def __len__(self):return len(self.__dict__) a = A() print(len(a)) View Codeitem系列
__getitem__?????? ? __setitem__??????? ?? __delitem__
類似字典的用法
class Foo:def __init__(self,name,age,sex):self.name = nameself.age = ageself.sex = sexdef __getitem__(self, item):if hasattr(self,item):return self.__dict__[item]def __setitem__(self, key, value):self.__dict__[key] = valuedef __delitem__(self, key):del self.__dict__[key]f = Foo('wangming',38,'男') print(f['name']) f['hobby'] = '男' print(f.hobby,f['hobby']) del f.hobby # object 原生支持 __delattr__ del f['hobby'] # 通過自己實現的 print(f.__dict__) View Code__new__
構造方法 : 創建一個對象
class A:def __init__(self):self.x = 1print('in init function')def __new__(cls, *args, **kwargs):print('in new function')return object.__new__(A, *args, **kwargs)a = A() print(a.x)》》》 in new function in init function 1 View Code #單例模式 #一個類 始終 只有 一個 實例 #當你第一次實例化這個類的時候 就創建一個實例化的對象 #當你之后再來實例化的時候 就用之前創建的對象class Singleton:def __new__(cls, *args, **kw):if not hasattr(cls, '_instance'):cls._instance = object.__new__(cls, *args, **kw)return cls._instanceone = Singleton() two = Singleton()two.a = 3 print(one.a) # 3 # one和two完全相同,可以用id(), ==, is檢測 print(id(one)) # 29097904 print(id(two)) # 29097904 print(one == two) # True print(one is two)單例模式單例模式 View Code__eq__
__eq__ 定義了類的等號(==)行為
可以去重
class A:def __init__(self):self.a = 5self.b = 2def __eq__(self,obj):if self.a == obj.a and self.b == obj.b:return True a = A() b = A() print(a.a) print(a.b) print(b.a) print(b.b) print(a == b)》》》 5 2 5 2 True View Code__hash__
摘要算法:密碼密文加密
摘要算法只能加密,沒有解密功能
# 摘要算法 # import hashlib # 提供摘要算法的模塊 # 不管算法多么不同,摘要的功能始終不變 # 對于相同的字符串使用同一個算法進行摘要,得到的值總是不變的 # 使用不同算法對相同的字符串進行摘要,得到的值應該不同 # 不管使用什么算法,hashlib的方式永遠不變# import hashlib # 提供摘要算法的模塊 # sha = hashlib.md5() # sha.update(b'這是密碼區') # print(sha.hexdigest())# sha 算法 隨著 算法復雜程度的增加 摘要的時間成本空間成本都會增加# 摘要算法 # 密碼的密文存儲 # 文件的一致性驗證# 在下載的時候 檢查我們下載的文件和遠程服務器上的文件是否一致# 兩臺機器上的兩個文件 你想檢查這兩個文件是否相等 # 用戶注冊 # 用戶 輸入用戶名 # 用戶輸入 密碼 # 明文的密碼進行摘要 拿到一個密文的密碼 # 寫入文件# 用戶的登錄import hashlib usr = input('username :') pwd = input('password : ') with open('userinfo') as f:for line in f:user,passwd,role = line.split('|')md5 = hashlib.md5()md5.update(bytes(pwd,encoding='utf-8'))md5_pwd = md5.hexdigest()if usr == user and md5_pwd == passwd:print('登錄成功') # 加鹽 提高密碼的安全等級 import hashlib # 提供摘要算法的模塊 md5 = hashlib.md5(bytes('鹽',encoding='utf-8')) #加鹽區可以是任意字符 # md5 = hashlib.md5() md5.update(b'123456') print(md5.hexdigest()) # 動態加鹽 提高密碼的安全等級 # 用戶名 密碼 # 使用用戶名的一部分或者 直接使用整個用戶名作為鹽 import hashlib # 提供摘要算法的模塊 md5 = hashlib.md5(bytes('鹽',encoding='utf-8')+b'') # md5 = hashlib.md5() md5.update(b'123456') print(md5.hexdigest()) # 文件的一致性校驗 # 文件的一致性校驗這里不需要加鹽?
轉載于:https://www.cnblogs.com/DI-DIAO/p/8329073.html
總結
以上是生活随笔為你收集整理的Python之面向对象四的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Longest Palindromic
- 下一篇: JNDI数据源的配置