day7-python类反射
一、概述
一般的高阶语言都有反射的功能特性,python也不例外,网上资料显示,python支持类反射和模块反射,今天就先学习一下类反射的相关知识,模块反射后续再展开把。Python的类反射用于把字符串(对应于属性或方法)反射成内存中的地址对象,以便按需调用,实现某些特性的动态装配,它主要通过hasattr()、getattr()、setattr()、和delattr()来实现,类似于数据库的增删改查操作把。
二、反射函数
以下内容主要思想转自师兄张其高的博客https://www.cnblogs.com/zhangqigao/articles/6947023.html
2.1 hasattr(obj, name_str)
作用:判断一个对象obj中是否有对应的name_str字符串所代表的属性或者方法,返回布尔值。注意这里的对象可以是类,也可以是实例化的对象。

1 class Dog(object):
2
3 def __init__(self, name):
4 self.name = name
5
6 def eat(self, food):
7 print('%s is eating %s' % (self.name, food))
8
9 obj1 = Dog('XiaoHuang')
10
11 print('obj1:\t %s ' % hasattr(obj1, 'name')) #判断属性
12 print('class Dog:\t %s' % hasattr(Dog, 'eat')) #判断方法
13
14 input = input(">>>:").strip() #动态输入字符串,动态判断
15 print(hasattr(obj1, input))
16
17 输出:
18 obj1: True
19 class Dog: True
20 >>>:food
21 False
2.2 getattr(obj, name_str)
作用:根据字符串name_str获取obj对象中的对应方法的内存地址或者对应属性的值

1 class Dog(object):
2
3 def __init__(self, name):
4 self.name = name
5
6 def eat(self, food):
7 print('%s is eating %s' % (self.name, food))
8
9 obj1 = Dog('XiaoHuang')
10 obj2 = Dog('Bark')
11
12 print('obj1:\t %s ' % getattr(obj1, 'name')) #返回属性地址
13 print('class Dog:\t %s' % getattr(Dog, 'eat')) #返回方法地址
14 print('obj1:\t %s' % getattr(obj1, 'eat')) #返回方法地址
15 print('obj2:\t %s' % getattr(obj2, 'eat'))
16
17 结果输出:
18 obj1: XiaoHuang
19 class Dog: <function Dog.eat at 0x00000000021CEEA0>
20 obj1: <bound method Dog.eat of <__main__.Dog object at 0x00000000021CCCC0>>
21 obj2: <bound method Dog.eat of <__main__.Dog object at 0x00000000021CCCF8>>
这里有一个小疑问,既然类中的方法都保存在类中,并且只保存一份,这里通过obj1和obj2去获取的类方法的地址显示是不同的,这是为什么呢?原因待脑补后补充。
2.3 setattr(obj, name_str, value)
作用:给obj对象添加一个新属性或者新方法,setattr(x, 'y', v) is equivalent to ``x.y = v''
- 给对象新增一个方法

1 class Dog(object):
2
3 def __init__(self, name):
4 self.name = name
5
6 def eat(self, food):
7 print('%s is eating %s' % (self.name, food))
8
9 def bulk(self): #预期新增的方法
10 print('%s is yelling...' % self.name)
11
12 obj1 = Dog('XiaoHuang')
13
14 str_input = input(">>>:").strip()
15 setattr(obj1, str_input, bulk)
16 func = getattr(obj1, str_input)
17 func(obj1)
18
19 print('obj1:\t %s ' % getattr(obj1, str_input))
20 print('class Dog:\t %s' % getattr(Dog, str_input))
21
22 结果输出:
23 >>>:hehe
24 XiaoHuang is yelling...
25 obj1: <function bulk at 0x0000000001CF3E18>
26 Traceback (most recent call last):
27 File "D:/python/S13/Day6/testclass.py", line 28, in <module>
28 print('class Dog:\t %s' % getattr(Dog, str_input))
29 AttributeError: type object 'Dog' has no attribute 'hehe'
30
31 Process finished with exit code 1注意:
(1) 这里新增的方法只是对实例化的对象有效,对类无效
(2) 最后在获取func的内存地址后,也就是bulk的内存地址后,调用时需要传入实例化对象方法,因为定义的新增bulk方法有参数self,而这种动态新增的方法,参数无论是否为self,都需要手动传入 - 给对象新增一个属性

1 # !/usr/bin/env python
2 # -*- coding:utf-8 -*-
3
4 class Dog(object):
5
6 def __init__(self, name):
7 self.name = name
8
9 def eat(self, food):
10 print('%s is eating %s' % (self.name, food))
11
12
13 obj1 = Dog('XiaoHuang')
14
15 str_input = input(">>>:").strip()
16 setattr(obj1, str_input, 3)
17 print(getattr(obj1, str_input))
18 print('obj1:\t %s ' % getattr(obj1, str_input))
19 print('----')
20 print(obj1.__dict__)
21
22 输出:
23 >>>:age
24 3
25 obj1: 3
26 ----
27 {'name': 'XiaoHuang', 'age': 3}
上述示例程序显示,对象新增的属性可以通过__dict__来查看到,新增成功。
2.4 delattr(obj, name_str)
作用:删除obj对象中的属性或者方法,delattr(x, 'y') is equivalent to ``del x.y''

1 class Dog(object):
2
3 def __init__(self, name):
4 self.name = name
5
6 def eat(self, food):
7 print('%s is eating %s' % (self.name, food))
8
9
10 obj1 = Dog('XiaoHuang')
11
12 str_input = input(">>>:").strip()
13 delattr(obj1, str_input)
14 print(Dog.__dict__)
15 print('----')
16 print(obj1.__dict__)
17 print(getattr(obj1, str_input))
18
19 输出:
20 #删除属性
21 >>>:name
22 Traceback (most recent call last):
23 File "D:/python/S13/Day6/testclass.py", line 24, in <module>
24 print(getattr(obj1, str_input))
25 AttributeError: 'Dog' object has no attribute 'name' #访问被删除的name属性报错
26 {'__module__': '__main__', '__init__': <function Dog.__init__ at 0x000000000219EEA0>, 'eat': <function Dog.eat at 0x000000000219EF28>, '__dict__': <attribute '__dict__' of 'Dog' objects>, '__weakref__': <attribute '__weakref__' of 'Dog' objects>, '__doc__': None}
27 ----
28 {} #实例的唯一属性name不见了
29
30 #删除方法
31 >>>:eat
32 Traceback (most recent call last):
33 File "D:/python/S13/Day6/testclass.py", line 20, in <module>
34 delattr(obj1, str_input)
35 AttributeError: eat #方法删除后立马报错了
36
三、综合运用
上面主要讲述的属性或方法的动态增、删、改、查的基本用法,实际上删除和增加用的很少,这里结合查、删、改来简述一下综合运用。

1 # !/usr/bin/env python
2 # -*- coding:utf-8 -*-
3
4 class Dog(object):
5
6 def __init__(self, name):
7 self.name = name
8
9 def eat(self, food):
10 print('%s is eating %s' % (self.name, food))
11
12
13 obj1 = Dog('XiaoHuang')
14
15 str_input = input(">>>:").strip()
16 if hasattr(obj1, str_input):
17 print('Before change')
18 print('obj1\t%s:%s' % (str_input, getattr(obj1, str_input)))
19 print('--------')
20 setattr(obj1, str_input, 'Jinba')
21 print('After change')
22 print('obj1\t%s:%s' %(str_input, getattr(obj1, str_input)))
23 else:
24 setattr(obj1, str_input, None) #对于不存在的属性设置为None,感觉意义不大?
25 print(getattr(obj1, str_input))
26
27 输出:
28 >>>:name
29 Before change
30 obj1 name:XiaoHuang
31 --------
32 After change
33 obj1 name:Jinba
34
35
day7-python类反射的更多相关文章
- Python类总结-反射及getattr,setattr
类反射的四个基本函数 hasattr getattr setattr delattr #反射 class BlackMedium: feature = 'Ugly' def __init__(self ...
- python 类知识点总结
python 类知识点总结 面向对象思想: 1.设计的时候,一定要明确应用场景 2.由对象分析定义类的时候,找不到共同特征和技能不用强求 1.简述类.对象.实例化.实例这些名词的含义: 类:从一组对象 ...
- python类:magic魔术方法
http://blog.csdn.net/pipisorry/article/details/50708812 魔术方法是面向对象Python语言中的一切.它们是你可以自定义并添加"魔法&q ...
- (转)python类:magic魔术方法
原文:https://blog.csdn.net/pipisorry/article/details/50708812 版权声明:本文为博主皮皮http://blog.csdn.net/pipisor ...
- 如何访问python类中的私有方法
在python中,不像c#/java类语言,支持类的私有方法,这点有点像objc,虽然objc可以通过扩展extension来实现,但源于objc的运行时特性,我们还是可以通过非常手段来进行访问的.不 ...
- python类的相关知识第二部分
类的继承.多态.封装 一.类的继承 1.应用场景: 类大部分功能相同,大类包含小类的情况 例如: 动物类 共性:都要吃喝拉撒.都有头有脚 特性: 猫类.走了很轻,叫声特别,喜欢白天睡觉 狗类.的叫声很 ...
- Python进阶----反射(四个方法),函数vs方法(模块types 与 instance()方法校验 ),双下方法的研究
Python进阶----反射(四个方法),函数vs方法(模块types 与 instance()方法校验 ),双下方法的研究 一丶反射 什么是反射: 反射的概念是由Smith在1982年首次提出的 ...
- Python类中super()和__init__()的关系
Python类中super()和__init__()的关系 1.单继承时super()和__init__()实现的功能是类似的 class Base(object): def __init__(sel ...
- LightMysql:为方便操作MySQL而封装的Python类
原文链接:http://www.danfengcao.info/python/2015/12/26/lightweight-python-mysql-class.html mysqldb是Python ...
随机推荐
- python数据描述符
Python的描述符是接触到Python核心编程中一个比较难以理解的内容,自己在学习的过程中也遇到过很多的疑惑,通过google和阅读源码,现将自己的理解和心得记录下来,也为正在为了该问题苦恼的朋友提 ...
- MySQL数据库--练习
学生选课系统 设计表关系 创建表和插入数据 /* Navicat MySQL Data Transfer Source Server : localhost_3306 Source Server Ve ...
- ImageNet历年冠军和相关CNN模型
ImageNet 是一个超过15 million的图像数据集,大约有22,000类. 是由李飞飞团队从2007年开始,耗费大量人力,通过各种方式(网络抓取,人工标注,亚马逊众包平台)收集制作而成,它作 ...
- ABP官方文档翻译 2.4 日志
日志 服务端 获取记录器 基类日志记录器 配置 Abp.Castle.Log4Net包 客户端 服务端 ABP使用Castle Windsor`s 日志设备.它可以使用不同的日志类库:Log4Net, ...
- mspdb100.dll不见了的解决办法
一.如果在运行某软件或编译程序时提示缺少.找不到mspdb100.dll等类似提示,将下载来的mspdb100.dll拷贝到指定目录即可 (一般是system系统目录或放到软件同级目录里面),或者重新 ...
- 《Java程序设计》 第2周学习总结
20145318 <Java程序设计>第2周学习总结 教材学习内容总结 short,2字节:int,4字节:long,8字节:byte,1字节:float,4字节:double,8字节:c ...
- Jquery10 高级事件
学习要点: 1.模拟操作 2.命名空间 3.事件委托 4.on.off 和 one jQuery 不但封装了大量常用的事件处理,还提供了不少高级事件方便开发者使用.比如模拟用户触发事件.事件委托事件. ...
- svn checkout 提示“由于连接方在一段时间后没有正确答复或连接的主机没有反应,连接尝试失败。”解决方法
安装好之后再windows上checkout项目,一直出错:“由于连接方在一段时间后没有正确答复或连接的主机没有反应,连接尝试失败”:在尝试了很多次之后找到了最后的问题所在. 在网上找的方法试过了, ...
- [BZOJ4016]最短路径树问题
Description 给一个包含n个点,m条边的无向连通图.从顶点1出发,往其余所有点分别走一次并返回. 往某一个点走时,选择总长度最短的路径走.若有多条长度最短的路径,则选择经过的顶点序列字典序最 ...
- [BZOJ3124]直径
Description 小Q最近学习了一些图论知识.根据课本,有如下定义.树:无回路且连通的无向图,每条边都有正整数的权值来表示其长度.如果一棵树有N个节点,可以证明其有且仅有N-1 条边. 路径:一 ...