如何使用装饰器 (bottle.py)
How to use decorators (bottle.py)
我正在尝试使用 bottle.py 构建一些网页。似乎使用 bottle 的主要部分是学习使用装饰器,但我已经阅读了 python 文档对装饰器的解释,但我仍然不确定我是否理解它们。
文档说:
"A Python decorator is a specific change to the Python syntax that allows us to more conveniently alter functions and methods (and possibly classes in a future version)."
听起来您正在调用一个函数并进行了一些更改,但我不确定您为什么要这样做或如何阅读装饰器。
查看一些瓶子代码:
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
装饰器只是一个函数包装器,它需要一些可计算值并用更多可计算值包围它,从技术上讲,装饰器是一个函数,returns一个函数(或一个对象,实际上有装饰器类).
比如说你想做一个记录器装饰器,这个记录器装饰器将执行一些东西并记录谁在执行它:
def loggger(name):
def wrapper(f):
def retF(*args, **kwargs):
print name, "is executing"
f(*args, **kwargs)
return retF
return wrapper
所以,我们的装饰器会在调用我们想要的函数之前打印 "Daniel is executing",例如
@logger("Daniel")
def add2Nums(a,b):
return a+b
>>> add2Nums(1,2)
>>> Daniel is executing
>>> 3
Bottle 的工作原理相同,在
@bottle.route('/static/<filepath:path>')
它只是包装您的 server_static
调用,因此每当调用路由您的函数的某些访问时。
查看此代码:
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()
函数,以便:
它接受一个函数作为参数。
Return一个函数。
A Python decorator is a specific change to the Python syntax that
allows us to more conveniently alter functions and methods (and
possibly classes in a future version).
好吧,假设你想 add 到 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
What does this line do @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()
函数必须定义为:
- 采用任何旧参数,例如'world'
- Return 一个函数:
- 将函数作为参数。
- Return是一个函数。
其次,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
If its a fancy function call then why do it this way rather than just
calling the function?
高级东西。
评论: 也许你忘了解释路由装饰器具体做了什么?
@route('/hello')
def hello():
return "Hello World!"
The route() decorator binds a piece of code to an URL path. In this
case, we link the /hello path to the hello() function. This is called
a route (hence the decorator name) and is the most important concept
of this framework. You can define as many routes as you want. Whenever
a browser requests a URL, the associated function is called and the
return value is sent back to the browser. It’s as simple as that.
http://bottlepy.org/docs/dev/tutorial.html
路径可以包含通配符:
The simplest form of a wildcard consists of a name enclosed in angle
brackets (e.g. <name>
)....Each wildcard matches one or more
characters, but stops at the first slash (/).
The rule /<action>/<item>
matches as follows:
Path Result
/save/123 {'action': 'save', 'item': '123'}
/save/123/ No Match
/save/ No Match
//123 No Match
Filters are used to define more specific wildcards, and/or transform
the matched part of the URL before it is passed to the callback. A
filtered wildcard is declared as <name:filter>
The following standard filters are implemented:
:path matches all characters including the slash character in a non-greedy way and may be used to match more than one path
segment.
我正在尝试使用 bottle.py 构建一些网页。似乎使用 bottle 的主要部分是学习使用装饰器,但我已经阅读了 python 文档对装饰器的解释,但我仍然不确定我是否理解它们。
文档说:
"A Python decorator is a specific change to the Python syntax that allows us to more conveniently alter functions and methods (and possibly classes in a future version)."
听起来您正在调用一个函数并进行了一些更改,但我不确定您为什么要这样做或如何阅读装饰器。
查看一些瓶子代码:
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
装饰器只是一个函数包装器,它需要一些可计算值并用更多可计算值包围它,从技术上讲,装饰器是一个函数,returns一个函数(或一个对象,实际上有装饰器类).
比如说你想做一个记录器装饰器,这个记录器装饰器将执行一些东西并记录谁在执行它:
def loggger(name):
def wrapper(f):
def retF(*args, **kwargs):
print name, "is executing"
f(*args, **kwargs)
return retF
return wrapper
所以,我们的装饰器会在调用我们想要的函数之前打印 "Daniel is executing",例如
@logger("Daniel")
def add2Nums(a,b):
return a+b
>>> add2Nums(1,2)
>>> Daniel is executing
>>> 3
Bottle 的工作原理相同,在
@bottle.route('/static/<filepath:path>')
它只是包装您的 server_static
调用,因此每当调用路由您的函数的某些访问时。
查看此代码:
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()
函数,以便:
它接受一个函数作为参数。
Return一个函数。
A Python decorator is a specific change to the Python syntax that allows us to more conveniently alter functions and methods (and possibly classes in a future version).
好吧,假设你想 add 到 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
What does this line do
@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()
函数必须定义为:
- 采用任何旧参数,例如'world'
- Return 一个函数:
- 将函数作为参数。
- Return是一个函数。
其次,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
If its a fancy function call then why do it this way rather than just calling the function?
高级东西。
评论: 也许你忘了解释路由装饰器具体做了什么?
@route('/hello') def hello(): return "Hello World!"
The route() decorator binds a piece of code to an URL path. In this case, we link the /hello path to the hello() function. This is called a route (hence the decorator name) and is the most important concept of this framework. You can define as many routes as you want. Whenever a browser requests a URL, the associated function is called and the return value is sent back to the browser. It’s as simple as that.
http://bottlepy.org/docs/dev/tutorial.html
路径可以包含通配符:
The simplest form of a wildcard consists of a name enclosed in angle brackets (e.g.
<name>
)....Each wildcard matches one or more characters, but stops at the first slash (/). The rule/<action>/<item>
matches as follows:
Path Result
/save/123 {'action': 'save', 'item': '123'}
/save/123/ No Match
/save/ No Match
//123 No Match
Filters are used to define more specific wildcards, and/or transform the matched part of the URL before it is passed to the callback. A filtered wildcard is declared as
<name:filter>
The following standard filters are implemented:
:path matches all characters including the slash character in a non-greedy way and may be used to match more than one path segment.