知识点 - python 反射

Posted 如果迎着风就飞,俯瞰这世界有多美

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识点 - python 反射相关的知识,希望对你有一定的参考价值。

    断断续续从年前到现在学了面向对象一个月了,之前学反射的时候,只是都是看下代码,理解就可以了,今天在代码的时候还是不太得心应手,于是百度各种,终于明白了,写此博客,供自省。

反射

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()
[email protected]:~$ cat test2.py 
import test

test.test()

运行

[email protected]:~$ python3 test.py 
hello world.
__name__ =  __main__
[email protected]:~$ 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方法实现也就是执行输出

此时应该理解最初的代码了吧

 

以上是关于知识点 - python 反射的主要内容,如果未能解决你的问题,请参考以下文章

python 知识点:反射 之 getattr()实现以字符串形式导入模块和执行函数

反射基本知识

为啥我的 Ray March 片段着色器反射纹理查找会减慢我的帧速率?

python小知识片段

python小知识片段

OpenGL片段着色器不照亮场景