反射与二次加工标准类型
反射与二次加工标准类型 |
一、反射
反射主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。
有四个可以实现自省(反射)的函数,如下表所示:
函数名 | 含义 |
hasattr(object,name) | 判断object中有没有一个name字符串对应的方法或属性 |
getattr(object,name, default=None) | 检查obj.__dict__中有没有name这个键值,有则不做任何处理,没有则报错 |
setattr(object,name,value) | 等价于object.name=value |
delattr(object,name) |
等价于del object.name
|
各个函数具体代码实现:
class BlackMedium:feture = 'Ugly'def __init__(self,name,addr):self.name = nameself.addr = addrdef sell_hourse(self):print('%s正在卖房子' %self.name)def rent_hourse(self):print('%s正在租房子' %self.name)print(hasattr(BlackMedium,'feture')) #结果为:True b1 = BlackMedium('alex','厦门') print(hasattr(b1,'name')) #结果为:True print(hasattr(b1,'sell_hourse')) #结果为:Trueprint(getattr(b1,'name')) #结果为:alex g = getattr(b1,'sell_hourse') g() #结果为:alex正在卖房子 print(getattr(b1,'sell_hoursesafgsgr','没有这个属性')) #结果为:没有这个属性 setattr(b1,'phone',18264894546) print(b1.__dict__) #结果为:{'name': 'alex', 'addr': '厦门', 'phone': 18264894546} setattr(b1,'func',lambda x:x+1) print(b1.__dict__) #结果为:{'name': 'alex', 'addr': '厦门', 'phone': 18264894546, 'func': <function <lambda> at 0x000000000041C1E0>} delattr(b1,'func') print(b1.__dict__) #结果为:{'name': 'alex', 'addr': '厦门', 'phone': 18264894546}
上述代码介绍了实现自省(反射)的函数。
反射的两个好处:
第一的好处:实现可插拔机制
假设程序员a与程序员b负责同一个项目,程序员a负责实现功能,而程序员b负责执行功能,那么程序员b在执行功能时发现程序员a的实现功能还未写入,这样就会出错,该如何解决这一问题?我们可以使用上面所学的反射来解决,具体代码如下:
#程序员a写的实现功能,写在ftp_client.py文件 class FtpClient:def __init__(self,addr):print('正在连接服务器%s' %addr)self.addr = addr# def put(self): #假设这方法还没写,被程序员b调用# print('正在上传文件')
#程序员b写的执行功能,写在ftp_bin.py文件 from ftp_client import FtpClientf1 = FtpClient('1.1.1.1') #f1.put() ftp_client文件还没有写这功能会报错,可以利用反射方式判断,如下所示if hasattr(f1,'put'):func_get = getattr(f1,'put')func_get() else:print('不存在此方法,处理其它的逻辑')
上述代码利用反射方式判断,相当于事先定义接口,接口只有在被完成后才会真正执行,这实现了即插即用。
第二个好处:动态导入模块(基于反射当前模块成员)
假如你需要导入m1.py模块,即:
import m1 __import__('m1.tttt') #这是解释器自己内部用的,它导入的就是m1模块 importlib.import_module('m1.tttt') #与上面这句效果一样
我们来了解类内置attr函数,分别是__setattr__、__getattr__、__delattr__。
__getattr__只有在使用点调用属性且属性不存在时候才会执行,具体如何实现请看下面代码:
class Foo:x = 1def __init__(self,y):self.y = ydef __getattr__(self, item):print('执行__getattr__') #调用一个对象不存在时候才会执行 f1 = Foo(10) print(f1.y) #结果为:10 print(getattr(f1,'y')) #结果为:10 f1.svdgsg #结果为:执行__getattr__
__delattr__删除属性的时候才会执行,该属性不存在也会执行,具体实现如下代码所示:
class Foo:x = 1def __init__(self,y):self.y = ydef __delattr__(self, item):print('删除操作__delattr__')self.__dict__.pop(item) #内置的 f1 = Foo(10) del f1.y #结果为:删除操作__delattr__ del f1.x #结果为:删除操作__delattr__,报错
__setattr__在类被实例化、以及添加或修改属性的才会执行,代码如下:
class Foo:x = 1def __init__(self,y):self.y = ydef __setattr__(self,key,value):print('执行__setattr__')self.__dict__[key] = value #内置的 f1 = Foo(10) #结果为:执行__setattr__ print(f1.__dict__) #结果为:{'y': 10} f1.z = 2 #结果为:执行__setattr__ print(f1.__dict__) #结果为:{'y': 10, 'z': 2}
二、二次加工标准类型
1.包装
Python为大家提供了标准数据类型,以及丰富的内置方法,其实在很多场景下我们都需要基于标准数据类型来定制我们自己的数据类型,新增/改写方法,这就用到了我们刚学的继承/派生知识。
假设利用list方法只能添加到字符串类型,具体代码如下:
class List(list):def append(self, item):if type(item) is str:super().append(item) else:print('只能添加字符串类型')l1 = List('hello') l1.append('alex') print(l1) #结果为:['h', 'e', 'l', 'l', 'o', 'alex'] l1.append(1646) #结果为:只能添加字符串类型 print(l1) #结果为:['h', 'e', 'l', 'l', 'o', 'alex']
上述代码在讲述包装一个类型通常是对已存在的类型的一些定制,这种做法可以新建、修改或删除原有产品的功能,其它的则保持原样。
2.授权
授权是包装的一个特性,授权的过程即是所有更新的功能都是由新类的某部分来处理,但已存在的功能就授权给对象的默认属性。
假设我们想要修改文件的写操作,具体代码如下:
import datetime class Open:def __init__(self,filename,mode='r',encoding='utf-8'):#self.filename = filenameself.file = open(filename,mode,encoding=encoding)self.mode = modeself.encoding = encodingdef write(self,line): #将写操作加上当前时间t = datetime.datetime.now()self.file.write('%s %s' %(t,line))def __getattr__(self,item):return getattr(self.file,item)f1 = Open('a.txt','w+') f1.write('1111111\n') #执行类的write方法 f1.write('ssssss\n') f1.write('hhhhh\n') f1.seek(0) print(f1.read()) #先在初始函数找,然后在类找,最后找到__getattr__方法,触发__getattr__
实现授权的关键点就是类中的__getattr__函数。
转载于:https://www.cnblogs.com/lzc69/p/11264038.html
反射与二次加工标准类型相关推荐
- python十大标准_python对标准类型的分类
python的标准类型可以按照三种方式分类. 一.按存储模型分类 按存储模型分可以分为原子(标量)类型和容器类型. 原子(标量)类型指对象(这里的对象不是对象数据类型,而是任何可能的值)的值只能含有一 ...
- 利用反射机制获取未知类型的枚举的信息
原文:利用反射机制获取未知类型的枚举的信息 开发游戏设置选项遇到一个问题,我有两个枚举,一个是屏幕分辨率,一个是语言 我需要在不知道一个枚举到底是哪一个枚举类型的情况下,获取这个枚举的值以及这个枚举类 ...
- python运算符的分类_python对象——标准类型运算符
对象值的比较 比较运算符用来判断同类型对象是否相等,所有的内建类型均支持比较运算,比较运算返回布尔值 True 或 False. 注意,实际进行的比较运算因类型而异.换言之,数字类型根据数值的大小和符 ...
- python语言中包含的标准数据类型_Python对象——标准类型的分类
如果让我们最啰嗦的描述标准类型,我们也许会称它们是Python 的"基本内建数据对象原始类型". z "基本",是指这些类型都是Python 提供的标准或核心类 ...
- python提供两个对象身份比较操作符_标准类型对象比较操作符
标准类型对象比较操作符 (2008-08-31 12:22:17) 标签: it 标准类型对象身份比较操作符 Python 提供了is和is not操作符来测试两个变量是否指向同一个对象. 像下面这样 ...
- Effective JavaScript Item 40 避免继承标准类型
本系列作为Effective JavaScript的读书笔记. ECMAScript标准库不大.可是提供了一些重要的类型如Array,Function和Date.在一些场合下.你或许会考虑继承当中的某 ...
- python标准函数有哪些_Python几个标准类型内建函数
Python提供了一些内建函数用于基本对象类型:cmp(),repr(),str(),type()和等同于repr()的(' ')操作符 (1)type() type的用法如下: type(objec ...
- python包标准类型和动态导入模块和多态和反射和授权
class List(list):def append(self, p_object):if type(p_object) is str:# self.append(p_object)super(). ...
- go使用反射reflect获取变量类型
可以用反射: package mainimport ("fmt""reflect" )func main() {var x float64 = 3.4fmt.P ...
最新文章
- 让你的 conda “回滚”到以前版本的环境
- 机器学习特征筛选:互信息法(mutual information)
- (chap1 网络基础知识)网络的构成要素:(7)网关
- Java设计模式(13)----------代理模式
- 报送数据标准校验java_Java:数据校验 - osc_gaqp1a2z的个人空间 - OSCHINA - 中文开源技术交流社区...
- 排序提示若执行此操作所有合并单元格需大小相同
- 【DB2】NULLS LAST与NULLS FIRST
- java三角函数计算器_编程实现一个科学计算器,能够实现加减乘除,三角函数计算等。用户界面自己设计...
- C++实现双向循环链表
- java 蜂鸣器_蜂鸣器的介绍
- TP_link家庭无线路由
- 论文介绍 -- Rethinking the Evaluation of Video Summaries
- android 拨打多个电话号码,和多号如何使用副号打电话/发短信
- 网站敏感骂人词库及算法(附6仟个敏感词)
- macOS上使用Openconnect代替Cisco Anyconnect
- 使用VMware创建虚拟机,并配置虚拟机网络
- 婚恋交友系统源码,实现基础的系统功能
- 汽车文化-实用与实在-车身结构
- 设置访问权限的神器-------subinacl
- HashMap 的长度为什么是 2 的幂次方
热门文章
- java web登录状态保持_java web用于保持状态的4种方法
- charles抓取手机APP,配置正确却抓不到数据
- LeetCode:位运算实现加法
- 机器学习 基本概念,常用经典模型
- 清北学堂十一培训酱油记
- DATEADD(Day, DATEDIFF(Day,0,ShippingTime), 0)
- 程序员需要了解的一点组织行为学知识
- 2012年4月18日 新的开始
- centos arm-linux-gcc,CentOS 6.4配置arm-linux-gcc交叉环境
- python的序列包括字符串列表和什么_Python基础:03序列:字符串、列表和元组