自己动手撸Python框架:4. 路径映射-1

只考虑简单的路径映射,会涉及到一些简单的正则表达式。web.py里映射用的是列表,每个映射两个元素,为了写代码简便,直接用字典好了。在开始内容之前,我们先做些准备工作。

globals的花招

给你一个名字,如何查看有没有同名的类然后再创建一个实例?

import inspect

class TestA:
    def info(self):
        print('TestA')
    
def create(cls_name):
    g = globals()
    if cls_name in g:
        if inspect.isclass(g[cls_name]):
            return g[cls_name]()
    return None
    
ta = create('TestA')
tb = create('TestB')
ta.info()
print(tb)

在Python里你每定义一个类,添加一个变量,就会在全局增加一个名字映射,方便执行的时候查找。用globals()可以返回当前代码里包含的所有名字及对应的对象。所以g['TestA']()和TestA()是等价的。而TestB因为全局没有这个类所以返回None。inspect.isclass是判断某个变量是不是类。

URL解析

URL的标准格式如下,Python的urllib库提供了urlparse函数帮助我们快速解析URL。

from urllib.parse import urlparse

url = 'http://www.xyz.com/abc/def;params?a=1&b=2&c=zzz#fragment'
p = urlparse(url)
print('scheme: ' + p.scheme)
print('netloc: ' + p.netloc)
print('path: ' + p.path)
print('params: ' + p.params)
print('query: ' + p.query)
print('fragment: ' + p.fragment)

 执行后,可以看到各部分信息如下:

scheme: http
netloc: www.xyz.com
path: /abc/def
params: params
query: a=1&b=2&c=zzz
fragment: fragment

正则表达式匹配

在mapping里我们定义了路径匹配的规则,具体实现是使用正则表达式匹配。web.py在设计的时候考虑到效率,针对正则表达式的匹配进行了缓存处理。具体实现可以看源代码utils.py里Memoize类的实现。我们在这里简化一下代码,假设mapping为('^/index/name=(.*)&age=(.*)$', 'index'),现在输入的路径是/index/name=ZV&age=18。我们可以通过以下代码完成路径匹配并获得参数。

import re

class proxy:
    def __init__(self):
        self.match = None
        
    def __call__(self, match):
        self.match = match
        
def match(pattern, cls, value):
    p = proxy()
    compiled = re.compile(pattern)
    compiled.sub(p.__call__, value)
    cls, args = compiled.sub(cls, value), p.match
    return cls, args

if __name__ == '__main__':
    pattern = '/index/name/(.*)/age/(.*)'
    cls = 'index'
    value = '/index/name/ZV/age/18'
    cls, args = match(pattern, cls, value)
    print('Class:' + cls)
    if args:
        print('Args: ' + str([x for x in args.groups()]))

程序执行结果:

Class:index
Args: ['ZV', '18']

在了解了这些预备知识后,在下一章我们就会为框架添加URL映射功能。

猜你喜欢

转载自blog.csdn.net/panda_lin/article/details/121693377
今日推荐