python-聊聊反射
反射
对于初学python可能较难理解,但反射是非常有用。
试想一下,当别的程序传入给你写的这段代码一个变量(var=“math”),这个变量是一个字符串,这个字符串是一个模块或者一个模块下的某个方法,你需要通过变量来导入此模块或者方法,如何导入此模块或方法呢,如果直接执行 import var是会出错的,因为var在你的这段代码中是一个变量, 这时就需要反射, 如何使用反射呢。
1.聊聊自省
在计算机编程中,自省是指这种能力:检查某些事物以确定它是什么、它知道什么以及他能做什么。自省向程序员提供了极大的灵活性和控制力。
几个重要的函数:
dir函数,传入的参数是对象,返回该对象的所有属性和函数列表:
>>> dir(str)
['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__getslice__', '__gt__', '__hash__', '__init__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '_formatter_field_name_split', '_formatter_parser', 'capitalize', 'center', 'count', 'decode', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'index', 'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
可以看出,string对象的所有函数,属性都列举出来了。
getatter方法,传入参数是对象和该对象的函数或者属性的名字,返回对象的函数或者属性实例,如下:
>>> getattr('str','rfind')
<built-in method rfind of str object at 0x7fc2e04c5b10>
callable方法,如果传入的参数是可以调用的函数,则返回true,否则返回false。
>>> callable(getattr('str','rfind'))
True
>>> callable(getattr('str','__doc__'))
False
>>>
列出对象的所有可以执行的函数:这个地方用到了列表推导式:
>>> methodLIst = [method for method in dir(str) if callable(getattr(str,method))]
>>> print methodLIst
['__add__', '__class__', '__contains__', '__delattr__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__getslice__', '__gt__', '__hash__', '__init__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '_formatter_field_name_split', '_formatter_parser', 'capitalize', 'center', 'count', 'decode', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'index', 'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
2.python是如何体现反射的
globals()
这个函数返回一个map,这个map的key是全局范围内对象的名字,value是该对象的实例,在不导入任何module下,执行globals()的结果如下:
>>> globals()
{'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', '__doc__': None, '__package__': None}
>>>
在导入sys后,可以发现,globals()返回的map中,多了sys module:
>>> globals()
{'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', 'sys': <module 'sys' (built-in)>, '__doc__': None, '__package__': None}
在导入sgmlib如下:
>>> import sgmllib
>>> globals()
{'sgmllib': <module 'sgmllib' from '/usr/lib64/python2.6/sgmllib.pyc'>, '__builtins__': <module '__builtin__' (built-in)>, '__package__': None, 'sys': <module 'sys' (built-in)>, '__name__': '__main__', '__doc__': None}
如果导入类后,在map中,可以找到类SGMLParser。
>>> from sgmllib import SGMLParser
>>> globals()
{'sgmllib': <module 'sgmllib' from '/usr/lib64/python2.6/sgmllib.pyc'>, 'SGMLParser': <class sgmllib.SGMLParser at 0x7fbd2754c530>, '__builtins__': <module '__builtin__' (built-in)>, '__package__': None, 'sys': <module 'sys' (built-in)>, '__name__': '__main__', '__doc__': None}
所以,只要将class的名字作为key,即可得到class。如下:
>>> globals()['SGMLParser']
<class sgmllib.SGMLParser at 0x7fbd2754c530>
>>> parser = globals()['SGMLParser']()
>>> parser
<sgmllib.SGMLParser instance at 0x7fbd2d64f1b8>
将模块引入,之后确定模块的相应类的名字,就可以得到了一个类对象,之后就可以实例化了。
3.反射详解
python中的反射功能是由以下四个内置函数提供:hasattr、getattr、setattr、delattr,改四个函数分别用于对对象内部执行:检查是否含有某成员、获取成员、设置成员、删除成员。
#!/usr/bin/env python
#-*- coding:utf-8 -*-
__author__ = 'wyf' class Foo(object):
def __init__(self):
self.name = 'chushiyaoyue' def func(self):
return 'func' obj = Foo()#实例化一个对象 # #### 检查是否含有成员 ####
hasattr(obj, 'name') #True
hasattr(obj, 'func') #True # #### 获取成员 ####
getattr(obj, 'name')
getattr(obj, 'func')
#chushiyaoyue
#<bound method Foo.func of <__main__.Foo object at 0x0000000002C5F4A8>>
# #### 设置成员 ####
setattr(obj, 'age', 18)#添加属性
setattr(obj, 'show', lambda num: num + 1)#添加方法
# print vars(obj)
#{'age': 18, 'name': 'chushiyaoyue', 'show': <function <lambda> at 0x0000000002A46128>}#已经添加了一个属性和一个方法
# # #### 删除成员 ####
delattr(obj, 'name')
delattr(obj, 'func')
__import__('模块名字')
from 包 import 模块名 as 别名 ====等于=== 别名 = __import__("模块名的字符串")
针对该模块同一级下另外一个目录,也就是包,而这个包下有另一个包,而我们需要导入的模块还在其下面,这时候,不能应用包.包.模块作为字符串传入__import__来导入了,因为其只会导入第一层包,需要加入一个参数fromlist = True
a = __import__('包')#基础的导入
__import__("a.b.c.file.login",fromlist=True)#多层级的导入
__import__("a.b.c.file.login") #是不对的 只导入了a目录 包
python中一切实物都是对象,类,模块也是对象!反射是通过字符串的形式操作对象相关的成员!
类是对象:
#!/usr/bin/env python
#-*- coding:utf-8 -*-
__author__ = 'wyf' class Foo(object): staticField = "test123" def __init__(self):
self.name = 'chushiyaoyue' def func(self):
return 'func' @staticmethod
def bar():
return 'bar' print getattr(Foo, 'staticField')
print getattr(Foo, 'func')
print getattr(Foo, 'bar')
模块是对象:
#!/usr/bin/env python
# -*- coding:utf-8 -*- def dev():
return 'dev'
home.py
#!/usr/bin/env python
# -*- coding:utf-8 -*- """
程序目录:
home.py
index.py 当前文件:
index.py
""" import home as obj #obj.dev() func = getattr(obj, 'dev')
func()
实例小练习:根据用户输入的url执行相关的功能
#!/usr/bin/env python
#-*- coding:utf-8 -*-
__author__ = 'wyf' def login():
return 'login' def logout():
return 'logout' def nb():
return '特别牛逼的页面'
account.py
最简单粗暴的方法,简单很容易想到,但是如果方法一多,你要写很多代码
#!/usr/bin/env python
#-*- coding:utf-8 -*-
__author__ = 'wyf' from lib import account url = raw_input('请输入url:') if url.endswith('login'):
r = account.login()
print r elif url.endswith('logout'):
r = account.logout()
print r elif url.endswith('nb'):
r = account.nb()
print r else:
print ''
简单的方式
使用反射的方式,一步到位不管你有多少个方法调用,我都支持
#!/usr/bin/env python
#-*- coding:utf-8 -*-
__author__ = 'wyf' from lib import account
url = raw_input('请输入url:')
target_module,target_func = url.split('/') m = __import__('lib.',target_module,fromlist=True)
if hasattr(m,target_func):#判断这个函数里面是否存在这个方法
target_func = getattr(account,inp)#获取这个方法
r = target_func()#执行这个方法
print r
else:
print ''
python-聊聊反射的更多相关文章
- python的反射机制
转载自:http://www.cnblogs.com/feixuelove1009/p/5576206.html 对编程语言比较熟悉的朋友,应该知道"反射"这个机制.Python作 ...
- python的反射
目前大多数网站都是通过路由的方法来,处理url请求,如果有很多个url的话,不停的include或者用if判断匹配,似乎不太符合情理,因此这里讲讲python的反射机制, 自动装在模块.请看下面的实例 ...
- 简单谈谈python的反射机制
转:http://www.jb51.net/article/87479.htm 本文主要介绍python中的反射,以及该机制的简单应用,熟悉JAVA的程序员,一定经常和Class.forName打交道 ...
- 【转】简单谈谈python的反射机制
[转]简单谈谈python的反射机制 对编程语言比较熟悉的朋友,应该知道“反射”这个机制.Python作为一门动态语言,当然不会缺少这一重要功能.然而,在网络上却很少见到有详细或者深刻的剖析论文.下面 ...
- Python进阶----反射(四个方法),函数vs方法(模块types 与 instance()方法校验 ),双下方法的研究
Python进阶----反射(四个方法),函数vs方法(模块types 与 instance()方法校验 ),双下方法的研究 一丶反射 什么是反射: 反射的概念是由Smith在1982年首次提出的 ...
- Python之反射,正则
本节主要内容: 一. 反射: getattr hasattr setattr defattr 二. 补充模块中特殊的变量 三. 正则表达式 re模块 (一)反射: hasattr(object, na ...
- 关于PYTHON的反射,装饰的练习
从基本概念,简单例子才能慢慢走到高级一点的地方. 另外,PYTHON的函数式编程也是我很感兴趣的一点. 总体而言,我觉得OOP可以作大的框架和思路,FP能作细节实现时的优雅牛X. ~~~~~~~~~~ ...
- 详解python之反射机制
一.前言 def f1(): print('f1') def f2(): print('f2') def f3(): print('f3') def f4(): print('f4') a = 1 t ...
- 第六章:Python基础の反射与常用模块解密
本课主题 反射 Mapping 介绍和操作实战 模块介绍和操作实战 random 模块 time 和 datetime 模块 logging 模块 sys 模块 os 模块 hashlib 模块 re ...
- python 异常 反射
异常 反射 一.异常处理: AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x IOError 输入/输出异常:基本上是无法打开文件 ImportError ...
随机推荐
- CmdParse
Procedure URPOSE Uses Dos,Crt; Const VersionNum = 'V1.0 BETA'; ProgNameStr = 'NEWPROJ.EXE'; ProgName ...
- python基础(四)
内置函数 callable() #判断是否能够被调用执行,可以调用返回True,例如函数和类 chr() #将ascii值转换为字符,例如print(chr(65) )输出为a ord()#将字符转换 ...
- JQuery DataTables Editor---页面内容修改&&数据库信息修改 (1)
我们使用jquery datatables 不光是为了对数据的展示,同时需要对数据惊行简单的操作,这个操作分为两个部分:1.页面内容的修改:2.对应的数据库信息的修改. 前一篇博文介绍了页面级的操作, ...
- oc block基本使用
// // main.m // block基本使用 // // Created by Ymmmsick on 15/7/21. // Copyright (c) 2015年 Ymmmsick. All ...
- keil MDK的信号函数
keil的信号函数用于模拟和测试串行IO,模拟IO,端口通讯等重复发生的外部事件. 信号函数以关键字signal开头.在函数中必须调用twatch用于延时,不然keil会陷入死循环.twatch函数的 ...
- 使用Flex图表组件
原文 http://blog.csdn.net/mylxiaoyi/article/details/1618470 使用Flex图表组件 以图表或是图的方式显示数据的能力可以使得Flex程序用户的数据 ...
- 怎样学习使用libiconv库
怎样学习使用libiconv库 - My Study My Study About My Learn or Study etc. 怎样学习使用libiconv库 By Cnangel on Febru ...
- Android 弹出通知Toast的使用
//官方帮助文档:http://wear.techbrood.com/guide/topics/ui/notifiers/toasts.html <LinearLayout xmlns:andr ...
- SQLite使用报告
SQLite简介 SQLite是遵守ACID的关联式数据库管理系统,它包含在一个相对小的C库中.它是D.RichardHipp建立的公有领域项目. 不像常见的客户-服务器范例,SQLite引擎不是个程 ...
- [Oracle] - 性能优化工具(3) - ADDM
ADDM 通过检查和分析AWR获取的数据来推断Oracle数据库中可能的问题.并给出优化建议. 获取ADDM的方法例如以下: @?/rdbms/admin/addmrpt.sql 以下能够看一个样例: ...