反射和__setattr__,__delattr__,__getattr__用法
反射
什么是反射:反射的概念是由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__用法的更多相关文章
- python基础----isinstance(obj,cls)和issubclass(sub,super)、反射、__setattr__,__delattr__,__getattr__、二次加工标准类型(包装)
一.isinstance(obj,cls)和issubclass(sub,super) isinstance(obj,cls)检查是否ob ...
- python基础之类的内置__setattr__,__delattr__,__getattr__和 二次加工标准类型(包装)
一.内置attr:__setattr__,__delattr__,__getattr__ __setattr__ #添加/修改属性会触发它的执行 __delattr__ #删除属性的时候会触发 __g ...
- 类方法__setattr__,__delattr__,__getattr__
__getattr__,_delattr_,_getattr_ class Foo: x = 1 def __init__(self, y): self.y = y def __getattr__(s ...
- python __setattr__和__getattr__
通过为dict添加__setattr__和__getattr__, 可以属性的语法访问dict的元素 http://www.2cto.com/kf/201507/413971.html class S ...
- Python魔法方法之属性访问 ( __getattr__, __getattribute__, __setattr__, __delattr__ )
通常情况下,我们在访问类或者实例对象的时候,会牵扯到一些属性访问的魔法方法,主要包括: ① __getattr__(self, name): 访问不存在的属性时调用 ② __getattribute_ ...
- python __setattr__、__getattr__、__getattribute__全面详解
一.属性引用函数 hasattr(obj,name[,default])getattr(obj,name)setattr(obj,name,value)delattr(obj,name) 二.属性引用 ...
- Python之路【第九篇】:面向对象进阶
阅读目录 一. isinstance(obj,cls)和issubclass(sub,super)二. 反射三. __setattr__,__delattr__,__getattr__四. 二次加工标 ...
- 面向对象之(非)绑定方法,反射,isinstance与issubclass
isinstance(obj,cls)和issubclass(sub,super) isinstance(obj,cls)检查obj是否是类 cls 的对象 class Foo(object): pa ...
- 面向对象相关概念与在python中的面向对象知识(魔法方法+反射+元类+鸭子类型)
面向对象知识 封装 封装的原理是,其成员变量代表对象的属性,方法代表这个对象的动作真正的封装是,经过深入的思考,做出良好的抽象(设计属性时用到),给出“完整且最小”的接口,并使得内部细节可以对外透明( ...
随机推荐
- Mac端博客发布工具推荐
引子 推荐一款好用的 Mac 端博客发布工具. 下载地址 echo 博客对接 这里以cnblog为例.接入类型为metawebblog,access point可以在cnblog的设置最下边找到,然后 ...
- Java 符号引用 与 直接引用
在类的加载过程中的解析阶段,Java虚拟机会把类的二进制数据中的符号引用 替换为 直接引用,如Worker类中一个方法: public void gotoWork(){ car.run(); //这段 ...
- 基于BASYS2的VHDL程序——分频和数码管静态显示程序
转载请注明出处:http://www.cnblogs.com/connorzx/p/3633860.html 分频是基于计数器程序.由于FPGA的并行处理能力,根本不需要单片机式的中断指令,用起来很方 ...
- uva 10881 Piotr's Ants 解题报告
题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=20&pa ...
- uva 401 Palindromes 解题报告
题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...
- linux系统配置之PATH环境变量的设置(centos)
Centos系统下修改环境变量PATH路径的方法 电脑脑中必不可少的就是操作系统.而Linux的发展非常迅速,有赶超微软的趋势.这里介绍Linux的知识,让你学好应用Linux系统.比如要把/etc/ ...
- slim.flatten——将输入扁平化但保留batch_size,假设第一维是batch
slim.flatten(inputs,outputs_collections=None,scope=None) (注:import tensorflow.contrib.slim as slim) ...
- asio socket设置 server地址与端口的两种方式
1. 用解释器的方法, 常用来解析域名, 如 // query("www.163.com","80"), 也可以 query("www.163.co ...
- 必须知道的八大种排序算法【java实现】
一.冒泡排序 冒泡排序是一种简单的排序算法.它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来.走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成. ...
- seafile文档
https://manual-cn.seafile.com/deploy_windows/download_and_setup_seafile_windows_server.html