反射

反射

反射是什么?

在绝大多数语言当中都有反射机制的存在,
可以用字符串的方式去访问对象的属性,调用对象的方法(但是不能去访问方法),Python中一切皆对象,都可以使用反射

反射有什么用?

反射是为了增加程序的动态描述能力。通俗一些,就是可以让用户参与代码执行的决定权。

怎么用反射?

hasattr(obj,'属性')  obj.属性  判断该对象属性是否存在
getattr(obj,'属性')  获取obj.属性  不存在就会报错
setattr(obj,'属性')  设置obj.属性  =  属性值
delattr(obj,'属性')  删除obj.属性

那好,现在呢我们有这样一个应用场景,就是要根据用户输入的url也就是网址的不同,来调用不同的函数,实现不同的操作

1、简单版

首先先定义几个视图函数

###### view.py 视图文件

def login():
    """
    登陆视图函数
    :return: 
    """
    print("登陆页面")

def logout():
    """
    退出视图函数
    :return: 
    """
    print("退出页面")

def index():
    """
    网站首页
    :return: 
    """
    print("网站主页")


#######  start.py 启动文件
import view

def run():
    """
    启动程序
    :return: 
    """
    inp = input("请输入你想要访问的页面:").strip()
    if inp == "login":
        login()
    elif inp == "logout":
        logout()
    elif inp == "index":
        index()

if __name__ == '__main__':
    run()

# 运行启动函数 run()
# 输入你想要访问的页面路径 例如:login

这样就可以实现一个简单的WEB路由功能,根据不同的url,执行不同的视图函数,从而获取到不同的页面。
但是现在有一个最现实的问题,就是我们的视图函数,我们的页面绝对不止这么一点,可能会有成百上前个,那我们每一个都要这么写是不是得累死啊。怎么办,这个时候就需要用到了我们今天讲到的反射了。

2、反射(简单版)

首先我们的视图函数不用动,我们仔细观察,用户他们输入的url路径是不是跟我们将要调用的视图函数名基本是一样的,那我们想一想到底能不能用这个字符串直接调用函数就好了。
那这就要用到我们Python内置的方法了:getattr

import view

def run():
    inp = input("请输入你想要访问的页面:").strip()

    # 简单版:
    func = getattr(view,inp)
    func()

if __name__ == '__main__':
    run()

首先我们一起来看一看getattr的使用方式:接受两个参数,前面一个参数接受一个对象,后面接收一个“字符串”!!!

我们使用input输入得到的肯定是一个字符串,然后getattr方法通过传入的参数,去前面一个对象里面去找一个叫inp的成员。这个过程就相当于将一个字符串变成一个函数名的过程。然后把获得的结果赋值给func这个变量,实际func这个名字就指向了view.py里面的某个视图函数。最后通过调用func函数,实现对view.py里面函数的调用。这整个流程就是一个动态访问的过程,都不写死,全部根据用户输入的内容变化。

这个就是Python的反射,它的核心本质其实就是利用字符串的形式去对象或是模块当中操作相应的成员。

那好接下来我们再看,这个程序还是有一些小瑕疵的,那就是当用户输入的是一个非法路径的时候,由于在视图模块中没有同名的函数,就会出bug。

那要怎么办呢,在Python中其实还有一个hasattr函数,可以用于判断视图模块中是否存在某个成员。

import view

def run():
    inp = input("请输入你想要访问的页面:").strip()
    # 改善版
    if hasattr(view,inp):
        func = getattr(view,inp)
        func()
    else:
        print("404")

if __name__ == '__main__':
    run()

通过hasattr的判断,我们就可以防止非法输入了,并且可以将所有的非法输入统一定位到错误页面。

其实反射还有两个比较重要的方法setattr,delattr.

import view

def home():
    print("网站首页")

def run():
    inp = input("请输入你想要访问的页面:").strip()

    # 改善版
    # setattr(view,inp,home)
    # delattr(view,inp)
    if hasattr(view,inp):
        func = getattr(view,inp)
        func()
    else:
        print("404")

if __name__ == '__main__':
    run()

posted @ 2019-07-25 17:52  Sean_Yang  阅读(150)  评论(0)    收藏  举报