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成員刪除掉
注意, 以上操作都是在記憶體中進行的. 並不會影響你的源代