面向对象 -- 反射(详细)

使用对象反射

obj . 属性名

obj . 方法名()

可以直接适用对象的方法和属性

当我们只有字符串数据类型的内容的时候

可以使用

getattr(对象名,'方法名')() 来调用方法

getattr(对象名,'属性名') 来调用属性

1.使用对象反射
class Manager:   # 管理员用户
    def __init__(self,name):
        self.name  = name
    def create_course(self):  # 创建课程
        print('in Manager create_course')

    def create_student(self): # 给学生创建账号
        print('in Manager create_student')

    def show_courses(self): # 查看所有课程
        print('in Manager show_courses')

    def show_students(self): # 查看所有学生
        print('in Manager show_students')

不用反射
alex = Manager('alex')
operate_lst = ['创建课程','创建学生账号','查看所有课程','查看所有学生']
for index,opt in enumerate(operate_lst,1):
    print(index,opt)
num = input('请输入您要做的操作 :')
if num.isdigit():
    num = int(num)
if num == 1:
    alex.create_course()
elif num == 2:
    alex.create_student()
elif num == 3:
    alex.show_courses()
elif num == 4:
    alex.show_students()

使用反射
alex = Manager('alex')
operate_lst = [('创建课程','create_course'),('创建学生账号','create_student'),
               ('查看所有课程','show_courses'),('查看所有学生','show_students')]
for index,opt in enumerate(operate_lst,1):
    print(index,opt[0])
num = input('请输入您要做的操作 :')
if num.isdigit():
    num = int(num)
    if hasattr(alex,operate_lst[num-1][1]):
        getattr(alex,operate_lst[num-1][1])()

shop 买东西类
    1.浏览商品   scan_goods
    2.选择商品 ,添加到购物车  choose_goods
    3.删除商品   delete_goods
class Shop:

    def __init__(self,name):
        self.name = name
    def scan_goods(self):
        print('%s正在浏览商品'%self.name)

    def choose_goods(self):
        print('%s正在选择商品'%self.name)

    def delete_goods(self):
        print('%s正在删除商品'%self.name)

s = Shop('self哥')
s.choose_goods()
s.scan_goods()
s.delete_goods()
if hasattr(s,'choose_goods'):   # 判断s对象有没有choose_goods
    func = getattr(s,'choose_goods')   # 使用s找到choose_goods对应的内存地址
    print(func)
    func()
content = input('')
if hasattr(s,content):   # 判断s对象有没有choose_goods
    func = getattr(s,content)   # 使用s找到choose_goods对应的内存地址
    print(func)
    func()
opt_lst = ['scan_goods','choose_goods','delete_goods']
for index,opt in enumerate(opt_lst,1):
    print(index,opt)
num = int(input('num :'))
if hasattr(s,opt_lst[num-1]):
    getattr(s,opt_lst[num-1])()

和反射没关系
for i in Shop.__dict__.keys():
    if not i.startswith('__'):
        print(i)

使用类反射

cls . 属性名

cls . 方法名()

class A:
    Country = '中国'

    @classmethod
    def show(cls):
        print('国家 : ',cls.Country)

'Country'
print(getattr(A,'Country'))   # print(A.Country)

A.show  # getattr(A,'show')
'show'
getattr(A,'show')()   # A.show()

使用模块反射

import time

time.time()

import re
ret = re.findall('d+','2985urowhn0857023u9t4')
print(ret)
'findall'
getattr(re,'findall')   # re.findall
ret = getattr(re,'findall')('d','wuhfa0y80aujeiagu')
print(ret)

def func(a,b):
    return a+b

wahaha = func
ret = wahaha(1,2)
print(ret)
import time
time.time  == getattr(time,'time')
time.time()  == getattr(time,'time')()

'time'
now  = getattr(time,'time')()
print(now)

time.sleep(1)
print(321)
getattr(time,'sleep')(1)   # time.sleep(1)
print(123)

反射本文件中的内容

只要是出现在全局变量中的名字,都可以用 getattr(modules[__name__] , 字符串数据类型的名字) 来获得

from sys import modules

语法
a = 1
b = 2
getattr(modules[__name__],'变量名')

函数名
def func(a,b):
    print('in func',a,b)

getattr(modules[__name__],'func')   # func
func(1,2)
getattr(modules[__name__],'func')(1,2)   # func

类名
class Course:
    def func(self):
        print('in func')

print(Course)
'Course'
print(getattr(modules[__name__],'Course'))   # Course
getattr(modules[__name__],'Course')()   # 实例化的过程
只要是a.b这种结构,都可以使用反射
用对象类模块反射,都只有以下场景
这种结构有两种场景
    a.b   b是属性或者变量值
        getattr(a,'b')   == a.b
    a.b()  b是函数或者方法
        a.b()
            getattr(a,'b')()
        a.b(arg1,arg2)
            getattr(a,'b')(arg1,arg2)
        a.b(*args,**kwargs)
            getattr(a,'b')(*args,**kwargs)
如果是本文件中的内容,不符合a.b这种结构
如果是这种方式,引用的模块就不是 from sys import modules , 而是直接引用 import sys 直接调用func() getattr(sys.modules[
__name__],'func')() 直接使用类名 Person() getattr(sys.modules[__name__],'Person')() 直接使用变量名 print(a) getattr(sys.modules[__name__],'a') 所有的getattr都应该和hasattr一起使用 if hasattr(): getattr()

setattr

除了可以修改私有化的属性,还可以通过字符串数据类型的变量名,给一个对象创建一个新的属性

但 setattr 不可绑定方法

使用 setattr 创建了一个方法后,也只是创建在属性的内存空间中,而不是类的内存空间

这种方法不是正常的方法

所以 setattr 只用来绑属性

class A:
    def qqxing(self):
        print('qqxing')

alex = A()
alex.name = 'sb'
print(alex.name)
setattr(alex,'name','sb')   # alex.name = 'sb'
print(alex.name)

    

deleter

deleter(对象名,'属性')

删除对象的一个属性

和 setattr 一样,不能操作方法,只能操作属性

issubclass

判断类与类之间的关系

其实就是判断类与类之间是否有继承关系

issubclass(Son,Foo)

判断Son是不是Foo的子类

输出的结果是布尔值

object是任何类的父类,所以 insubclass(Son,object) 的结果总是 True

isinstance

判断对象与类之间的关系,这个 '类' 也包括父类

isinstance(obj,cls)

判断obj是否是cls或cls子类的对象

isinstance(obj,类)  判断时时承认继承关系的

类 = type(obj) 也可以判断类与对象的关系,但只承认实例化这个对象的那个类(不承认所有的继承关系)

原文地址:https://www.cnblogs.com/biulo/p/10639859.html