我正在尝试使用bottle.py来构建一些网页。似乎使用瓶子的一个主要部分是学习使用装饰器,但我已经阅读了python docs解释装饰器是什么,但我仍然不确定我理解它们。
文档说:
" Python装饰器是对Python语法的一种特定更改,它允许我们更方便地更改函数和方法(以及未来版本中可能的类)。"
听起来你正在调用一个带有一些变化的函数,但我不确定你为什么会这样做或如何阅读装饰器。
看一些瓶子代码:
if __name__ == '__main__':
PROJECT_ROOT = os.path.abspath(os.path.dirname(__file__))
STATIC_ROOT = os.path.join(PROJECT_ROOT, 'static').replace('\\', '/')
HOST = os.environ.get('SERVER_HOST', 'localhost')
try:
PORT = int(os.environ.get('SERVER_PORT', '5555'))
except ValueError:
PORT = 5555
@bottle.route('/static/<filepath:path>')
def server_static(filepath):
"""Handler for static files, used with the development server.
When running under a production server such as IIS or Apache,
the server should be configured to serve the static files."""
return bottle.static_file(filepath, root=STATIC_ROOT)
# Starts a local test server.
bottle.run(server='wsgiref', host=HOST, port=PORT)
这一行做什么@bottle.route('/static/<filepath:path>')
?
如果它是一个花哨的函数调用那么为什么这样做而不是只调用函数?
感谢您的帮助! :d
答案 0 :(得分:7)
查看此代码:
def my_decorator(func):
return lambda: print("goodbye")
def greet():
print('hello')
result = my_decorator(greet)
result()
--output:--
goodbye
以下是完成同样事情的捷径:
def my_decorator(func):
return lambda: print("goodbye")
@my_decorator
def greet():
print('hello')
greet()
--output:--
goodbye
@my_decorator
语法使用它下面的函数greet
,并进行此调用:
greet = my_decorator(greet)
必须定义my_decorator()
函数,以便:
它需要一个函数作为参数。
返回一个函数。
Python装饰器是Python语法的特定更改 允许我们更方便地改变功能和方法(和 可能是未来版本中的类。)
好吧,那么让我们说你想添加到greet()函数所做的事情:
def my_decorator(func): # func = greet
def add_to_greet():
func() #<*********This is greet()
print('world') #<***This is additional stuff.
return add_to_greet
@my_decorator
def greet():
print('hello')
greet()
--output:--
hello
world
这一行做什么
@bottle.route('/static/<filepath:path>')
好的,你准备好了吗?如果@some_name
语法指定了参数,例如:
@wrapper('world')
def do_stuff():
首先 python将执行以下调用:
@wrapper('world')
def do_stuff():
...
#****HERE:
decorator = wrapper('world') #decorator is a newly created variable
wrapper()
函数必须定义为:
其次 ,python将执行调用:
@wrapper('world')
def do_stuff():
...
decorator = wrapper('world')
#*****HERE:
do_stuff = decorator(do_stuff)
呼!这是一个例子:
def wrapper(extra_greeting):
def my_decorator(func):
def add_to_greet():
func()
print(extra_greeting)
return add_to_greet
return my_decorator
@wrapper('world')
def greet():
print('hello')
greet()
--output:--
hello
world
现在,让我们分析一下这个装饰者:
@bottle.route('/static/<filepath:path>')
def server_static(filepath):
bottle -- a module
route -- a function(or other callable) defined in the bottle module
'/static/<filepath:path>' -- a route
所以瓶子模块可能如下所示:
#bottle.py
def route(your_route): #your_route <= '/static/<filepath:path>'
def my_decorator(func): #The decorator syntax will cause python to call this function with server_static as the argument
def do_stuff(filepath):
func(filepath) #Call the server_static() function with the part of the url that matched filepath
return do_stuff #This function will be called when your code calls server_static(...)
return my_decorator
如果它是一个花哨的函数调用那么为什么这样做而不仅仅是 调用函数?
高级的东西。
评论: 也许您忘了解释路由装饰器的具体用途了什么?
@route('/hello') def hello(): return "Hello World!"
route()装饰器将一段代码绑定到URL路径。在这 case,我们将/ hello路径链接到hello()函数。这就是所谓的 路线(因此是装饰者名称)并且是最重要的概念 这个框架。您可以根据需要定义任意数量的路径。每当 浏览器请求一个URL,调用相关的函数和 返回值被发送回浏览器。就这么简单。
http://bottlepy.org/docs/dev/tutorial.html
路径可以包含通配符:
最简单的通配符形式包含一个角度包含的名称 括号(例如
<name>
)....每个通配符匹配一个或多个 字符,但 在第一个斜线停止 (/)。 规则/<action>/<item>
匹配如下:
Path Result
/save/123 {'action': 'save', 'item': '123'}
/save/123/ No Match
/save/ No Match
//123 No Match
过滤器用于定义更具体的通配符和/或变换 在将URL传递给回调之前匹配的部分。一个 过滤的通配符声明为
<name:filter>
实施以下标准过滤器:
:路径以非贪婪方式匹配包括斜杠字符在内的所有字符, 可用于匹配多个路径 片段 强>
答案 1 :(得分:3)
装饰器只是一个函数包装器,它需要一些可计算的并用更多的可计算机包围它,从技术上讲,装饰器是一个函数,它返回一个函数(或一个对象,实际上有装饰器类)。
让我们假设您想制作一个记录器装饰器,这个记录器装饰器将执行某些操作并记录执行它的人:
def loggger(name):
def wrapper(f):
def retF(*args, **kwargs):
print name, "is executing"
f(*args, **kwargs)
return retF
return wrapper
所以,在调用我们想要的函数之前,我们的装饰器会打印“Daniel正在执行”,例如
@logger("Daniel")
def add2Nums(a,b):
return a+b
>>> add2Nums(1,2)
>>> Daniel is executing
>>> 3
在
中,瓶子的工作方式相同@bottle.route('/static/<filepath:path>')
它只是包含你的server_static
调用,所以只要有人调用你的函数路由就会被调用。