python學習 day018打卡 反射

AF1y發表於2018-11-09

本節主要內容:

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沒有issubclass() 那麼精準.

class Base:
    pass

class Foo(Base):
    pass

class Bar(Foo):
    pass

print(isinstance(Bar,Foo))  # True
print(isinstance(Foo,Bar))  # False
print(isinstance(Bar,Base)) # False

 

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

 

相關文章