【问题标题】:How to use decorators (bottle.py)如何使用装饰器 (bottle.py)
【发布时间】:2017-05-13 09:30:47
【问题描述】:

我正在尝试使用 bottle.py 来构建一些网页。似乎使用瓶子的主要部分是学习使用装饰器,但我已经阅读了关于装饰器是什么的 python 文档解释,但我仍然不确定我是否理解它们。

文档说:

“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/&lt;filepath:path&gt;') 这一行有什么作用?

如果它是一个花哨的函数调用,那么为什么要这样做而不是仅仅调用函数呢?

感谢您的帮助! :D

【问题讨论】:

    标签: python python-2.7 bottle


    【解决方案1】:

    查看此代码:

    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() 函数必须这样定义:

    1. 它将函数作为参数。

    2. 返回一个函数。

    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/&lt;filepath:path&gt;')

    好的,你准备好了吗?如果@some_name 语法指定了一个参数,例如:

     @wrapper('world')
     def do_stuff():
    

    首先 python 将执行以下调用:

     @wrapper('world')
     def do_stuff():
          ...
    
     #****HERE:
     decorator = wrapper('world')  #decorator is a newly created variable
    

    wrapper() 函数必须定义为:

    1. 采用任何旧的论点,例如'世界'
    2. 返回一个函数:
      1. 将函数作为参数。
      2. 返回一个函数。

    其次,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 路径。在这个 在这种情况下,我们将 /hello 路径链接到 hello() 函数。这就是所谓的 一条路线(因此是装饰器名称),是最重要的概念 这个框架的。您可以根据需要定义任意数量的路线。每当 浏览器请求一个 URL,相关的函数被调用并且 返回值被发送回浏览器。就这么简单。

    http://bottlepy.org/docs/dev/tutorial.html

    路径可以包含通配符:

    通配符的最简单形式是用角括起来的名称 方括号(例如&lt;name&gt;)....每个通配符匹配一个或多个 字符,但在第一个斜杠处停止 (/)。 规则/&lt;action&gt;/&lt;item&gt; 匹配如下:

    Path        Result
    /save/123   {'action': 'save', 'item': '123'}
    /save/123/  No Match
    /save/      No Match
    //123       No Match
    

    过滤器用于定义更具体的通配符和/或转换 在将 URL 传递给回调之前匹配的部分。一个 过滤后的通配符声明为&lt;name:filter&gt;


    实现了以下标准过滤器:

    :path 以非贪婪的方式匹配包括斜线字符在内的所有字符,可用于匹配多个路径 段

    http://bottlepy.org/docs/dev/routing.html

    【讨论】:

    • 也许你忘了解释那个路由装饰器具体是做什么的?
    • 完美!这描述得非常好!谢谢:D
    【解决方案2】:

    装饰器只是一个函数包装器,它需要一些可计算并用更多可计算包围它,从技术上讲,装饰器是一个返回函数(或对象,实际上有装饰器类)的函数。

    比如说你想制作一个 logger 装饰器,这个 logger 装饰器会执行一些东西并记录谁在执行它:

    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 调用,因此每当调用路由您的函数的某些访问权限时。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-07-19
      • 1970-01-01
      • 1970-01-01
      • 2022-08-15
      • 2020-02-29
      • 2014-02-14
      • 1970-01-01
      • 2018-06-08
      相关资源
      最近更新 更多