欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

Python修饰器的函数式编程

shiping1 的头像

  1. kamushin
    2014年3月20日10:14 | #1

    沙发. 还有个很常用的功能 @web.authenticated

  2. ljdawn
    2014年3月20日10:15 | #2

    好文。。。

  3. 2014年3月20日10:29 | #3

    Python 3.4里的asyncio更好玩。coroutine使用generator而不是thread。

  4. 子江
    2014年3月20日10:32 | #4

    请问get_line_number 在哪里定义的呢?

  5. astrum
    2014年3月20日10:35 | #6

    —– 要修正这一问,我们还得用Python的反映来解决,下面是相关的代码:

    反映应该是反射

    文章很棒!

  6. Tydus
    2014年3月20日11:21 | #8

    kamushin :
    沙发. 还有个很常用的功能 @web.authenticated

    Tornado党握爪

  7. 地狱星星
    2014年3月20日12:46 | #9

    好文,强烈推荐

  8. Ming
    2014年3月20日13:04 | #10

    可以用来实现AOP

  9. e3rp4y
    2014年3月20日13:33 | #11

    所以,Python的functool包中提供了一个叫wrap的decorator来消除这样的副作用。下面是我们新版本的hello.py。
    wrap -> wraps

  10. 2014年3月20日14:58 | #12

    每篇都是精品,钦佩之余,更多的是激励自己加倍努力!

  11. frank
    2014年3月20日15:14 | #13

    篇篇都是硬货!
    不过“注册回调函数”这个例子有些问题,“你调用main_page_func()或是next_page_func()就调到了黑洞了,啥也不会发生。你只有通过app.call_method才行。”,这句话是不对的,@app.register(‘/’) 注册了函数后直接把原函数返回了,所以main_page_func这个函数没有任何变化,可以跟原来一样调用。

  12. 2014年3月20日15:28 | #15

    典型的反框架模式,或者叫非侵入式框架,摒弃了强制性换取灵活性。可以人肉AOP。缺点是复用部分不够彻底,还有感觉这种功能以continuation实现的方式不如放到meta programming层次来的通用。

  13. expbored
    2014年3月20日16:56 | #16

    解释下“class式的 Decorator”节中aFunction()多次调用仅输出一次“inside myDecorator.__init__()”背后的动作是不是更有助于理解修饰器呢?

  14. 2014年3月20日20:23 | #17

    Tydus :

    kamushin :
    沙发. 还有个很常用的功能 @web.authenticated

    Tornado党握爪

    还有 @gen.coroutine 呢喵~
    话说那个 @memo 在 Python 3.2+ 可以用 @functools.lru_cache 取代了 :-)

  15. 飞罗
    2014年3月20日20:38 | #18

    在带参数及多个Decrorator模块下:
    wrapper函数中的 fn(*args, **kwds) 改成fn() 会不会更好点,因为fn调用没有参数

  16. 2014年3月20日21:06 | #19

    @Tydus 
    tornado党 +1 ,@web.authenticated 好用

  17. 2014年3月20日22:47 | #20

    正在学习python,收藏了。

  18. 2014年3月20日22:55 | #21

    我也是这么理解的@frank

  19. autumnm1981
    2014年3月21日09:04 | #22

    C#中没有Annotation,对应的技术应该是Attribute。

  20. 2014年3月22日10:46 | #23

    感谢楼主分享,学习了

  21. coneagoe
    2014年3月23日15:37 | #24

    我以前一直深信好的架构能够减少维护成本,不过后来我开始有疑问了。其实不管是开发的人还是维护的人,学习成本是一样的。如果维护的人不能理解设计者的本意,再好的代码也会变成bull shit。所以学习的成本是一样的。

  22. blowyourheart
    2014年3月23日23:41 | #25

    @eleveni386 
    @login_required 也好用。

  23. kelvinhust
    2014年3月25日13:54 | #26

    = =我昨天面试刚好给人问了什么是Python的Decorator,然后我就回答这其实就是Decorator Pattern的实现。。
    我看了stackoverflow的回答(http://stackoverflow.com/questions/8328824/whats-the-difference-between-python-decorators-and-decora...),上面说Python的Decorator是在定义的时候去修改行为,Decorator模式是在运行期修改行为,所以Python的就高阶一点。
    但我觉得从本质上来看,两者都是通过Decorator包装原有的,来修改行为,思想是一样的。。
    真心求教,期待回答,谢谢!

  24. zz
    2014年3月26日22:42 | #27

    好文章啊!
    不过有一点还不懂,就是使用类方式实现装饰器的时候怎么消除副作用啊,foo.__name__直接就没有了,用@wraps也不行???

  25. zz
    2014年3月26日23:31 | #28

    zz :
    好文章啊!
    不过有一点还不懂,就是使用类方式实现装饰器的时候怎么消除副作用啊,foo.__name__直接就没有了,用@wraps也不行???

    def __init__(self, fn):
    self.fn = fn
    self.__name__ = fn.__name__
    用这个倒是可以,请教楼主还有更好的方法么?

  26. zzzz
    2014年4月3日11:04 | #29

    return “Hello, {}”.format(name)
    “Hello, {0}”.format(name)

  27. Majoy7
    2014年4月8日11:05 | #30

    这样挺酷的。不过有个疑问是,函数本身为何要关注自己如何被decorate,由调用者来决定不是更好,而且不同的调用者可能会有不同的decorate需求。

  28. 2014年4月13日17:53 | #31

    自习分析了一下,html.py的调用执行流程,发现这个带参数的多个decorator的执行流程和优先级顺序,让人有点费解

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    def makeHtmlTag(tag, *args, **kwds):
        print "Enter the makeHtmlTag ",tag,args,kwds
        def real_decorator(fn):
            print "Enter the real_dec"
            css_class = " class='{0}'".format(kwds["css_class"]) \
                                if "css_class" in kwds else ""
            print "\tcss_class:"+css_class
            print "\tfn.__name__:"+fn.__name__
            def wrapped(*args, **kwds):
                print "Enter the warapped",args,kwds
                print "\twarp_fn.__name__:"+fn.__name__
                print "\tcurrnt css_calss:"+css_class
                print "leave the warapped",args,kwds
                return  "" + fn(*args, **kwds) + ""
            print "leave the real_dec"
            return wrapped
        print "      ...........     "
        print "leave the makeHtmlTag ",tag,args,kwds
        return real_decorator
     
    @makeHtmlTag(tag="b", css_class="bold_css")
    @makeHtmlTag(tag="i", css_class="italic_css")
    def hello():
        return "hello world"
     
    print hello()

    ——————————————————————————————
    输出结果如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    Enter the makeHtmlTag  b () {'css_class': 'bold_css'}
          ...........    
    leave the makeHtmlTag  b () {'css_class': 'bold_css'}
    Enter the makeHtmlTag  i () {'css_class': 'italic_css'}
          ...........    
    leave the makeHtmlTag  i () {'css_class': 'italic_css'}
    Enter the real_dec
        css_class: class='italic_css'
        fn.__name__:hello
    leave the real_dec
    Enter the real_dec
        css_class: class='bold_css'
        fn.__name__:wrapped
    leave the real_dec
    Enter the warapped () {}
        warp_fn.__name__:wrapped
        currnt css_calss: class='bold_css'
    leave the warapped () {}
    Enter the warapped () {}
        warp_fn.__name__:hello
        currnt css_calss: class='italic_css'
    leave the warapped () {}
    <b><i>hello world</i></b>
  29. 2014年4月25日17:35 | #32

    @Tydus

    `@gen.coroutine`
    更常用吧,否则tornado用着没意思了。。。

  30. 2014年4月25日17:40 | #33

    addbook :
    @Tydus
    @gen.coroutine
    更常用吧,否则tornado用着没意思了。。。
    博主可以使用markdown编辑器,可能更方便。。

  31. winlin
    2014年5月13日19:51 | #34

    飞罗 :
    在带参数及多个Decrorator模块下:
    wrapper函数中的 fn(*args, **kwds) 改成fn() 会不会更好点,因为fn调用没有参数

    同问,能不能同时适用于fn() 与 fn(*args, **kwargs)

  32. virusdefender
    2014年7月2日09:28 | #35

    赞!!篇篇都是干货!

  33. 轨迹
    2014年7月8日12:27 | #36

    很棒

  34. 2014年8月14日00:49 | #37

    解决了困扰我很长时间的疑问,目前为止看过关于decorator解释得最清楚的文章。

  35. gaoxiao
    2014年9月1日12:08 | #38
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    def makeHtmlTag(tag, *args, **kwds):
        def real_decorator(fn):
            css_class = " class='{0}'".format(kwds["css_class"]) \
                                         if "css_class" in kwds else ""
            def wrapped(*args, **kwds):
                return "" + fn(*args, **kwds) + ""
            return wrapped
        return real_decorator
     
    @makeHtmlTag(tag="b", css_class="bold_css")
    @makeHtmlTag(tag="i", css_class="italic_css")
    def hello():
        return "hello world"
     
    print hello()

    上面这段代码,wrapped函数应该没必要传参吧?改成下面这样结果是一样的:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    def makeHtmlTag(tag, *args, **kwds):
        def real_decorator(fn):
            css_class = " class='{0}'".format(kwds["css_class"]) \
                                         if "css_class" in kwds else ""
            def wrapped():
                return "" + fn() + ""
            return wrapped
        return real_decorator
     
    @makeHtmlTag(tag="b", css_class="bold_css")
    @makeHtmlTag(tag="i", css_class="italic_css")
    def hello():
        return "hello world"
     
 
普通分类: