反射

什么是反射

反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。

python中面向对象的反射

通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)

四个可以实现自省的函数

用户输入一段字符串,执行该字符串对应的方法

hasattr():判断一个属性是否在对象中,返回True或False

getattr():通过字符串获取属性方法,如果获取到了,就会返回相应的属性或方法

setattr():通过字符串来设置属性或方法

delattr():通过字符串来删除属性或方法

class Foo:
    def run(self):
        print('run')
    def speak(self):
        print('speak')
p=Foo()
print(Foo.__dict__)
cmd=input('请输入命令: ')
print(Foo.__dict__)
Foo.__dict__[cmd](p)
if hasattr(p,cmd):
    run=getattr(p,cmd)
    run()
else:
    print('该命令不存在')

# 通过用户输入key和value往对象中赋值
key=input('请输入key:')
value=input('输入value:')
setattr(p,key,value)
print(p.age)

#动态的往对象中放方法
def test(a):
    print(a)
print(p.__dict__)
setattr(p,'test',test)
print(p.__dict__)
p.test(0)
#原始的删除方法
 p.name='lqz'
 print(p.__dict__)
 del p.name
 print(p.__dict__)
#动态删除p中属性为变量a的属性
p.name='lqz'
p.age=18
p.sex='male'
a=input('请输入要删除的属性:')
print(p.__dict__)
delattr(p,a)
print(p.__dict__)
#直接p.a是不对的
#del p.a

例子

class BlackMedium:
    feature='Ugly'
    def __init__(self,name,addr):
        self.name=name
        self.addr=addr

    def sell_house(self):
        print('%s 黑中介卖房子啦,傻逼才买呢,但是谁能证明自己不傻逼' %self.name)
    def rent_house(self):
        print('%s 黑中介租房子啦,傻逼才租呢' %self.name)

b1=BlackMedium('万成置地','回龙观天露园')

#检测是否含有某属性
print(hasattr(b1,'name'))
print(hasattr(b1,'sell_house'))

#获取属性
n=getattr(b1,'name')
print(n)
func=getattr(b1,'rent_house')
func()

# getattr(b1,'aaaaaaaa') #报错
print(getattr(b1,'aaaaaaaa','不存在啊'))

#设置属性
setattr(b1,'sb',True)
setattr(b1,'show_name',lambda self:self.name+'sb')
print(b1.__dict__)
print(b1.show_name(b1))

#删除属性
delattr(b1,'addr')
delattr(b1,'show_name')
delattr(b1,'show_name111')#不存在,则报错

print(b1.__dict__)

四个方法的使用演示

模块也是对象,也可以用四个方法

import  os
print(hasattr(os,'path1'))

使用自己写的模块,通过反射来获取模块中是否有我要使用的属性或方法,如果有就执行,没有,就报错

import utils

utils.speak()
if hasattr(utils,'speak'):
    speak=getattr(utils,'speak')
    speak()

反射的好处

可以事先定义好接口,接口只有在被完成后才会真正执行,这实现了即插即用,这其实是一种‘后期绑定’,什么意思?即你可以事先把主要的逻辑写好(只定义接口),然后后期再去实现接口的功能

#我以为它写完了
utils.eat()
#更安全
if hasattr(utils,'eat'):
    eat=getattr(utils,'eat')
    eat()
else:
    print('那个人还没写完呢')
posted on 2019-09-02 20:25  黑糖A  阅读(66)  评论(0编辑  收藏  举报