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
cc7756789
V2EX  ›  Python

python 类中装饰器

  •  
  •   cc7756789 · 2015-05-23 21:53:58 +08:00 · 2906 次点击
    这是一个创建于 3476 天前的主题,其中的信息可能已经有所发展或是发生改变。
    a = Question()
    a.all_answer() 正常,结果打印到屏幕
    但是我想 a.all_answer(write=True) 执行 if write == True:把结果写入文件

    但 a.all_answer(True)报错:

    TypeError: internal() takes exactly 1 argument (2 given)

    a.all_answer(erite=True)也报错:
    TypeError: internal() got multiple values for keyword argument 'write'

    把装饰函数放到类中也一样。


    代码高亮: https://git.oschina.net/hgzhg/test/blob/master/decorator.py

    def write_answer(pre=''):
    def wrapper(F):
    def internal(write):
    if write == True:
    result = F(write)
    with open('/path/a.txt', 'w') as f:
    f.write(result)
    else:
    print pre
    F(write)
    return internal
    return wrapper


    class Question(object):
    @write_answer('logging...')
    def all_answer(self, write=False):
    #下面代码部分直接忽略吧

    answer_number = self.answer_number()
    reg_img = r'http://pic3.zhimg.com/\w+\.jpg'
    if answer_number == 0:
    print "This question is no answers"
    else:
    re_br = re.compile(r'<br/?>')
    re_allmark = re.compile(r'<[^>]+>',re.S)
    all_answer_list = self.soup.find_all( 'div', 'zm-item-answer ')
    for each in all_answer_list:
    print each.h3.get_text()
    content = str(each.find('div', ' zm-editable-content clearfix'))
    br2n = re.sub(re_br, '\n', content)
    for s in br2n.split('\n'):
    print re.sub(re_allmark, '', s)
    sinux
        1
    sinux  
       2015-05-23 22:01:08 +08:00
    为什么你的装饰器的参数不是一个function?
    ibigbug
        2
    ibigbug  
       2015-05-24 00:04:51 +08:00
    `def internal(write)` ---> `def internal(*args, **kwargs)`

    `if write` ---> `if kwargs.get('write')`

    `F(write)` ---> `F(*args, **kwargs)`

    `a.all_answer(True) ---> `a.all_answer(write=True)`
    monkeylyf
        3
    monkeylyf  
       2015-05-24 09:36:20 +08:00
    a.all_answer(True)是在调用bounded method相当于Question.all_answer(a, True) 这就是为什么你看到了2 given 的TypeError

    而你的def internal只接受一个arg(write), 你可以改成def internal(obj, write) 然后下面所有调用F的时候都写成F(obj, write) 缺点是这个decorator 只能装饰类方法 如果用在普通的function上又会有typeerror args mismatch之类的问题
    也可以参考楼上的用*/** magic来 这里的缺点是你如果用的default value那么你就要去kwargs里使用dict.get操作 同时要hard code你的变量名

    总的来说不建议在类里面用装饰器 能flatten就flatten
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4173 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 05:22 · PVG 13:22 · LAX 21:22 · JFK 00:22
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.