1. 程式人生 > >類的反射介紹和應用

類的反射介紹和應用

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Time    : 2018/5/20 23:27
# @Author  : chen
# @File    : 反射.py

"""
# 反射: 通過字串對映到物件的屬性
"""


"""
class People:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def talk(self):
        print('%s is talking' % self.name)


obj = People('egon', 18)

print(obj.name)  # .(點)後面是一個屬性,不是字串,
# 本質上是  obj.__dict__['name'] 是隱藏字典裡key為'name'的值
print(obj.talk)  # 點後面一定時一個屬性,不是字串
print(obj.talk())


# 接受使用者的輸入,使用input方法,接收內容都轉化為字串

# 需求,根據使用者輸入 返回物件的屬性
# choice = input('>>: ')
# print(obj.choice)   # 會直接報錯(AttributeError: 
# 'People' object has no attribute 'choice'),點後面應該是屬性,而不是字串


# 1.python 內建方法  hasattr,有兩個引數,第一個是物件,第二個是例項的屬性
# 只能返回True 和 False
print(hasattr(obj, 'name'))  # 實際操作等於 obj.name 等同於  obj.__dict__['name']
print('attribute_talk', hasattr(obj, 'talk'))  # obj.talk
print('attribute_talka', hasattr(obj, 'talka'))  # obj.talk


# 2.getattr() 跟hasattr差不多,但不存在的屬性可以加引數不報錯
# 第一個,第二個引數跟hasattr一樣,第三個指定返回的結果(字串)
print(getattr(obj, 'talk', None))  # 當呼叫的是類的方法時,返回的結果是繫結類的方法的地址
# 如果是屬性就直接返回結果
print(getattr(obj, 'namexxxx', None))
print(getattr(obj, 'namexxxx', 'Error'))


# 3.以字串的形式 ,設定屬性(新增)
setattr(obj, 'sex', 'male')  # obj.sex = 'male'
print(obj.sex)


# 4. 以字串形式  刪除屬性
delattr(obj, 'age')  # obj.age
print(obj.__dict__)
"""
""" class People: country = 'China' def __init__(self, name, age): self.name = name self.age = age def talk(self): print('%s is talking' % self.name) obj = People('egon', 18) # 5. 同時適用於類,判斷類中有沒有國籍這個屬性 print(getattr(People, 'country')) # People.country # 通過字串,訪問物件,類的屬性 """
# 反射的應用 # 接收使用者輸入,觸發查詢屬性 class Service: def run(self): while True: inp = input('>>: ').strip() # cmd = 'get a.txt' cmds = inp.split() # cmds = ['get', 'a.txt'] if len(cmds) == 2: # 判斷使用者輸入是否正確 if hasattr(self, cmds[0]): # 這裡要使用self,不能隨便使用別的,我使用的Service,報錯了,就是因為傳參問題
func = getattr(self, cmds[0]) func(cmds[1]) else: print('has no attribute') else: print('your cmds is wrong') def get(self, cmds): print('get......', cmds) def put(self): print('put......') obj = Service() obj.run()

getattr反射的使用

getattr(class,‘str’)
第一個引數填class,第二個使用的是字串(函式名)

另外一種用法
getattr(class,‘str’),第一個引數是模組名稱,第二個是類名

import sys

class Course:
    def __init__(self, name, period, price):
        self.name = name  # 課程名
        self.period = period  # 課程週期
        self.price = price  # 課程價格

print('type型別:', type(sys.modules[__name__]), '值結果:', sys.modules[__name__])
s = getattr(sys.modules[__name__], 'Course')
print('s的type型別:', type(s))
a = s('egon', '6 months', 19800)
print('a的type型別:', type(a))
print('a的name屬性:', a.name)

輸出結果:

type型別: <class 'module'> 值結果: <module '__main__' from 'D:/python_product/select_homework/core/Teacher.py'>
s的type型別: <class 'type'>
a的type型別: <class '__main__.Course'>
a的name屬性: egon

==================================================================
sys.modules[__name__] # 表示當前模組的名稱
雖然當前模組沒有類,但是使用了import後,將會把匯入模組的類放到當前模組的區域性變數中
於是,再獲取當前模組的類就會有了類名
使用反射就能獲取到對應的類,加括號即可執行