关于修饰器,请问教程中的代码为什么不能进一步简化? - V2EX
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 3406 次点击
    这是一个创建于 3330 天前的主题,其中的信息可能已经有所发展或是发生改变。
    因为不会用社区的语法来缩进,所以只能放图,望谅解
    这个是自学的教程上提供的代码:


    我觉得 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     Solana     3088 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 25ms UTC 00:29 PVG 08:29 LAX 17:29 JFK 20:29
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86