python魔法函数和装饰器_python: 从函数了解到装饰器

让我们扫一眼上次我们写的简单NotFlask类。

class NotFlask():

def __init__(self):

self.routes = {}

def route(self, route_str):

def decorator(f):

self.routes[route_str] = f

return f

return decorator

def serve(self, path):

view_function = self.routes.get(path)

if view_function:

return view_function()

else:

raise ValueError('Route "{}"" has not been registered'.format(path))

app = NotFlask()

@app.route("/")

def hello():

return "Hello World!"

现在我们有一个新的改进方法用来匹配输入的路径,我们打算移除我们上一个版本实现时用到的原生字典。

让我们从改造我们的函数着手,以便于添加路径,这样我们就可以用(pattern, view_function)对列表代替字典保存我们的路径。

这意味着当一个程序员使用@app.route()装饰一个函数,我们将要尝试将他们的路径编译变成一个正则表达式,然后存储它,属于一个在我们新的路径列表里的装饰函数。

让我们看看实现代码:

class NotFlask():

def __init__(self):

self.routes = []

#Here's our build_route_pattern we made earlier

@staticmethod

def build_route_pattern(route):

route_regex = re.sub(r'()', r'(?P\1.+)', route)

return re.compile("^{}$".format(route_regex))

def route(self, route_str):

def decorator(f):

#Instead of inserting into a dictionary,

#We'll append the tuple to our route list

route_pattern = self.build_route_pattern(route_str)

self.routes.append((route_pattern, f))

return f

return decorator

我们也打算需要一个get_route_match方法,给它一个路径实例,将会尝试并找到一个匹配的view_function,或者返回None如果一个也找不到的话。

然而,如果找了到匹配的话,除了view_function之外,我们还需要返回一个东西,那就是我们包含之前捕获匹配组的字典,我们需要它来为视图函数传递正确的参数。

好了我们的get_route_match大概就长这样:

def get_route_match(path):

for route_pattern, view_function in self.routes:

m = route_pattern.match(path)

if m:

return m.groupdict(), view_function

return None

现在我们快要完成了,最后一步将是找出调用view_function的方法,使用来自正则表达式匹配组字典的正确参数。

调用一个函数的若干种方法

让我们回顾一下不同的方法调用一个python的函数。

比如像这样:

def hello_user(username):

return "Hello {}!".format(username)

最简单的(也许正是你所熟知的)办法是使用正则参数,在这里参数的顺序匹配我们定义的那些函数的顺序。

>>> hello_user("ains")

Hello ains!

另一种方法调用一个函数是使用关键词参数。关键词参数可以通过任何顺序指定,适合有许多可选参数的函数。

>>> hello_user(username="ains")

Hello ains!

在Python中最后一种调用一个函数的方法是使用关键词参数字典,字典中的关键词对应参数名称。我们告诉Python解包一个字典,并通过使用两个星号“**”来把它当作函数的关键词参数。 下面的代码段与上面的代码段完全一样,现在我们使用字典参数,我们可以在运行时动态创建它。

>>> kwargs = {"username": "ains"}

>>> hello_user(**kwargs)

Hello ains!

好了,还记得上面的groupdict()方法?就是那个同样的在正则表达式完成匹配后返回{“username”: “ains”}的家伙?那么现在我们了解了kwargs,我们能很容易向我们的view_function传递字典匹配,完成NotFlask!

那么让我们把这些都塞进我们最终的类中。

class NotFlask():

def __init__(self):

self.routes = []

@staticmethod

def build_route_pattern(route):

route_regex = re.sub(r'()', r'(?P\1.+)', route)

return re.compile("^{}$".format(route_regex))

def route(self, route_str):

def decorator(f):

route_pattern = self.build_route_pattern(route_str)

self.routes.append((route_pattern, f))

return f

return decorator

def get_route_match(self, path):

for route_pattern, view_function in self.routes:

m = route_pattern.match(path)

if m:

return m.groupdict(), view_function

return None

def serve(self, path):

route_match = self.get_route_match(path)

if route_match:

kwargs, view_function = route_match

return view_function(**kwargs)

else:

raise ValueError('Route "{}"" has not been registered'.format(path))

接下来,就是见证奇迹的时刻,请看下面代码段:

app = NotFlask()

@app.route("/hello/")

def hello_user(username):

return "Hello {}!".format(username)

print app.serve("/hello/ains")

我们将得到输出:

Hello ains!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值