python學習 day018打卡 反射
本節主要內容:
1.isinstance,type,issubclass
2.區分函式和方法
3.反射(重點)
一.isinstance,type,issubclass
issubclass():判斷xxx類是否是yyy型別的子類
class Base: pass class Foo(Base): pass class Bar(Foo): pass print(issubclass(Bar,Foo)) # True print(issubclass(Foo,Bar)) # False print(issubclass(Bar,Base)) # Ture
type(obj):檢視obj是由哪個類建立的.
class Foo: pass obj = Foo() print(type(obj)) # <class '__main__.Foo'>
type()可以幫我們判斷xxx是否是xxx資料型別的
class Boy: pass class Girl: pass # 統計傳進來的男生和女生分別有多少 def func(*args): b=0 g=0 for obj in args: if type(obj) == Boy: b+=1 elif type(obj) == Girl: g += 1 return b,g ret = func(Boy(),Girl(),Boy(),Girl(),Boy(),Girl(),Boy()) print(ret)
isinstance() 也可以判斷xxx是否是xxx型別的資料,但是isinstance沒有type() 那麼精準.
class Base: pass class Foo(Base): pass class Bar(Foo): pass print(issubclass(Bar,Foo)) # True print(issubclass(Foo,Bar)) # False print(issubclass(Bar,Base)) # Ture
isinstance可以判斷該物件是否是xxx家族體系中的(只能往上判斷)
二,區分函式和方法
def func(): pass print(func) #<function func at 0x00000265B9E12E18> class Foo: def chi(self): print("我是吃") foo = Foo() print(foo.chi) # <bound method Foo.chi of <__main__.Foo object at 0x00000265BA00C908>>
函式在列印的時候,很明顯顯示的是function.而方法在列印的時候很明顯是method.但是在類裡面就不一定了:
class Foo: def chi(self): print("我是吃") @staticmethod def static_method(): pass @classmethod def class_method(cls): pass f = Foo() print(f.chi) # <bound method Foo.chi of <__main__.Foo object at 0x0000016B23AEC978>> print(Foo.chi) # <function Foo.chi at 0x0000016B23ACDF28> print(Foo.static_method) # <function Foo.static_method at 0x0000016B23AF4048> print(Foo.class_method) # <bound method Foo.class_method of <class '__main__.Foo'>> print(f.static_method) # <function Foo.static_method at 0x0000016B23AF4048> print(f.class_method) # <bound method Foo.class_method of <class '__main__.Foo'>>
通過觀察上面程式碼的結果,我們可以得出以下結論:
1.類方法.不論任何情況,都是方法.
2.靜態方法,不論任何情況,都是函式.
3.例項方法,如果是物件去訪問,就是方法.如果是類名訪問就是函式.
我們可以通過藉助types模組來幫我們分辨到底誰是函式,誰方法
from types import FunctionType, MethodType class Car: def run(self): # 例項方法 print("我是車, 我會跑") @staticmethod def cul(): print("我會計算") @classmethod def jump(cls): print("我會jump") # 例項方法: # 1. 用物件.方法 方法 # 2. 類名.方法 函式 c = Car() # print(isinstance(c.run, FunctionType)) # False # print(isinstance(Car.run, FunctionType)) # True # print(isinstance(c.run, MethodType)) # True # print(isinstance(Car.run, MethodType)) # False # 靜態方法 都是函式 # print(isinstance(c.cul, FunctionType)) # True # print(isinstance(Car.cul, FunctionType)) # True # print(isinstance(c.cul, MethodType)) # False # print(isinstance(Car.cul, MethodType)) # False # 類方法都是方法 print(isinstance(c.jump, FunctionType)) # False print(isinstance(Car.jump, FunctionType)) # False print(isinstance(c.jump, MethodType)) # True print(isinstance(Car.jump, MethodType)) # True # FunctionType:函式 # MethodType: 方法
插入: 我們寫的類也可以看做是物件,類的型別是type,即type(類) ==><class 'type'>
三.反射
反射:所謂反射就是通過字串來動態訪問模組中的功能.通過手動輸入需要執行的功能,反著去模組裡找,這個就叫反射
# master.py def chi(): print("大牛很能吃") def he(): print("大牛從來不喝") def la(): print("大牛就知道拉") def sa(): print("大牛說撒是什麼")
import master while True: s = input("請輸入你要測試的功能:") if hasattr(master,s): func = getattr(master,s) func() else: print("你輸入的是個啥玩意兒啊")
裡面涉及到的兩個函式---getattr(), hasattr()
getattr()用來獲取資訊
hasattr()用來判斷xxx中是否包含了xxx功能.
class Person: country = "大清" def chi(self): pass # 類中的內容可以這樣動態獲取 print(getattr(Person,"country")) print(getattr(Person,"chi")) # 相當於Foo.func 函式 # 物件一樣可以 obj = Person() print(getattr(obj,"country")) print(getattr(obj,"chi")) # 相當於obj.func 方法
總結,getattr()可以從模組中獲取內容,也可以從類中獲取內容,也可以從物件中獲取內容.在python中一切皆為物件,那可以這樣認為.getattr從物件中動態的獲取成員
關於反射,一共有4個函式:
1.hasattr(obj,str)判斷obj中是否包含str成員
2.getattr(obj,str)從obj中獲取str成員
3.setattr(obj,str,value)吧obj中的str成員設定成value.注意,這裡的value可以是值,也可以是函式或者方法.如果str不存在,就建立新的成員,把值賦值給新成員
4.delattr(obj,str)把obj中的str成員刪除掉
注意,以上操作都是在記憶體中進行的,並不會影響你的原始碼
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)) # 4 print(f.chi) # 此時的chi既不是靜態方法,也不是例項方法,更不是類方法.就相當於你在類中寫了個self.chi = lambda 是一樣的 print(f.__dict__) # {'chi': <function <lambda> at 0x00000238E1392E18>} delattr(f,"chi") print(hasattr(f,"chi")) # False