1. 程式人生 > >isinstance type issubclass 區分方法和函式 反射:hasattr getattr setattr delattr

isinstance type issubclass 區分方法和函式 反射:hasattr getattr setattr delattr

isinstance      type      issubclass


  isinstance: 判斷你給物件是否是xx型別的. (向上判斷)


  type: 返回xxx物件的資料型別


  issubclass: 判斷xxx類是否xxx的子類

class Animal:
    def eat(self):
        print("剛睡醒吃點兒東西")

class Cat(Animal):
    def play(self):
        print("貓喜歡玩兒")

c = Cat()

print
(isinstance(c, Cat)) # c是一隻貓 這裡判斷c是不是Cat類裡面的 print(isinstance(c, Animal)) # 向上判斷 這裡判斷c是不是Animal類裡面的 a = Animal() print(isinstance(a, Cat)) # 不能向下判斷 print(type(a)) # 返回 a的資料型別 print(type([])) print(type(c)) # 精準的告訴你這個物件的資料型別 # 判斷.xx類是否是xxxx類的子類 print(issubclass(Cat, Animal)) print(issubclass(Animal, Cat))
# 應用 def cul(a, b): # 此函式用來計算數字a和數字b的相加的結果 # 判斷傳遞進來的物件必須是數字. int float if (type(a) == int or type(a) == float) and (type(b) == int or type(b) == float): return a + b else: print("對不起. 您提供的資料無法進行計算") print(cul(a, c))

 

 如何區分方法和函式(程式碼)


在類中:


例項方法


  如果是類名.方法   函式


  如果是物件.方法    方法


類方法:                都是方法

靜態方法:             都是函式

from types import MethodType, FunctionType
isinstance()

def func():
    print("我是函式")

class Foo:
    def chi(self):
        print("我是吃")

# print(func) # <function func at 0x0000000001D42E18>
f = Foo()
# f.chi()

print(f.chi) # <bound method Foo.chi of <__main__.Foo object at 0x0000000002894A90>>

# 野路子:
這裡列印了方法或者函式的名字
列印的結果中包含了function. 函式
#             method  .  方法

我們的類也是物件.
這個物件: 屬性就是類變數
方法就是類方法

class Person:
    def chi(self):
        print("我要吃魚")

    @classmethod
    def he(cls):
        print("我是類方法")

    @staticmethod
    def pi():
        print("泥溪鎮地皮")

p = Person()
Person.chi(1)  # 不符合面向物件的思維
#這裡直接使用類名.方法 其實是沒有經過物件的,所以不符合面向物件的思維,雖然這裡可以使用,但是千萬不要用
print(p.chi) # <bound method Person.chi of <__main__.Person object at 0x00000000028C4B70>> print(Person.chi) # <function Person.chi at 0x00000000028989D8> 例項方法: 1. 如果使用 物件.例項方法 方法 2. 如果使用 類.例項方法 函式 print(Person.he) # <bound method Person.he of <class '__main__.Person'>> print(p.he) # <bound method Person.he of <class '__main__.Person'>> 類方法都是 方法 print(Person.pi) # <function Person.pi at 0x0000000009E7F488> print(p.pi) # <function Person.pi at 0x0000000009E7F488> 靜態方法都是函式 # 記下來 from types import FunctionType, MethodType # 方法和函式 匯入的是函式 和方法模組 from collections import Iterable, Iterator #可迭代的 迭代器 例項:


class Person: def chi(self): # 例項方法 print("我要吃魚") @classmethod def he(cls): print("我是類方法") @staticmethod def pi(): print("泥溪鎮地皮") p = Person() print(isinstance(Person.chi, FunctionType)) # True print(isinstance(p.chi, MethodType)) # True print(isinstance(p.he, MethodType)) # True print(isinstance(Person.he, MethodType)) # True print(isinstance(p.pi, FunctionType)) # True print(isinstance(Person.pi, FunctionType)) # True

在這裡,就可以得出結論:

在類中:

例項方法    如果是類名.方法   函式

                  如果是物件.方法    方法


類方法:                都是方法

靜態方法:             都是函式

from types import MethodType, FunctionType
isinstance()

 ___________________________________________________________________________

反射.         

首先, 我們看這樣⼀個需求, 說, 有個大牛, 寫了⼀堆特別牛B的程式碼. 然後放在了⼀個py ⽂件裡(模組), 這時, 你想⽤這個大⽜寫的東西. 但是呢. 你⾸先得知道⼤牛寫的這些程式碼都是 幹什麼用的. 那就需要你把⼤牛寫的每一個函式跑一下. 摘一摘⾃己想用的內容. 來咱們模擬 這樣的需求, 首先, ⼤牛給出⼀個模組. 

 

import master   # 報錯不用管    這裡匯入模組

print("""
    1. chi:  大牛特別能吃
    2. he: 大牛特別能喝
    3. shui: 大牛特別能睡
    4. play: 大牛特別能玩兒
    5. sa: 大牛很喜歡撒謊
""")
while 1:
    content = input("請輸入你要執行的函式:")
    if content == "1":
        master.chi()
    elif content == "2":
        master.he()
    elif content =="3":
        master.shui()
    elif content == "4":
        master.play_1()
    elif content == "5":
        master.sa()

  寫是寫完了. 但是.....如果⼤牛現在寫了100個功能呢?  你的判斷要100次麼? 太累 了吧.  現有的知識解決不了這個問題. 那怎麼辦呢?  注意看. 我們可以使⽤反射來完成這樣的功能. 非常的簡單. 想想. 這里我們是不是讓使用者輸入要執行的功能了. 那這個功能就是對應 模組里的功能.  那也就是說. 如果能通過字元串來動態訪問模組中的功能就能解決這個問題. 好了. 我要告訴你. 反射解決的就是這個問題.   為什什麼叫反射?  反著來啊.  正常是我們先引入 模組, 然後⽤模組去訪問模組里的內容. 現在反了. 我們⼿動輸入要運行的功能. 反著去模組 里找.  這個就叫反射

 
 
import master   #匯入模組

while
1: content = input("請輸入你要測試的功能:") # 使用者輸入的功能是一個字串 # 判斷 xxx物件中是否包含了xxxxx if hasattr(master, content): xx = getattr(master, content) xx() print("有這個功能") else: print('沒有這個功能')

 

 

關於反射, 其實⼀一共有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成員刪除掉

注意, 以上操作都是在記憶體中進行的. 並不會影響你的原始碼

 

# 對於模組而言可以使用getattr, hasattr, 同樣對於我們的物件也可以執行類似的操作

class Person:
    def __init__(self, name, laopo):
        self.name = name
        self.laopo = laopo


p = Person("寶寶", "林志玲")

print(hasattr(p, "laopo")) #
print(getattr(p, "laopo")) # p.laopo

setattr(p, "laopo", "胡一菲") # p.laopo = 胡一菲
setattr(p, "money", 100000000000) # p.money = 100000000

print(p.laopo)
print(p.money)

delattr(p, "laopo") # 把物件中的xxx屬性移除.  != p.laopo = None
print(p.laopo)#####會報錯
______________________

True
林志玲
胡一菲
100000000000

最後移除了laopo這個屬性,所以會報錯

 
 

關於反射, 其實一共有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成員刪除掉

注意, 以上操作都是在記憶體中進行的. 並不會影響你的源代