如何使用装饰器(bottle.py)

时间:2015-11-18 10:12:56

标签: python python-2.7 bottle

我正在尝试使用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

2 个答案:

答案 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()函数,以便:

  1. 它需要一个函数作为参数。

  2. 返回一个函数。

  3.   

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

    1. 采取任何旧的论点,例如'世界'
    2. 返回一个函数:
      1. 以函数为参数。
      2. 返回一个函数。
    3. 其次 ,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>

        

      实施以下标准过滤器:

           

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

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

答案 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调用,所以只要有人调用你的函数路由就会被调用。