1. 程式人生 > >第十八天- 型別判斷 函式和方法判斷 反射

第十八天- 型別判斷 函式和方法判斷 反射

 

# isinstance  type  issubclass 內建函式:

# 1.issubclass() 這個內建函式可判斷xxx類是否是yyy型別的子類
# issubclass(子類,父類)
 1 class Base:
 2     pass
 3 
 4 class Foo(Base):
 5     pass
 6 
 7 class Bar(Foo):
 8     pass
 9 
10 print(issubclass(Bar,Foo)) # True
11 print(issubclass(Foo,Bar)) # False
12 print
(issubclass(Bar,Base)) # True 可以隔代判斷
View Code
1 # 補充:object是所有類的根,面向物件的祖宗
2 # print(issubclass(Foo,object))  # True
3 # print(issubclass(Bar,object))  # True
4 # print(issubclass(Base,object)) # True

 

# 2.type(xxx) 返回該物件的資料型別
1 class Foo:
2     pass
3 obj = Foo()
4 # print(obj,type(obj)) # <class '__main__.Foo'> Foo類
# type 精準的返回資料型別
1 # type 精準的返回資料型別
2 def cul(a,b):  # 計算兩個引數的和(判斷是否int float類)
3     if(type(a) == int or type(a) == float) and (type(b) == int or type(b) == float):
4         return a + b
5     else:
6         print("不能幫你計算")
7 
8 # print(cul(10,20))
9 # print(cul(10,"哈哈哈"))
View Code

 

# 3.isinstance 判斷xxx是否是一種yyy(包括父類)
 1 class Animal:
 2     pass
 3 
 4 class Cat(Animal):  # x是一種y. x繼承y
 5     pass
 6 
 7 class BosiCat(Cat):
 8     pass
 9 
10 tom = Cat()
11 print(isinstance(tom,Cat))  # True
12 print(isinstance(tom,Animal)) # True  判斷tom是否是一種Animal(包括父類)
13 print(isinstance(tom,BosiCat)) # False
14 # 只能往上判斷 不可往下.如.可以說貓是一種動物.但不可說貓是一種波斯貓

 

 

# 判斷方法和函式 :
# 1.print列印方法區分
 1 class Foo:
 2     def chi(self):
 3         print("我是吃")
 4 
 5     @staticmethod
 6     def he():
 7         pass
 8 
 9     @classmethod
10     def shui(cls):
11         pass
12 
13 f = Foo()
14 print(f.chi) # 方法 <bound method Foo.chi of <__main__.Foo object at 0x000002B3F3FD3438>>
15 print(Foo.chi) # 函式 <function Foo.chi at 0x000002B3F3FC8A60>
16 print(Foo.he) # 函式 <function Foo.he at 0x0000013B49F38B70
17 print(Foo.shui) # 方法 <bound method Foo.shui of <class '__main__.Foo'>>
View Code

 

# 2.用types模組判斷區分
# 所有的⽅法都是MethodType的例項
# 所有的函式都是FunctionType的例項
 1 from types import MethodType,FunctionType  # 固定開頭
 2 def func():
 3     pass
 4 
 5 print(isinstance(func,FunctionType))  #  True
 6 print(isinstance(func,MethodType)) # False
 7 
 8 class Foo1:
 9     def chi(self):
10         print("我是吃")
11 
12     @staticmethod
13     def he():
14         pass
15 
16     @classmethod
17     def shui(cls):
18         pass
19 
20 test = Foo1()
21 # 例項方法
22 print(type(test.chi))  # <class 'method'>
23 print(type(Foo.chi))  # <class 'function'>
24 print(isinstance(test.chi,MethodType)) # True 物件呼叫時是方法
25 print(isinstance(Foo.chi,FunctionType)) # True 類呼叫時是函式
26 
27 # 靜態方法
28 print(isinstance(Foo.he,FunctionType)) # True
29 print(isinstance(Foo.he,MethodType))  # False
30 
31 # 類方法
32 print(isinstance(Foo.shui,FunctionType)) # False
33 print(isinstance(Foo.shui,MethodType)) # True
View Code
'''
總結---
類方法:任何情況都是方法
靜態方法:任何情況都是函式
例項方法:物件使用是方法,類使用是函式
'''


# 反射:
# 關於反射, ⼀共有4個函式:
# 1. hasattr(obj, str) 判斷obj中是否包含str成員
# 2. getattr(obj,str) 從obj中獲取str成員
# 3. setattr(obj, str, value) 把obj中的str成員設定成value.注意.這⾥的value可以是值,也可以是函式或者⽅法
# 4. delattr(obj, str)把obj中的str成員刪除掉
# 注意,反射操作都是在記憶體中進⾏的.並不會影響你的原始碼
 1 ''' 例子:我們看這樣⼀個需求,說,有個⼤⽜,寫了⼀堆特別⽜B的程式碼.然後放在了⼀個py⽂件⾥(模組),這時,你想⽤這個⼤⽜寫的東⻄.但是.你⾸先得知道⼤⽜寫的這些程式碼都是⼲什麼⽤的.那就需要你把⼤⽜寫的每⼀個函式跑⼀下.摘⼀摘⾃⼰想⽤的內容.我們來模擬這樣的需求.'''
 2 
 3 # 大佬給出的模組
 4 
 5 def chi():
 6     print("胖虎很能吃")
 7 
 8 def he():
 9     print("胖虎很能喝")
10 
11 def la():
12     print("胖虎很能拉")
13 
14 def sa():
15     print("胖虎很能撒")
16 
17 def shui():
18     print("胖虎一睡一年")
19 
20 
21 import master
22 
23 # 注意:以下改動是在記憶體裡改變master內容,而不是改變原始檔
24 # hasattr() 查
25 # getattr() 拿
26 # setattr() 改
27 # delattr() 刪
28 
29 print('''作為大牛,我幫你寫了:
30     chi
31     he
32     la
33     sa
34     shui
35 等功能,你看著用吧''')
36 while 1:
37 
38     s = input("請輸入你要測試的功能,q退出\n")
39     if s.strip().upper() == "Q":
40         break
41     if hasattr(master,s): # 獲取之前先判斷是否存在這個功能,避免報錯
42         func = getattr(master,s)  # 獲取這個功能 再執行
43         func()
44     else:
45         print("我看你是在為難我胖虎!")
46 
47 
48 #我對大牛的功能不太滿意想刪改,但又不想改動大牛原始檔
49 
50 # 我寫的功能
51 def chi():
52     print("胖虎說的不對,胖虎超級能吃")
53 
54 # 改變
55 setattr(master,"chi",chi)  # 此時再執行上面迴圈就變成我改的程式碼了
56 
57 #如果不想改動大牛的,又想還有自己的
58 setattr(master,"xinchi",chi)  # 即原master沒有這功能,我新增 'xinchi'
59 
60 # 如上可知 setattr與字典類似有就改沒有就新增
61 
62 # 再來看看刪除 delattr
63 # delattr() 刪掉快取中的chi
64 delattr(master,"chi")  # 第二個引數注意是字元相當於字典的"key"
65 
66 
67 
68 # 以上操作即是反射,反著來. 正常是我們先引入模組, 然後⽤模組去訪問模組⾥的內容. 現在反了. 我們⼿動輸入要運⾏的功能. 反著去模組⾥找. 這個就叫反射。 同樣的也適用與物件和類,可理解成動態的獲取修改,程式結束一切又清空,不會對原始檔造成改動。
View Code

 

 

# md5 加密:不可逆的一種加密方式 多用於密碼加密,檔案驗證中
 1 # 建立 加銘文 獲取密碼都是固定操作
 2 import hashlib
 3 
 4 # 加鹽 防止撞庫 大幅度提高密碼安全等級
 5 SALT = b"fasjfuhfofhfafjafjjjpjhfiahfohioihofsfkhf890%$fl131213.,,["
 6 
 7 # 建立md5的物件
 8 obj = hashlib.md5(SALT)  # 加鹽
 9 # 給obj設定銘文
10 obj.update("IG牛逼".encode("utf-8"))
11 # 獲取到密文
12 secret = obj.hexdigest()
13 
14 print(secret)  # e31f4e0214b7f355c8b1bb6dff5bf4ae
View Code
# 函式MD5加密
 1 # 用函式來執行上面內容
 2 
 3 import hashlib
 4 
 5 def jiami(content):
 6     obj = hashlib.md5(SALT)
 7     obj.update(content.encode("utf-8"))
 8     return obj.hexdigest()
 9 
10 # 註冊
11 username = input("請輸入你的使用者名稱:\n")
12 password = input("請輸入你的密碼:\n")
13 password = jiami(password)
14 print(password)   # 78012ff9df2569139c05847e622c4943
15 
16 # 登入
17 username1 = input("請輸入你的使用者名稱:\n")
18 password1 = input("請輸入你的密碼:\n")
19 
20 if username1 == username  and jiami(password1) == password:
21     print("登入成功!")
22 else:
23     print("登入失敗!")
View Code