python反射

反射

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

class Foo(object):

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

    def func(self):
        return 'func'

obj = Foo()

# #### 检查是否含有成员 ####
hasattr(obj, 'name')
hasattr(obj, 'func')

# #### 获取成员 ####
getattr(obj, 'name')
getattr(obj, 'func')

# #### 设置成员 ####
setattr(obj, 'age', 18)
setattr(obj, 'show', lambda num: num + 1)

# #### 删除成员 ####
delattr(obj, 'name')
delattr(obj, 'func')

详细解析:

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

class Foo(object):

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

    def func(self):
        return 'func'

obj = Foo()

# 访问字段
obj.name
# 执行方法
obj.func()

那么问题来了?

a、上述访问对象成员的 name 和 func 是什么?

答:是变量名

b、obj.xxx 是什么意思?

答:obj.xxx 表示去obj中或类中寻找变量名 xxx,并获取对应内存地址中的内容。

c、需求:请使用其他方式获取obj对象中的name变量指向内存中的值 “henry”
class Foo(object):

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

# 不允许使用 obj.name
obj = Foo()

答:有两种方式,如下:

class Foo(object):

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

    def func(self):
        return 'func'

# 不允许使用 obj.name
obj = Foo()

print(obj.__dict__['name']) #__dict__方法可以获取对象obj的成员,并保存在字典中
class Foo(object):

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

    def func(self):
        return 'func'

# 不允许使用 obj.name
obj = Foo()

print(getattr(obj, 'name')) #通过反射的方法获取对象的变量
d、比较三种访问方式
  • obj.name
  • obj.dict['name']
  • getattr(obj, 'name')

答:第一种和其他种比,...

第二种和第三种比,...

web框架实例如下:

#!/usr/bin/env python
#coding:utf-8
from wsgiref.simple_server import make_server

class Handler(object):

    def index(self):
        return 'index'

    def news(self):
        return 'news'


def RunServer(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])
    url = environ['PATH_INFO']
    temp = url.split('/')[1]
    obj = Handler()
    is_exist = hasattr(obj, temp)
    if is_exist:
        func = getattr(obj, temp)
        ret = func()
        return ret
    else:
        return '404 not found'

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

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

反射当前模块成员:

#!/usr/bin/env python
# -*- coding:utf-8 -*-

import sys


def s1():
    print('s1')


def s2():
    print('s2')


this_module = sys.modules[__name__]

hasattr(this_module, 's1')
getattr(this_module, 's2')

类也是对象

class Foo(object):

    staticField = "old boy"

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

    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'
#!/usr/bin/env python
# -*- coding:utf-8 -*-

"""
程序目录:
    home.py
    index.py

当前文件:
    index.py
"""


import home as obj

#obj.dev()

func = getattr(obj, 'dev')
func()

附:反射的妙用

#!/usr/bin/env/ python

import sys

class WebServer(object):
    def __init__(self, host, port):
        self.host = host
        self.port = port
    def start(self):
        print("Server is starting...")
    def stop(self):
        print("Server is stopping...")
    def restart(self):
        self.stop()
        self.start()

def test_run(self, name):
    print("running." ,name,self.host)

if __name__=="__main__":
    server = WebServer('localhost',333)
    server2 = WebServer('localhost',333)
    if hasattr(server,sys.argv[1]):
        func = getattr(server,sys.argv[1])  #获取server.start内存地址
        func()

    setattr(server,'run',test_run)
    server.run(server,'messi')
    # delattr(WebServer,'start')
    # print(server.restart())

#输出结果:
Server is starting...
running. messi localhost
posted @ 2016-03-22 22:05  鬼凤  阅读(131)  评论(0编辑  收藏  举报