python学习笔记-Day08--(反射)

从一开始学习这一块感觉blog就比较难写,本来就不太会写博客的问题就更严重了。j_0012.gif

想不出什么形象的比喻。所以要写blog的时候我的心情是这样的j_0004.gif,但是我的心情应该调整成这样的j_0002.gif


还是用上课时举的例子来说明白。


首先说明一下,反射要用到内置函数,

getattr(obj,name)
hasattr(obj,name)
delattr(obj,name)  #操作内存,不影响文件,很少使用
setattr(obj,name)  #操作内存,不影响文件,很少使用


先看一下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.


从一个对象中得到一个命名的属性, getattr(x,"y")  等价于 x.y

其他三个函数与此类似。

上面的先有个印象就好。下面开始详细说明:


首先我们先考虑一个问题。

当我们访问一个网址的时候,我们可以发现,每一个网址都有一个对应的页面。

最直观的python代码实现就是:


            import web

            url = raw_input("url:")

            if url =="web/url01":

                result = web.page01()      #处理页面数据,并返回结果

                print  result

            elif url =="web/url02":

                result = web.page02()    #处理页面数据,并返回结果

                print  result

            elif url =="web/url03":

                result = web.page03()   #处理页面数据,并返回结果

                print  result

            ............

            else:

                print "404 not found"


 web.py的内容如下:

            def url01():

                return "This is  ur01"

            def url01():

                return "This is  ur02"

            def url01():

                return "This is  ur03"

            ............


如果网页少的时候是没有问题的,但是当网页越来越多的时候,这样做显然是不行的。

优化以后外面可以用下面的办法(没有加url判断,即url不存在的时候)


import web

url = raw_input("url:")

preUrl,endUrl = url.split("/")

func = getattr(web,endUrl) 

result = func()

print result


运行代码,如果此时输入的url为     web/url01

那么输出结果为:    This is  ur01


使用正常的代码实现为:(有错误判断)

        from wsgiref.simple_server import make_server

        def RunServer(environ, start_response):
            start_response('200 OK', [('Content-Type', 'text/html')])
            url = environ['PATH_INFO']

            # temp 等于方法的名字
            temp = url.split('/')[1]

            #导入web模块
            import web

            #判断web模块中是否含有 temp,用与判断成员是否存在
            is_exist = hasattr(web, temp)
            if is_exist:

                # 将temp赋值给func,获取函数
                func = getattr(web, temp)
                #ret 得到func()的返回值
                ret = func()
                return ret
            else:
                return '404 not found'

        if __name__ == '__main__':
            httpd = make_server('', 8001, RunServer)
            print "Serving HTTP on port 8001..."
            httpd.serve_forever()


上面的代码其实就是运行一个httpServer ,如果这个httpServer 得到一个url,就会判断这个url是否存在,如果存在就调用相应的模块和方法,如果不存在就返回 404错误


所有的操作就是对内存中内容的操作

看完下面的代码可能就会明白了

import  web                            # 导入web模块,加载到内存

print dir(web)                         # 查看web模块有那些内容

print hasattr(web,"web_hasattr")        #判断web模块是否含有 “web_hasattr” 方法或属性
print getattr(web,"url01")                     # 得到web模块中的url01方法(或属性,本文中为方法),并打印

setattr(web,"newFun","newFun value")  # 给web模块增加 "newFun" 方法或属性,值为"newFun value"

                                该操作为内存中的操作,不影响磁盘上的文件,也就是说,源文件不会发生变化         
print dir(web)

print delattr(web,"fun1")# 删除web模块中的 "newFun" 方法或属性
                               同样该操作为内存中的操作,不影响磁盘上的文件,也就是说,源文件不会发生变化  print dir(page01)

对比看六次print的输出结果:
['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'fun1', 'fun2', 'fun3', 'fun4', 'fun5']
False
<function fun1 at 0x7fbebff587d0>
['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'fun1', 'fun2', 'fun3', 'fun4', 'fun5', 'newFun']
None
['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'fun2', 'fun3', 'fun4', 'fun5', 'newFun']



开脑洞的想法:

delattr(obj,name)  和 setattr(obj,name)  都是在内存操作,那么类也是可以存在于内存中的,那么这两个函数同样可以对内存中的类进行操作。

        class foo:

            staticVar= "staticVar"
            def __init__(self):
                self.var ="var"
            def show(self):
                pass
            @staticmethod
            def sshow():
                pass
            @classmethod
            def cshow(cls):
                pass

        obj =foo()
        print dir(obj)
        print obj.__dict__
        print hasattr(obj,"sdf")
        print hasattr(obj,"show")
        输出结果:
        ['__doc__', '__init__', '__module__', 'cshow', 'show', 'sshow', 'staticVar', 'var']
        {'var': 'var'}
        False
        True    


好,继续前面的,前面的代码主要都是使getattr(obj,name)的第二个参数为动态参数来处理不同的url

对于网站来说,不可能把所有的页面处理方法都写在一个文件里,那么如果动态的使用不同文件里的不同方法(或属性)呢?

即 动态的使用  getattr(obj,name)  的第一个参数。

看如下代码:

controller,action = raw_input("url:").split("/")
module = __import__(controller)  #等价于 import 模块名 as module
func=  getattr(module,action)
ret = func()
print ret


这里的代码就是上面所有代码的最终版,

也就是我们所说的反射

我理解的是反射就是

你出发某一个条件,然后系统根据找个条件去做处理,并给你返回处理结果。


就好像经过 巴甫洛夫 训练后的狗

你一摇铃铛 狗就流口水。。。


大神博客地址

http://home.cnblogs.com/u/wupeiqi/

我的blog地址:

http://www.timesnotes.com/?p=139




你可能感兴趣的:(python,反射,getattr,setattr,delattr,hasattr)