python之路-day18-反射
一、昨日內(nèi)容回顧
類與類之間的關(guān)系
1、依賴關(guān)系。通過參數(shù)的傳遞把另外的一個類的對象傳遞進(jìn)來
2、關(guān)聯(lián)關(guān)系,組合,聚合。 通過屬性設(shè)置來維護(hù)兩個對象的關(guān)系
def __init__():
self.stuList = []
def __init__():
self.teacher = teacher
3、關(guān)于繼承
self : 誰調(diào)用的,self就是誰
4、特殊成員
__init__() 初使化方法
__new__() 構(gòu)造方法
__call__() 對象()
__add__() +
__getitem__ 對象[]
__setitem__ 對象[] = 值
__delitem__ del 對象[]?
__del__ del 對象 析構(gòu)函數(shù)
__len__ len(對象)
__iter__ for. iter()
__next__ next()
__dir__ dir()
__getslice__ 對象[::]
__hash__ hash()
__class__
__dict__ 查看當(dāng)前對象的屬性
?
?
二、isinstance , type , issubclass1、 issubclass :這個內(nèi)置函數(shù)可以幫我們判斷xxx類是否是 yyy類型的子類
?
?
? ? ? class Base:pass class Foo(Base):passclass Bar(Foo):passprint(issubclass(Bar, Foo)) # True print(issubclass(Bar, Base)) # False print(issubclass(Foo, Bar)) # True View Code?
2、type: type(obj) 表示obj是由哪個類創(chuàng)建的 ---- 用法一 class Foo:passobj = Foo() # 查看對象 obj由哪個類創(chuàng)建 print(obj , type(obj)) # <__main__.Foo object at 0x0000029B31A17080> <class '__main__.Foo'> type還可以幫我們判斷 xxx 是否是 xxx 數(shù)據(jù)類型的 ---- 用法二class Boy:passclass Girl:pass # 統(tǒng)計傳進(jìn)來的男女生數(shù)量分別是多少def func(*args):b, g = 0, 0for obj in args:if type(obj) == Boy:b += 1elif type(obj) == Girl:g += 1return b , gret = func(Boy(),Girl(),Girl(),Girl(),Girl(),Boy(),Boy(),Boy(),Boy()) print(ret) # (5, 4)?
在進(jìn)行計算時,先判斷好要計算的數(shù)據(jù)類型必須是 int 或者 float ----用法三 def add(a, b):if (type(a) == int or type(a) == float) and (type(b) == int or type(b) == float):return a + belse:print("我要報錯")?
3、isinstance 它也可以判斷xxx是yyy類型的數(shù)據(jù),但是 instance沒有type那么精準(zhǔn) class Base:passclass Foo(Base):passclass Bar(Foo):passprint(isinstance(Foo(), Foo)) # True print(isinstance(Foo(), Base)) # True print(isinstance(Bar(), Base)) # True print(isinstance(Foo(), Bar)) # False isinstance 可以判斷該對象是否是xxx家族體系中的(只能網(wǎng)上判斷)三、區(qū)分函數(shù)的方法 1、一般情況下 直接打印一下,就能區(qū)分是函數(shù)還是方法(特殊情況下不準(zhǔn)確)
def func():passprint(func) # <function func at 0x000002C283502E18>class Foo:def chi(self):print("我是吃") f = Foo() print(f.chi) # <bound method Foo.chi of <__main__.Foo object at 0x0000021DD6227320>>
函數(shù)在打印的時候,很明顯的顯示的是function, 而方法在打印的時候很明顯是method
其實(shí),并不一定是這樣的。如: class Foo():def chi(self):print("我是吃")@staticmethoddef static_method():pass@classmethoddef class_method(cls):pass f = Foo() print(f.chi) # <bound method Foo.chi of <__main__.Foo object at 0x00000284EC6E7320>>print(Foo.chi) # <function Foo.chi at 0x000001C8CC0288C8>print(Foo.static_method) #<function Foo.static_method at 0x0000028079048950>print(Foo.class_method) # <bound method Foo.class_method of <class '__main__.Foo'>>print(f.static_method) # <function Foo.static_method at 0x00000272AF6E8950>print(f.class_method) # bound method Foo.class_method of <class '__main__.Foo'>> 仔細(xì)觀察,我們能得到以下結(jié)論:
1)、類方法,不論任何情況,都是方法
2)、靜態(tài)方法,不論何種情況,都是函數(shù)
3)、實(shí)例方法,如果是實(shí)例方法,則是方法;如果是類訪問,則是函數(shù)
2、在程序里如何分辨是函數(shù)函還是方法呢?
所有的方法都MethodType的實(shí)例
所有的函數(shù)都是FunctionType的實(shí)例 from types import MethodType,FunctionTypedef func():passprint(isinstance(func, FunctionType)) # True print(isinstance(func, MethodType)) # Falseclass Foo:def chi(self):print("我要吃")@staticmethoddef static_method():pass@classmethoddef class_method(cls):passobj = Foo() print(type(obj.chi)) # method print(type(Foo.chi)) # function print(isinstance(obj.chi, MethodType)) # True print(isinstance(Foo.chi, FunctionType)) # Trueprint(isinstance(Foo.static_method, FunctionType)) # True print(isinstance(Foo.static_method, MethodType)) # Falseprint(isinstance(Foo.class_method, FunctionType)) # False print(isinstance(Foo.class_method, MethodType)) # True
?
四、反射首先我們來看一個這樣的需求,有個大牛,寫了一堆特別牛逼的代碼,然后放在了py文件里(模塊)
這時,想要用大牛寫的東西,但是,首先得直到大牛寫的這些代碼都是干什么用的。那就需要把每個函數(shù)
跑一下。
DN.pydef chi():print("大牛特別能吃")def he():print("大牛特別能喝")def la():print("大牛一次啦三斤")def sa():print("大牛一次撒幾噸")接下來錯誤的示例:這樣的寫法非常的low,假如有100個函數(shù),這個代碼就非常恐怖import DNwhile 1:print("""作為大牛,我?guī)湍銓懥?#xff1a;chihelasa等功能,自己看看吧""")func = input("輸入你想要測試的功能:")if func == "he":DN.chi()elif func == "chi":DN.chi()。。。。。。正確的打開姿勢:import DNwhile 1:print("""作為??, 我?guī)湍銓懥?chihelashui 等功能. ??看看吧""")gn = input("請輸?你要測試的功能:")# niuB版func = getattr(DN, gn)func()getattr(對象,字符串):從對象中獲取到xxx功能。此時xxx是一個字符串。get表示找 attr表示屬性(功能)。但是這里有個問題,假如手一抖,輸入錯了,在大牛的代碼里沒有找到想要的內(nèi)容,那么這個時候就會報錯。所以在getattr之前,要先判斷有沒有import DN from types import FunctionType while 1:print("""作為??, 我?guī)湍銓懥?chihelashui 等功能. ??看看吧""")gn = input("請輸?你要測試的功能:")# niuB版if hasattr(DN, gn): # 如果master??有你要的功能# 獲取這個功能, 并執(zhí)?attr = getattr(DN, gn)# 判斷是否是函數(shù). 只有函數(shù)才可以被調(diào)?if isinstance(attr, FunctionType):attr()else:# 如果不是函數(shù), 就打印print(attr)
?
總結(jié):getattr可以從模塊中獲取內(nèi)容,在python中一切皆為對象。那可以這樣認(rèn)為。getattr()從對象中動態(tài)的獲取內(nèi)容
補(bǔ)充:
關(guān)于反射,其實(shí)一共有4個函數(shù):
1、hasattr(obj, str) 判斷obj中是否包含str成員
2、getattr(obj, str) 從obj中獲取 str成員
3、setattr(obj,str,value) 把obj中的str成員設(shè)置成value。注意,這里的value
可以是值,也可以是函數(shù)或者方法
4、defattr(obj, str) 把obj中的str成員刪掉
注意:以上的操作都是在內(nèi)存中進(jìn)行的,并不會影響源代碼 class Foo:pass f = Foo()print(hasattr(f, "chi")) # False setattr(f, "chi", "123")print(f.chi) # 被添加了?個屬性信息 setattr(f, "chi", lambda x: x + 1) print(f.chi(3)) # 4print(f.chi) # 此時的chi既不是靜態(tài)?法, 也不是實(shí)例?法, 更不是類?法. 就相當(dāng)于你在類中 # 寫了個self.chi = lambda 是?樣的 print(f.__dict__) # {'chi': <function <lambda> at 0x107f28e18>} delattr(f, "chi") print(hasattr(f, "chi")) # False
?
五、MD5 加密1、md5特點(diǎn):不可逆的一種加密方式,最多用在密碼加密上
2、實(shí)例: import hashlib# 創(chuàng)建md5的對象 obj = hashlib.md5() # 給obj設(shè)置明文 obj.update("alex".encode("utf-8")) # update傳入多的內(nèi)容需為byte類型 # 獲取密文 result = obj.hexdigest() # haxdigest hax是16進(jìn)制,digest是摘要 print(result) # 534b44a19bf18d20b71ecc4eb77c572f
3、以上為粗略的md5小試,此方法產(chǎn)生的密文容易被撞庫破解,下面的是改進(jìn)版 import hashlibSALT = b"alex" # 加鹽 此方法可有效的防止被撞庫 obj = hashlib.md5(SALT) obj.update("alex".encode("utf-8")) result = obj.hexdigest() print(result) # 0bf4375c81978b29d0f546a1e9cd6412# # md5 的整理使用 def md5_method(content):obj = hashlib.md5(SALT)obj.update(content.encode("utf-8"))return obj.hexdigest()# 4、 MD5的應(yīng)用# 注冊 # alex 123 ---》 b75bd008d5fecb1f50cf026532e8ae67 username = input("用戶名:") password = input("密碼:") password = md5_method(password)# 登錄 uname = input("用戶名:") pwd = input("密碼:") if md5_method(pwd) == password and uname == username:print("登錄成功") else:print("失敗")
?
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/alvin-jie/p/9936225.html
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎總結(jié)
以上是生活随笔為你收集整理的python之路-day18-反射的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 面试题56: 数组中数字出现的次数
- 下一篇: 在本地生成ssh-key 免密码远程cl
