python記錄_day18 反射 判斷函式與方法
一、三個內建函式
1、issubclass(a, b) 判斷a類是否是b類的子類
1 class Foo: 2 pass 3 4 class Zi(Foo): 5 pass 6 7 class Sun(Zi): 8 pass 9 print(issubclass(Zi,Foo)) #True 10 print(issubclass(Zi,Sun)) # Falseissubclass
2、type(物件) 返回該物件的資料型別,精確識別(即不向上相容)
1 class Animal: 2 pass 3 4typeclass Cat(Animal): 5 pass 6 7 class BosiCat(Cat): 8 pass 9 10 c = Cat() 11 b = BosiCat() 12 print(type(c)) #<class '__main__.Cat'> 會準確說出c是一種Cat,不會說c是一種Animal
3、isinstance(物件,類) 判斷xx物件是否是xxx類 (向上相容)
class Animal: pass class Cat(Animal): pass class BosiCat(Cat):isinstacepass c = Cat() b = BosiCat() print(isinstance(c , Cat)) #判斷c 是否是一種Cat print(isinstance(c,Animal)) #判斷c 是否是一種Animal print(isinstance(c,BosiCat)) 結果: True True False
二、判斷函式與方法
python官方定義:
函式function —— A series of statements which returns some value to a caller. It can also be passed zero or more arguments which may be used in the execution of the body.
方法method —— A function which is defined inside a class body. If called as an attribute of an instance of that class, the method will get the instance object as its first argument (which is usually called self).
從定義看,函式就相當於一個數學公式,它不與其他東西相互關聯,傳遞相應的引數就能用。而方法是,定義在類內部的函式,並且這個函式和類或類的例項物件有某種關聯,訪問時會自動傳遞一個引數作為第一引數。
簡單來說:
函式沒和類或物件進行繫結;
方法和類或物件有繫結
# 區分函式和方法:
1 def func(): 2 pass 3 print(func) # <function func at 0x10646ee18> 函式 4 class Foo: 5 6 def chi(self): 7 print("我是吃") 8 f = Foo() 9 print(f.chi) # <bound method Foo.chi of <__main__.Foo object at 10 0x10f688550>> 方法函式和方法
1 class Foo: 2 def chi(self): 3 print("我是吃") 4 @staticmethod 5 def static_method(): 6 pass 7 @classmethod 8 def class_method(cls): 9 pass 10 11 f = Foo() 12 13 print(f.chi) # <bound method Foo.chi of <__main__.Foo object at 14 0x10f688550>> 15 16 print(Foo.chi) # <function Foo.chi at 0x10e24a488> 17 print(Foo.static_method) # <function Foo.static_method at 0x10b5fe620> 18 print(Foo.class_method) # bound method Foo.class_method of <class 19 '__main__.Foo'>> 20 21 print(f.static_method) # <function Foo.static_method at 0x10e1c0620> 22 print(f.class_method) #<bound method Foo.class_method of <class 23 '__main__.Foo'>>函式和方法
結論:
1. 類方法. 不論任何情況, 都是方法.
2. 靜態方法, 不論任何情況. 都是函式
3. 例項方法, 如果是例項訪問. 就是方法. 如果是類名訪問就是函式.
#官方判斷方法:
通過types模組引入MethodType FunctionType 來判斷
1 from types import FunctionType, MethodType 2 3 class Car: 4 def run(self): # 例項方法 5 print("我是車, 我會跑") 6 7 @staticmethod 8 def cul(): 9 print("我會計算") 10 11 @classmethod 12 def jump(cls): 13 print("我會jump") 14 15 c = Car() 16 17 例項方法: 18 # 1. 用物件.方法 方法 19 # 2. 類名.方法 函式 20 c = Car() 21 print(isinstance(c.run, FunctionType)) # False 22 print(isinstance(Car.run, FunctionType)) # True 23 print(isinstance(c.run, MethodType)) # True 24 print(isinstance(Car.run, MethodType)) # False 25 26 # 靜態方法 都是函式 27 print(isinstance(c.cul, FunctionType)) # True 28 print(isinstance(Car.cul, FunctionType)) # True 29 print(isinstance(c.cul, MethodType)) # False 30 print(isinstance(Car.cul, MethodType)) # False 31 32 # 類方法都是方法 33 print(isinstance(c.jump, FunctionType)) # False 34 print(isinstance(Car.jump, FunctionType)) # False 35 print(isinstance(c.jump, MethodType)) # True 36 print(isinstance(Car.jump, MethodType)) # True判斷
三、反射(重點)
關於反射, 其實一共有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成員刪除掉
注意:
obj可以是模組,類,例項物件
以上操作都是在記憶體中進行的, 並不會影響你的原始碼,但是在同一個py檔案中,你通過反射修改了類,是會影響到其他物件的。
1 #反射用到的四個函式,常用的是hasattr 和getattr 2 # setattr(a,b,c) a是要操作的物件,b是操作物件中的成員字串形式,c是修改的值 3 # getattr(a,b) 有返回值,返回值形式a.b a是要操作的物件,b是操作物件中的成員字串形式 4 #delattr(a,b) a是要操作的物件,b是操作物件中的成員字串形式 5 #hasatter(a,b) a是要操作的物件,b是操作物件中的成員字串形式 6 7 class Car: 8 9 def __init__(self,color,pai,price): 10 self.color = color 11 self.pai = pai 12 self.price= price 13 14 def fly(self): 15 print('我的車會飛') 16 17 c = Car('blue','豐田','18888') 18 f = getattr(Car,"fly") #操作物件是類,返回值相當於Car.fly 19 print(f) #<function Car.fly at 0x0000000001EA9D08> 這裡是函式,沒有和類繫結,所以需要下面手動傳值 20 f(c) # f是函式,沒有和類繫結,所以需要手動傳值Car.fly(c) ,它是等價於c.fly()的 21 22 #delattr(Car,"fly") #操作的是類,把類中fly方法刪除了 23 #c.fly() #報錯,沒有fly 24 25 c2 =Car("yellow","bmw",20000) 26 27 def fly(): 28 print("通過物件c修改fly方法") 29 30 setattr(c,"fly",fly) #並沒有改變類中的內容,相當於在當前物件中建立了一個fly方法,一個物件是不可能有修改類的許可權的 31 c.fly() #通過物件c修改fly方法 32 c2.fly() #我的車會飛 33 c3 = Car("blue","賓士",88888) 34 c3.fly() #我的車會飛 35 setattr(Car,'fly',lambda self:print('通過類名,修改fly方法')) #通過類名修改fly方法 36 c.fly() #通過物件c修改fly方法 37 c2.fly() #通過類名,修改fly方法 38 c3.fly() #通過類名,修改fly方法 39 c4 = Car("red","悍馬",66666) 40 c4.fly() #通過類名,修改fly方法