一、反射

1、模块导入

为方便反射的讲解,首先我们先引入import导入的方式(我们已经在python开发[第九篇]中讲解过一些基本知识)的进一步提升。

模块的导入的常见方式是:

import commons  #当导入的模块与现在的正在编写的模块在同一个级别,或者是在上一级目录中
 
import commons as CC  #给模块重新命令

from lib.test import index   #当模块在一个多级目录下

import lib.test.index   #当模块在一个多级目录下

上面的导入方式皆是最简单的方式,而且我们也不能得知导入的模块属性是什么(字符串,还是其他什么),如:commons 我们并不知道他的类型是什么。为了解决这个问题,我们发现了 __import__("模块名")方法,如下:


__import__
("commons") #导入同级或者上一级的模块 __import__("lib.test.index",fromlist=True) #导入多级目录下的模块, fromlist就是为了实现目录的依次查询

从上面可以看见,模块名——>>使用的是字符串格式。

2、反射

python中的反射功能是由以下四个内置函数提供:hasattr、getattr、setattr、delattr,改四个函数分别用于对对象内部执行:检查是否含有某成员、获取成员、设置成员、删除成员。如下详解:

"""
假设现在有模块,commons.py 。模块内容如下:

name="alex"
def f1():
  return "ff"
"""

#######getattr方法#######
#1 import commons

#将f1方法以字符串的格式传入。在commons模块下,寻找f1属性,并将属性赋值给target_func
target_func
= getattr(commons,"f1") target_func() #执行结果:ff

#2
DD = __import__("commons) #通过另一中方式导入模块
target_func = getattr(DD,"f1")
# 设置默认值,没有找到为默认值
target_func = getattr(DD,"f1",None) #None是设置的默认值,如果没有找到,那么print(target_func)=None。
# 还可以获取全局变量
str_ = getattr(DD,"name",None)
#########hasattr方法#########
# 判断 函数或变量存在与否, true or false r= hasattr(commons,"name") r= hasattr(commons,"func")
########setattr方法######### 设置 变量或者定义函数 fuc
= setattr(commons,"f4", lambda x:x+2) str_s = setattr(commons,"name3", "weiwei") #注意:这个添加只是内存上的添加,并不会在模块文件中出现添加
#########delattr方法####### 删除 变量或者定义函数 f
= delattr(commons,"name")
#注意:这个删除方法也只是在内存上的删除,并不会删除文件中的内容

3、使用反射查找类中成员

当我们要访问一个对象的成员时,应该是这样操作:

class Foo(object):
 
    def __init__(self):
        self.name = 'alex'
 
    def func(self):
        return 'func'
 
obj = Foo()
 
# 访问字段
obj.name
# 执行方法
obj.func()
那么问题来了?
a、上述访问对象成员的 name 和 func 是什么? 
答:是变量名
b、obj.xxx 是什么意思? 
答:obj.xxx 表示去obj中或类中寻找变量名 xxx,并获取对应内存地址中的内容。
c、需求:请使用反射寻找类中的成员
class Foo(object):

    def __init__(self):
        self.name = 'alex'
    def func(self):
        return 'func'

r=hasattr(Foo,"__init__")
print(r)  #执行结果:True
t=hasattr(Foo,"name")
print(t)  #执行结果:False  #说明name不是类的成员
c、需求:请使用其他方式获取obj对象中的name变量指向内存中的值 “alex”,该如何做?
答:有两种方式,如下:
#####方式一
class Foo(object):

    def __init__(self):
        self.name = 'alex'

    def func(self):
        return 'func'

# 不允许使用 obj.name来进行访问
obj = Foo()

print (obj.__dict__['name'])

#######方式二

# 不允许使用 obj.name来进行访问
obj = Foo()

print (getattr(obj, 'name'))   #因为name是obj对象中封装的。所以name本就在对象中
print(getatter(obj,"func"))

结论:1.反射是通过字符串的形式操作对象相关的成员。一切事物都是对象!!!

        2.成员是指:当前对象(模块)下所具有的实际变量(不包含形式参数)、函数以及类

4、实战1:

"""
有模块accout.py是网页的后台程序。

如果用户输入:www.etitian.org/accout/login。那么就意味着要去accout模块,执行login函数。针对这种情况,可以进行如下代买

"""
import accout
def runserver(url):
    x=url.split("/").[-1]
    if hasattr(accout,x):
        target=getattr(accout,x)
        target()
    else:
        print("404")

if __name__=="__main__":
    inp=input("请输入url地址:")
    runnserver(inp)

 实战2:

现在我们知道了文件下有类,类下有对象。那么我们如何通过反射从文件里去获取对象中的方法

#假设现在有模块(文件)index.py。模块中存有如下代码:
class
Foo(object): def __init__(self): self.name = 'alex' def func(self): return 'func'

实现方法:

target=__import__("s2",fromlist=True)  #导入模块文件
xx=getattr(target,"Foo")  #从模块中获取类
r=xx()  #创建类对象
name=getattr(r,"name")  #从对象中获取成员
print(name)

 

posted on 2017-06-08 11:38  进_进  阅读(172)  评论(0)    收藏  举报