反射

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

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

四个可以实现自省的函数

下列方法适用于类和对象(一切皆对象,类本身也是一个对象)


#hasattr 判断object中有没有一个name字符串对应的方法或属性
#getattr 用于以字符串的形式去传入对象的字典中寻找函数
#setattr 如果该值存在,就覆盖,不存在就添加
#delattr 如果该值存在就删除,不存在报错

hasattr(obj,'属性') #obj.属性  是否存在
getattr(obj,'属性') #获取obj.属性   不存在则报错
getattr(obj,'属性','默认值') #获取obj.属性   不存在不会报错,返回那个默认值
setattr(obj,'属性','属性的值') #obj.属性=属性的值
delattr(obj,'属性') #del obj.属性

class Game:
__game_type = 'cross_f'
def __init__(self,g_name,player,gun,moeny):
self.g_name = g_name
self.g_player = player
self.g_gun = gun
self.g_moeny = moeny
def buy_gun(self):
print('%s买了一把%s游戏的%s并花费了%s元'%(self.g_player,self.g_name,self.g_gun,self.g_moeny))
g1 = Game('cf','zk','blt',100) #hasattr 判断object中有没有一个name字符串对应的方法或属性
print(hasattr(g1,'name')) #True或者False #getattr 用于以字符串的形式去传入对象的字典中寻找函数
a = getattr(g1,'g_name1','随便定义')#语法getattr(对象,'字符串名',默认参数任意) #监测g1可不可以调取到某个数据属性和函数属性
print(a) #如果存在,数据属性,返回对应的V值,函数返回对应的函数对象,不存在返回设置的默认参数
#执行结果:随便定义 g1.g_test = 888 #添加函数和覆盖函数
#setattr 如果该值存在,就覆盖,不存在就添加
setattr(g1,'g_name','aaa') #添加函数和覆盖函数,执行效果和g1.g_test = 888一样
setattr(g1,'g_sex','aaa') #添加函数和覆盖函数,执行效果和g1.g_sex = aaa一样
print(g1.__dict__)
#执行结果:{'g_name': 'aaa', 'g_moeny': 100, 'g_sex': 'aaa', 'g_gun': 'blt', 'g_test': 888, 'g_player': 'zk'} del g1.g_test
#delattr 如果该值存在就删除,不存在报错
delattr(g1,'g_name') #AttributeError: name
print(g1.__dict__)
#执行结果:{'g_moeny': 100, 'g_player': 'zk', 'g_gun': 'blt', 'g_sex': 'aaa'}

通过__import__导入模块

正常的导入方式:

import 模块名(文件夹名)as 方法名(文件名)

通过__import__导入模块

__import__(name)    #导入模块,无论name有多少层,永远都只返回最顶层
module_t = __import__('a1.test') #会执行一次,al下边的test文件,但是不能调用
print(module_t) #现在的module_t=a1 如果想要调用a1下边的文件方法,就必须再往下找,
module_t.test.test1() #这样才可以调用

导入importlib模块,通过importlib下的import_module方法导入模块

import importlib
m = importlib.import_module('a1.test') #m得到的就是a1.test这个文件
m.test1() #直接用m.m下边的方法直接可以执行

通过用户输入,实现动态导入

user_im= input('输入想要导入的模块:')
imp_in = __import__(user_im)
a = imp_in.test(1,2);

具体玩法

#如果想通过用户输入实现,动态导入模块,并且可以根据用户输入,执行函数
user_im= input('输入想要导入的模块:')
#__import__用于以字符串的方式导入模块
imp_in = __import__(user_im)
user_infun = input('输入想到执行的函数:')
#getattr 用于以字符串的形式去某个模块中寻找函数
in_func = getattr(imp_in,user_infun)
#获取函数后,加()直接执行
a = in_func(1,5)
print(a)

为什么用反射之反射的好处

好处一:实现可插拔机制

有俩程序员,一个alex,一个是egon,alex在写程序的时候需要用到egon所写的类,但是egon去跟女朋友度蜜月去了,还没有完成他写的类,alex想到了反射,使用了反射机制alex可以继续完成自己的代码,等egon度蜜月回来后再继续完成类的定义并且去实现alex想要的功能。

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

class FtpClient:
'ftp客户端,但是还么有实现具体的功能'
def __init__(self,addr):
print('正在连接服务器[%s]' %addr)
self.addr=addr
#from module import FtpClient
f1=FtpClient('192.168.1.1')
if hasattr(f1,'get'):    #如果FtpClient存在get方法,就可以进入if判断,并通过getattr执行具体的get方法,处理下边的逻辑
func_get=getattr(f1,'get')
func_get()
else:
print('---->不存在此方法')#如果不存在,可编写else的逻辑
print('处理其他的逻辑') 不影响alex的代码编写


__setattr__,__delattr__,__getattr__用法

__getattr__只有在使用点调用属性且属性不存在的时候才会触发     比较有用
__delattr__删除属性的时候会触发
__setattr__添加/修改属性会触发它的执行
当你自己写__getattr__、__delattr__、__setattr__方法,系统会调用你写的方法,如果没写,系统调用默认
class Foo:
x=1
def __init__(self,y):
self.y=y def __getattr__(self, item):    #self传的是调用者自己  itme传的是调用错误的函数信息
print('----> from getattr:你找的【%s】属性不存在'%item) def __setattr__(self, key, value):
print('----> from setattr')
if type(value) is str: #判断v值为字符串类型,才能加入字典
print('执行设置操作')
# self.key=value #这就无限递归了,你好好想想
self.__dict__[key] = value.upper() # 应该使用它 最底层的操作就是在设置属性字典 upper(str)类型的全部大写
else:
print('必须是str才能加入') def __delattr__(self, item):  #self传的是调用者自己  itme传的是调用错误的函数信息
print('----> from delattr')
# del self.item #无限递归了
#self.__dict__.pop(item) #同理直接操作字典 f1=Foo(10)
f1=Foo('asdfgh')
print(f1.__dict__) #print(f1.ya)
# print(getattr(f1,'y')) #本质就是len(str)------>str.__len__()
# print(getattr(f1,'不存在的')) #如果这个参数不存在,那么会执行 __getattr__的参数,如果没有定义__getattr__,会走系统默认的(报错) #__setattr__添加/修改属性会触发它的执行
# f1=Foo(10)
# print(f1.__dict__) # 因为你重写了__setattr__,凡是赋值操作都会触发它的运行,你啥都没写,就是根本没赋值,除非你直接操作属性字典,否则永远无法赋值
# f1.z=3
# print(f1.__dict__) #__delattr__删除属性的时候会触发
#del f1.x #只要是删除操作就会调用__delattr__函数执行,值不存在也不会报错
# f1.__dict__['a']=3#我们可以直接修改属性字典,来完成添加/修改属性的操作
# del f1.a
# print(f1.__dict__) #__getattr__只有在使用点调用属性且属性不存在的时候才会触发
# f1.xxxxxx



反射和__setattr__,__delattr__,__getattr__用法的更多相关文章

  1. python基础----isinstance(obj,cls)和issubclass(sub,super)、反射、__setattr__,__delattr__,__getattr__、二次加工标准类型(包装)

    一.isinstance(obj,cls)和issubclass(sub,super)                                isinstance(obj,cls)检查是否ob ...

  2. python基础之类的内置__setattr__,__delattr__,__getattr__和 二次加工标准类型(包装)

    一.内置attr:__setattr__,__delattr__,__getattr__ __setattr__ #添加/修改属性会触发它的执行 __delattr__ #删除属性的时候会触发 __g ...

  3. 类方法__setattr__,__delattr__,__getattr__

    __getattr__,_delattr_,_getattr_ class Foo: x = 1 def __init__(self, y): self.y = y def __getattr__(s ...

  4. python __setattr__和__getattr__

    通过为dict添加__setattr__和__getattr__, 可以属性的语法访问dict的元素 http://www.2cto.com/kf/201507/413971.html class S ...

  5. Python魔法方法之属性访问 ( __getattr__, __getattribute__, __setattr__, __delattr__ )

    通常情况下,我们在访问类或者实例对象的时候,会牵扯到一些属性访问的魔法方法,主要包括: ① __getattr__(self, name): 访问不存在的属性时调用 ② __getattribute_ ...

  6. python __setattr__、__getattr__、__getattribute__全面详解

    一.属性引用函数 hasattr(obj,name[,default])getattr(obj,name)setattr(obj,name,value)delattr(obj,name) 二.属性引用 ...

  7. Python之路【第九篇】:面向对象进阶

    阅读目录 一. isinstance(obj,cls)和issubclass(sub,super)二. 反射三. __setattr__,__delattr__,__getattr__四. 二次加工标 ...

  8. 面向对象之(非)绑定方法,反射,isinstance与issubclass

    isinstance(obj,cls)和issubclass(sub,super) isinstance(obj,cls)检查obj是否是类 cls 的对象 class Foo(object): pa ...

  9. 面向对象相关概念与在python中的面向对象知识(魔法方法+反射+元类+鸭子类型)

    面向对象知识 封装 封装的原理是,其成员变量代表对象的属性,方法代表这个对象的动作真正的封装是,经过深入的思考,做出良好的抽象(设计属性时用到),给出“完整且最小”的接口,并使得内部细节可以对外透明( ...

随机推荐

  1. office web apps 整合到自己项目中(wopi实现在线预览编辑)

    借助office web apps实现在线预览和在线编辑 我所有的代码都是用go语言编写,你可以直接编译后使用,不用再有其他的操作. 最近项目实在太忙,这几天才有时间,这次是重头戏,要好好琢磨一下怎么 ...

  2. 安装MySQLdb出现的问题

    枫竹梦的环境是自己编译安装的MySQL,安装目录在/usr/local/mysql. 下载MySQLdb,由于网络上大多数的链接都是指向比较老的sourceforge上,而我们安装最新的1.2.5,h ...

  3. Chapter 3 Shared Assemblies and Strongly Named Assemblies

    As time marches on,MS developers and control developer modify their code:they fix bugs,patch securit ...

  4. servlet过滤器Filter(理论篇)

    为了减少servlet容器在服务器端对信息的判断量,产生了servlet过滤器. servlet过滤器是在java servlet规范2.3中定义的,他能够对servlet容器的请求和响应对象进行检查 ...

  5. jsp报An error has occurred. See error log for more details. Argument not valid错误

    An error has occurred. See error log for more details. Argument not valid 翻译过来是:一个错误已经发生.看到更多的细节错误日志 ...

  6. 【Redis笔记(四)】 Redis数据结构 - list链表

    原创作品,转载请标明:http://blog.csdn.net/Xiejingfa/article/details/50573605 经过前面的介绍,我们学习了Redis中string字符串.hash ...

  7. 大数相乘(hdu 1402)

    ------------------题目链接--------------------- 题目没啥说的,两个数相乘,fft,一发模板就AC,kuangbin模板大法好,不懂原理的小白也能体验AC. 个人 ...

  8. June 25,2014---->Binder(IPC),Dalvik ,DEX/ODEX

    1.Binder(IPC) Linux进程之间要能够互相通信,从而共享资源和信息.所以,操作系统内核必须提供进程间的通信机制(IPC,Inter-Process Communication). IPC ...

  9. mtk lk阶段的lcm流程

    一.lk进入kmain() 1. vendor/mediatek/proprietary/bootable/bootloader/lk/arch/arm/srt0.S bl kmain 二.初始化lk ...

  10. CF-831C

    C. Jury Marks time limit per test 2 seconds memory limit per test 256 megabytes input standard input ...