断断续续从年前到现在学了面向对象一个月了,之前学反射的时候,只是都是看下代码,理解就可以了,今天在代码的时候还是不太得心应手,于是百度各种,终于明白了,写此博客,供自省。
反射
1 什么是反射
反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。
2 python面向对象中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)
四个可以实现自省的函数 下列方法适用于类和对象(一切皆对象,类本身也是一个对象)
看了定义,还是只是了解一下,不贴代码都是刷流氓,直接上代码。
# test.py import sys def fn(): print(‘hello world‘) func_name = fn.__name__ fn_obj = getattr(sys.modules[__name__], func_name) # 根据函数名(func_name),获得函数对象 fn_obj()
运行结果是:
hello world
先大致看一下思路,
1. 首先定义了一个fn的函数
2. 通过获取当前__name__的值 来反射
估计你也是看的云里雾里。接下来我一一解释。
抛砖引玉
对于__name__大家不知道理解不,上代码。
#!/usr/bin/env python def test(): print('hello world.') print("__name__ = ",__name__) if __name__ == '__main__': test() hdfs@loocha11:~$ cat test2.py import test test.test()
运行
hdfs@loocha11:~$ python3 test.py hello world. __name__ = __main__ hdfs@loocha11:~$ python3 test2.py hello world. __name__ = test
从上可以看出,直接运行test的时候__name__就是等于字符串‘__main__’,要是被其他文件导入此时__name__就是等于模块名字。
总结:
当模块不是导入,而是直接运行,那么__name__的值就是__main__。理解__name__了吧。
知识点:
sys.modules是一个全局字典,该字典是python启动后就加载在内存中。
每当程序员导入新的模块,sys.modules都将记录这些模块。
字典sys.modules对于加载模块起到了缓冲的作用。
当某个模块第一次导入,字典sys.modules将自动记录该模块。
当第二次再导入该模块时,python会直接到字典中查找,从而加快了程序运行的速度。
既然懂了__name__,接下来我们继续最初的代码一一分析。
自省的函数 下列方法适用于类和对象(一切皆对象,类本身也是一个对象),先看其中两个。
hasattr(object,name)
判断object中有没有一个name字符串对应的方法或属性
getattr(object, name, default=None)
def getattr(object, name, default=None): # known special case of getattr """ getattr(object, name[, default]) -> value Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y. When a default argument is given, it is returned when the attribute doesn't exist; without it, an exception is raised in that case. """ pass
# test.py import sys def fn(): print(‘hello world‘) func_name = fn.__name__ # fn_obj = getattr(sys.modules[__name__], func_name) # 根据函数名(func_name),获得函数对象 fn_obj()
分析
1. 此时等于 func_name 等于 fn, 2. __name__ 等于 __main__ 3. sys.modules[__name__] 等于 sys.modules[test.py] #这个可能说不太妥当 4. getattr(sys.modules[__name__], func_name) 也就是sys.modules[__name__] 中取fn方法对象。
5. fn_obj() 表示 sys.modules[__name__] 中取fn方法实现也就是执行输出
此时应该理解最初的代码了吧