V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
Newyorkcity
V2EX  ›  Python

关于修饰器,请问教程中的代码为什么不能进一步简化?

  •  
  •   Newyorkcity · 2016-09-01 19:47:24 +08:00 · 3034 次点击
    这是一个创建于 3000 天前的主题,其中的信息可能已经有所发展或是发生改变。
    因为不会用社区的语法来缩进,所以只能放图,望谅解
    这个是自学的教程上提供的代码:


    我觉得 warpper 这一层的存在没有必要,可以简化掉
    因为加了装饰器之后 now() = log(text)(now)()对吧
    那 log(text)(now)()在 Log 函数执行完后变成 decorator(now)()
    此时直接让 decorator(now)执行完成变为 now()不就可以了么?
    所以直接让 decorator 的 return 为 func 不就结了?

    尝试了一下,是可以输出我想要的东西的...这样我就更加不明白了

    请问我的想法哪里错了呢?谢谢.
    25 条回复    2016-09-04 18:05:36 +08:00
    sherlocktheplant
        1
    sherlocktheplant  
       2016-09-01 20:05:29 +08:00
    区别在于你的写法访问不到参数
    sherlocktheplant
        2
    sherlocktheplant  
       2016-09-01 20:08:36 +08:00   ❤️ 2
    我的意思是你的装饰器里访问不到参数 比如 如果要求装饰器可以拦截或者篡改某些参数 你的写法做不到
    kkzxak47
        3
    kkzxak47  
       2016-09-01 20:13:29 +08:00 via Android
    无参数装饰器可以像你那样写
    Newyorkcity
        4
    Newyorkcity  
    OP
       2016-09-01 20:14:27 +08:00
    @sherlocktheplant 请问你说的参数是给 @log()用的还是给被修饰的函数用的?

    能否以'要求装饰器可以拦截或者篡改某些参数'出一道题?
    谢谢
    Newyorkcity
        5
    Newyorkcity  
    OP
       2016-09-01 20:15:36 +08:00
    @kkzxak47
    @log('execute')
    这个形式不已经是一个传入了参数的修饰器么?
    谢谢
    fds
        6
    fds  
       2016-09-01 20:19:11 +08:00
    原来的 wrapper 可以记录或者修改 args kw
    sherlocktheplant
        7
    sherlocktheplant  
       2016-09-01 20:24:08 +08:00
    @Newyorkcity
    比如说 要求将所有传入被修饰函数的字符串全部变成大写
    sherlocktheplant
        8
    sherlocktheplant  
       2016-09-01 20:26:38 +08:00   ❤️ 1
    第一层是用来接受修饰器本身的参数 第二层是接受被修饰的函数的引用 第三层是接受被修饰函数被调用时接受的参数
    tmackan
        9
    tmackan  
       2016-09-01 20:28:50 +08:00
    junnplus
        10
    junnplus  
       2016-09-01 21:54:26 +08:00
    return func 之后,你的 f 函数的 s 参数并不会被返回的 func 接受
    KDr2
        11
    KDr2  
       2016-09-01 22:03:59 +08:00   ❤️ 1
    楼上的诸位,难道不是楼主的第二种写法,只在代码加载时做了 log ,每次 call 的时候并不 log ?
    firemiles
        12
    firemiles  
       2016-09-01 22:39:19 +08:00
    楼主你的 log 只是在定义时起作用输出一次,调用的时候跟没装 log 一样
    sherlocktheplant
        13
    sherlocktheplant  
       2016-09-01 22:48:13 +08:00
    @KDr2
    @firemiles

    抱歉 很久没写 python 半桶水了
    Newyorkcity
        14
    Newyorkcity  
    OP
       2016-09-01 22:54:42 +08:00
    @KDr2
    @firemiles
    额?为什么这么说?
    我最后一行的那个 f(5)是调用吗?结果在打印 5 之前得到了 call f()啊?
    谢谢..
    firemiles
        15
    firemiles  
       2016-09-01 23:00:12 +08:00   ❤️ 1
    @Newyorkcity 你多屌用几次 f(5)试试,应该只能输出一次 log
    firemiles
        16
    firemiles  
       2016-09-01 23:00:29 +08:00
    @Newyorkcity 你多调用几次 f(5)试试,应该只能输出一次 log
    iptux
        17
    iptux  
       2016-09-01 23:04:37 +08:00 via Android
    /t/208738 历史总是惊人般的相似
    Newyorkcity
        18
    Newyorkcity  
    OP
       2016-09-02 09:02:14 +08:00
    @firemiles
    是的,尝试了一下发现只有在第一次调用函数才会出现 call f() 然后教程的代码每次都会出现 call f()
    可是请问这是为什么呢?
    加上了装饰器的话不就令 f = log(text)(f)了么
    那每次执行 f()都等于在自行 log(text)(f)()吧...为什么会出现之后的调用无效的问题呢
    firemiles
        19
    firemiles  
       2016-09-02 09:26:37 +08:00   ❤️ 1
    @Newyorkcity 你装饰器返回的是原函数 `f = f`,不是 wrapper ,所以你的装饰器没有效果,例子多一层 'f = wrapper';
    Newyorkcity
        20
    Newyorkcity  
    OP
       2016-09-02 09:33:28 +08:00
    @firemiles 大致懂了,谢谢~!
    kamen
        21
    kamen  
       2016-09-02 11:46:22 +08:00 via Android
    有一本 python 的书,对这些高级的用法讲得很详细,讲得也很浅明易懂,我当初看文档也是一脸懵逼,看了这本书就豁然开朗了,我记得 v2 有人翻译了这本书,放在了 gitbook
    longchisihai
        22
    longchisihai  
       2016-09-02 12:37:17 +08:00
    @kamen 啥书呀?能帮忙找找不?
    kamen
        23
    kamen  
       2016-09-02 14:40:11 +08:00
    你呀,还需要提高自身的姿势水平,我说这么多就是因为我当时不方便找,需要你自己用我的关键字去找。
    Google 搜索 gitbook,点击 explore ,搜索 python ,以 most stars 排序,第一个是一看就是讲基础的,第二个一看就是讲高级用法的,然后就不用我说了吧。
    Allianzcortex
        24
    Allianzcortex  
       2016-09-04 18:04:39 +08:00
    好问题啊。 LZ 难道没有发现需要两层装饰器的都是以 fn 为参数,而需要三层装饰器的都是在第二个返回函数里以 fn 作为参数? decorator 和 decorator with arguments 是不同的思路,看这个: http://stackoverflow.com/questions/5929107/python-decorators-with-parameters
    Allianzcortex
        25
    Allianzcortex  
       2016-09-04 18:05:36 +08:00
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1023 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 20:35 · PVG 04:35 · LAX 12:35 · JFK 15:35
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.