因为目前在写一个python的项目,用到了Python的反射机制,所以做一下笔记,把写项目过程中的感悟记下来。

先简单介绍下Demo用到的函数:

sys.path 是python的模块的路径集,是一个集合(使用之前记得导入sys模块)

  1. >>> sys.path
  2.  
  3. ['', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-i386-linux-gnu', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages/PILcompat', '/usr/lib/python2.7/dist-packages/gtk-2.0', '/usr/lib/pymodules/python2.7', '/usr/lib/python2.7/dist-packages/wx-3.0-gtk2']

如果你想追加一个模块那么将他的文件夹绝对路径添加到sys.path内就可以了

  1. >>> sys.path.append('/usr/develop/git/nearsec/')
  2. >>> sys.path
  3. ['', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-i386-linux-gnu', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages/PILcompat', '/usr/lib/python2.7/dist-packages/gtk-2.0', '/usr/lib/pymodules/python2.7', '/usr/lib/python2.7/dist-packages/wx-3.0-gtk2', '/usr/develop/git/nearsec/']

当然这只是临时的程序结束后,sys.path还是会恢复到原来的样子。

*****************************************************************************************************************

这部分可跳过,这部分的讲解只是为了让初学者更深的的理解反射的原理。

*****************************************************************************************************************

  1. 使用globals()获取当前内存中存在哪些对象,该方法返回一个字典(假设有一个base.py文件,文件内有一个Base类):
  2.  
  3. >>>globals()
  4.  
  5. 创建Base类对象前:
  6.  
  7. {'__builtins__': <module '__builtin__' (built-in)>, '__file__': './main.py', '__package__': None, 'sys': <module 'sys' (built-in)>, 're': <module 're' from '/usr/lib/python2.7/re.pyc'>, '__name__': '__main__', 'unittest': <module 'unittest' from '/usr/lib/python2.7/unittest/__init__.pyc'>, 'os': <module 'os' from '/usr/lib/python2.7/os.pyc'>, '__doc__': None}
  8.  
  9. 创建Base类对象后:
  10.  
  11. {'__builtins__': <module '__builtin__' (built-in)>, '__file__': './main.py', '__package__': None, 'sys': <module 'sys' (built-in)>, 're': <module 're' from '/usr/lib/python2.7/re.pyc'>, 'Base': <class base.Base at 0xb743520c>, 'base': <base.Base instance at 0xb743974c>, '__name__': '__main__', 'os': <module 'os' from '/usr/lib/python2.7/os.pyc'>, '__doc__': None}
  12.  
  13. 下面是使用dir()的结果
  14.  
  15. >>>dir()
  16.  
  17. 创建Base类对象前(可以看出内存已经导入了Baseosresys等模块):
  18.  
  19. ['Base', '__builtins__', '__doc__', '__file__', '__name__', '__package__', 'os', 're', 'sys']
  20.  
  21. 创建Base类对象后:
  22.  
  23. ['Base', '__builtins__', '__doc__', '__file__', '__name__', '__package__', 'base', 'os', 're', 'sys']
  24.  
  25. 如果dir()方法内写入一个对象,如:dir(sys)则返回sys模块的所有方法名称:
  26.  
  27. >>>dir(sys)
  28.  
  29. ['__displayhook__', '__doc__', '__excepthook__', '__name__', '__package__', '__stderr__', '__stdin__', '__stdout__', '_clear_type_cache', '_current_frames', '_getframe', '_mercurial', '_multiarch', 'api_version', 'argv', 'builtin_module_names', 'byteorder', 'call_tracing', 'callstats', 'copyright', 'displayhook', 'dont_write_bytecode', 'exc_clear', 'exc_info', 'exc_type', 'excepthook', 'exec_prefix', 'executable', 'exit', 'flags', 'float_info', 'float_repr_style', 'getcheckinterval', 'getdefaultencoding', 'getdlopenflags', 'getfilesystemencoding', 'getprofile', 'getrecursionlimit', 'getrefcount', 'getsizeof', 'gettrace', 'hexversion', 'long_info', 'maxint', 'maxsize', 'maxunicode', 'meta_path', 'modules', 'path', 'path_hooks', 'path_importer_cache', 'platform', 'prefix', 'py3kwarning', 'pydebug', 'setcheckinterval', 'setdlopenflags', 'setprofile', 'setrecursionlimit', 'settrace', 'stderr', 'stdin', 'stdout', 'subversion', 'version', 'version_info', 'warnoptions']

上面对比可以看出两个方法均可以获取当前内存中的所有对象与导入的模块。

*****************************************************************************************************************

__import__(moudle) 函数更能使导入一个模块,与头部的“import moudle”一样,只不过__inport__()是动态导入模块。

既然可以通过__import__(moudle)将模块加载到内存中,那么当然可以通过python的内部函数获取模块中的某个方法了,使用getattr(moudle, 'class_name')根据模块获取对象:clas = getattr(moudle, "class_name“这样就获取到了对象clas,既然clas已经获取到了那不是想调用任何方法不都可以了吗。

好了,用到的函数都已经讲解了一遍,进入主题吧(继承也不懂得去自己查查资料吧。^_^

首先演示不继承情况下调用,main.py是Demo1测试的入口

  1. #!/usr/bin/python
  2.  
  3. # -*- coding: utf- -*-
  4.  
  5. #Version: 0.01
  6.  
  7. #Create: --
  8.  
  9. #Authoruis: kun/
  10.  
  11. #project: main.py
  12.  
  13. import sys,os,re
  14.  
  15. def main():
  16.  
  17. base = __import__('base')#动态加载Base模块
  18.  
  19. clas = getattr(base, "Base")#获取Base对象
  20.  
  21. clas.test()#调用base中的方法
  22.  
  23. if __name__ == '__main__':
  24.  
  25. main()
  26.  
  27. #!/usr/bin/python
  28.  
  29. # -*- coding: utf- -*-
  30.  
  31. #Version: 0.01
  32.  
  33. #Create: --
  34.  
  35. #Authoruis: kun/
  36.  
  37. #project: base.py
  38.  
  39. class Base():
  40.  
  41. def __init__(self):
  42.  
  43. print 'init Base !'
  44.  
  45. @staticmethod
  46.  
  47. def test():
  48.  
  49. print 'Base test is running !'
  50.  
  51. 接下来是Demo2main.py 还是执行入口,继承后的反射调用:
  52.  
  53. #!/usr/bin/python
  54.  
  55. # -*- coding: utf- -*-
  56.  
  57. #Version: 0.01
  58.  
  59. #Create: --
  60.  
  61. #Authoruis: kun/
  62.  
  63. #project: main.py
  64.  
  65. import sys,os,re
  66.  
  67. def main():
  68.  
  69. base = __import__(sys.argv[])#动态加载控制台输入的模块名
  70.  
  71. clas = getattr(base, sys.argv[])#动态获取对象
  72.  
  73. clas.test()#调用base中的方法
  74.  
  75. print globals()
  76.  
  77. if __name__ == '__main__':
  78.  
  79. main()
  80.  
  81. #!/usr/bin/python
  82.  
  83. # -*- coding: utf- -*-
  84.  
  85. #Version: 0.01
  86.  
  87. #Create: --
  88.  
  89. #Authoruis: kun/
  90.  
  91. #project: base.py
  92.  
  93. class Base():
  94.  
  95. def __init__(self):
  96.  
  97. print 'init Base !'
  98.  
  99. @staticmethod
  100.  
  101. def test():
  102.  
  103. print 'Base test is running !'
  104.  
  105. #!/usr/bin/python
  106.  
  107. # -*- coding: utf- -*-
  108.  
  109. #Version: 0.01
  110.  
  111. #Create: --
  112.  
  113. #Authoruis: kun/
  114.  
  115. #project: test.py
  116.  
  117. from base import Base
  118.  
  119. class test(Base):
  120.  
  121. @staticmethod
  122.  
  123. def test():
  124.  
  125. print 'test test() is run !'
  1. 控制台:
  2.  
  3. root@kun:/usr/develop/git/demo# ./main.py test
  4.  
  5. test test() is run !
  6.  
  7. {'__builtins__': <module '__builtin__' (built-in)>, '__file__': './main.py', '__package__': None, 'sys': <module 'sys' (built-in)>, 're': <module 're' from '/usr/lib/python2.7/re.pyc'>, '__name__': '__main__', 'main': <function main at 0xb74c1454>, 'os': <module 'os' from '/usr/lib/python2.7/os.pyc'>, '__doc__': None}

后记:其实这个demo也算是为我正在开发安全项目的一个学习Demo,可拓展部分的代码核心就是有这些思想所组成,实现整个框架的可拓展性。目前,整个框架的核心源码基本完成了,我希望找几个小伙伴一起来完善好这个框架,有这个意向和能力的小伙伴联系我吧:qq1033163112。

Demo2中有个小瑕疵就是类名都必须小写,其实解决这个问题并不难,调用python的提供的函数将首字母转换为大写即可。后期我还会写出框架中用到其它技术的核心代码讲解Demo,项目最迟会在年中的时候开源,小伙伴们敬请期待吧。

python 反射调用的更多相关文章

  1. python反射

    python反射 python的反射是基于字符串的形式去对象(模块)中操作其成员.此操作是动态的,常用于web开发中url参数中对应模块或者函数的反射. 下面开始具体说明: 场景需求: 我的pytho ...

  2. python 全栈开发,Day94(Promise,箭头函数,Django REST framework,生成json数据三种方式,serializers,Postman使用,外部python脚本调用django)

    昨日内容回顾 1. 内容回顾 1. VueX VueX分三部分 1. state 2. mutations 3. actions 存放数据 修改数据的唯一方式 异步操作 修改state中数据的步骤: ...

  3. Python反射机制理解

    Python反射机制用沛齐老师总结的话说就是:利用字符串的形式去对象(模块)中操作(寻找)成员. getattr(object, name) object代表模块,name代表模块中的属性或成员,该函 ...

  4. Python反射和内置方法(双下方法)

    Python反射和内置方法(双下方法) 一.反射 什么是反射 反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问.检测和修改它本身状态或行为的一种能力(自省).这一概念的提出很快引发 ...

  5. python 反射

    python 反射的核心本质其实就是利用字符串的形式去对象(模块)中操作(查找/获取/删除/添加)成员,一种基于字符串的事件驱动! 反射的四个基本函数使用 hasattr,getattr,setatt ...

  6. C#如何反射出委托的签名,如何使用反射调用委托

    本文阐述C#中如何反射出委托的签名,假如我们有委托FooDelegate定义如下 delegate double FooDelegate (string param, bool condition); ...

  7. 外壳exe通过反射调用dll时

    外壳exe通过反射调用dll时,dll是 4.0的框架,外壳exe也需要编译成4.0的框架,如果dll本身有调用32位的dll,那么外壳exe也需要编译成32位. 调试时报的那个错,直接继续运行,不影 ...

  8. 从vs2010的UnitTestFramework类库提取私有方法反射调用的方法

    背景 年龄大点的程序员都知道在vs2010中创建单元测试非常的简单,鼠标定位在方法名字,右键创建单元测试,就会创建一个测试方法,即使是在私有方法上也可以创建测试方法. VS2010以后就没这么简单了, ...

  9. VS2010 F5调试时出现:“ 尝试运行项目时出错:未捕获通过反射调用的方法引发的异常”解决

    VS2010 F5调试时出现 尝试运行项目时出错:未捕获通过反射调用的方法引发的异常 两个解决方法:1) 打开项目属性,选择调试选项卡,将“启用非托管代码调试”一项钩上.2) 打开项目属性,选择调试选 ...

随机推荐

  1. LaTex 插入图片

    \usepackage{mathrsfs} \usepackage{amsmath} \usepackage{graphicx} 宏包 \includegraphics{graph01.eps} %插 ...

  2. SevenZip.pas BUG修改版 - 20160613

    原始版本: Henri Gourvest <hgourvest@gmail.com> 1.2版本 BUG修改: 1.对于文件名中带有空格的文件, 无法压缩, 原因是1488行, 压缩调用的 ...

  3. Count Complete Tree Nodes || LeetCode1

    /** * Definition for a binary tree node. * struct TreeNode { * int val; * struct TreeNode *left; * s ...

  4. http://www.blogjava.net/xylz/archive/2013/08/05/402405.html

    http://www.blogjava.net/xylz/archive/2013/08/05/402405.html

  5. elasticsearch使用操作部分

    本片文章记录了elasticsearch概念.特点.集群.插件.API使用方法. 1.elasticsearch的概念及特点.概念:elasticsearch是一个基于lucene的搜索服务器.luc ...

  6. Range对象理解,浏览器兼容性,获取鼠标光标位置

    一.关于浏览器的兼容性 目前主要有3种关于range的类似的对象,分别是W3C range 对象,Mozzlia selection ,ie TextRange 关于这三种的区别,请查看文档 http ...

  7. The tag 'DataGridTextColumn' does not exist in XML namespace ....

    错误 10 The tag 'DataGridTextColumn' does not exist in XML namespace 'http://schemas.microsoft.com/win ...

  8. in-list expansion

    in-list expansion也被称作or expansion --针对in后面是常量集合的另外一种处理方法.优化器会把目标sql中in后面的常量集合拆开,把里面的每个常量都提出来形成一个分支,各 ...

  9. mvc ajax dropdownlist onchang事件响应

    <script type="text/javascript"> $("#Cycle").on("change", functio ...

  10. Latex 学习

    Latex 学习 @(05.2 Latex)[latex][基础教程] 这篇文章是关于latex基础教程.pdf的一个总结. 基本知识 基础 1. 空格 多个空格会被视为一个空格 单个回车会被视为一个 ...