十三、反射(自省)

一、 反射(自省):主要是指程序可以访问、检测和修改它本身状态或行为的一种能力

  四个可以实现自省的函数:

  1、hasattr(object,name)     

    object--->对象,name--->字符串

    判断object中有没有一个name字符串对应的方法或属性

class AAA:
    def __init__(self,name,addr):
        self.name=name
        self.addr=addr
    def sale(self):
        print('----->')
p1=AAA('alex','nanjing')
print(hasattr(p1,'name'))   #True 
print(hasattr(p1,'sale'))    #True
print(hasattr(p1,'shugl'))    #False

  2、getattr(object,name,default=None)

    运行object对象所对应的name方法。若指定了default,不存在name时显示default内容,不指定时报错

class AAA:
    def __init__(self,name,addr):
        self.name=name
        self.addr=addr
    def sale(self):
        print('----->')
p1=AAA('alex','nanjing')
print(getattr(p1,'name'))   # alex
print(getattr(p1,'sale'))    #返回sale函数的内存地址
func=getattr(p1,'sale')
func()        #----->
print(getattr(p1,'shugl','没有这个参数'))    #没有这个参数
print(getattr(p1,'shugl'))    #报错

  3、setattr(object,name,value)

    设置object对象的name属性值为value

class AAA:
    def __init__(self,name,addr):
        self.name=name
        self.addr=addr
    def sale(self):
        print('----->')
p1=AAA('alex','nanjing')
setattr(p1,'name','alex1234')  
print(p1.name)    #alex1234
setattr(p1,'age',30)
print(p1.__dict__)   #{'age':'30','name':'alex','addr':'nanjing'}

   给对象设置函数属性

class AAA:
    def __init__(self,name):
        self.name=name
    def sale(self):
        print('----->')
p1=AAA('alex')
setattr(p1,'func',lambda x:x+1)
print(p1.__dict__)   #{'name':'alex','func':<function <almbda> at 0x00BF 17CB>}
setattr(p1,'func1',lambda self:self+'-nanjing')
print(p1.func(10))            #11
print(p1.func1('alexxxxx'))   #alexxxxx-nanjing

  4、del (object,name)

    删除object对象的name属性

class AAA:
    def __init__(self,name,addr):
        self.name=name
        self.addr=addr
    def sale(self):
        print('----->')
p1=AAA('alex','nanjing')
print(p1.__dict__)     #{'name':'alex','addr':'nanjing'}
delattr(p1,'name')  
print(p1.__dict__)   #{'addr':'nanjing'}

 二、反射的好处

    实际项目中,经常是多个程序员一起合作一个项目,使用反射可以帮助程序员之前开发代码互不影响

#程序员1开发代码
class FtpClient:
    'ftp客户端,但是没有实现具体功能'
    def __init__(self,addr):
        self.addr=addr
        print('正在连接服务器%s'%(self.addr))
        
#程序员2开发代码
from ftp_wenjian import FtpClient
f1=FtpClient('192.168.10.208')
if hasattr(f1,'put'):
    func=getattr(f1,'put')
    func()
else:
    print('没有方法put')

三、类内置的attr方法

1. __getattr__

   只有在调用的属性不存在时,才会执行__getattr__

class Foo:
    def __init__(self,y):
        self.y=y
    def __getattr__(self,item):
        print('执行__getattr__')

f1=Foo(10)
print(f1.y)   #10 
print(getattr(f1,'y'))  #10
f1.ssss   #执行__getattr__
print(f1.shug)   #执行__getattr__
                 #None 

2. __delattr__

  无论要删除的属性是否存在,都会执行__delattr__

  但是实际上,属性并没有被删除!!!需要在__delattr__中删除

class Foo:
    def __init__(self,y):
        self.y=y
    def __delattr__(self,item):
        print('删除操作')
     #self.__dict__.pop(item) f1
=Foo(10) del f1.y #删除操作 print(f1.__dict__) #{'y':10} del f1.x #删除操作

3. __setattr__

class Foo:
    x=1
    def __init__(self,y,z):
        self.y=y
     self.z=z
def __setattr__(self,key,value): #self.key=value #不能这样设置,会进入死循环 print('--->') self.__dict__[key]=value #生成实例时启动__setattr__时,不会将属性自动加到实例的属性字典,所以需要手动加 f1=Foo(10)

#--->
#--->
 
原文地址:https://www.cnblogs.com/haoy/p/10564126.html