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

Python class 里如何使用 self 的装饰器

  •  
  •   just1 · 2017-06-17 23:02:35 +08:00 · 6625 次点击
    这是一个创建于 2721 天前的主题,其中的信息可能已经有所发展或是发生改变。

    原本想实现这样的功能

    class a:
      logs=[]
      
      @self.log()
      def b():
        print('1')
        
      def log(self,text=''):
        def decorator(func):
          @functools.wraps(func)
          def wrapper(s, *args, **kw):
            self.logs.append(func,args,kw)
            return func(*args, **kw)
          return wrapper
    
        return decorator
      
      def redo(self):
        for _ in self.logs:
          _[0](*_[1],**_[2])
        
    

    但这是错误的,@self.log()会报错 NameError: name 'self' is not defined 也想过把 log 拉出来,不放在 class a 里,有 2 个思路: 1.log 加一个 object 的参数,每次把这个 class 传进去 2.log()用 class 包裹起来,先初始化把 class a 传进去,后来调用就不用加 object 的参数了。

    但是遇到问题 思路 1:@log(self)也是会报错 NameError: name 'self' is not defined 思路 2:没办法所有操作在 class a 内完成,没办法做成包调用

    求助 QAQ

    第 1 条附言  ·  2017-06-18 00:09:14 +08:00
    #7,#14 的回复完美解决🌝我怎么没想到
    19 条回复
    just1
        1
    just1  
    OP
       2017-06-17 23:13:09 +08:00
    = =在线等!!
    ipconfiger
        2
    ipconfiger  
       2017-06-17 23:31:14 +08:00   ❤️ 1
    头上无数黑线飘过
    1iuh
        3
    1iuh  
       2017-06-17 23:35:23 +08:00   ❤️ 1
    为什么要这样写装饰器?
    just1
        4
    just1  
    OP
       2017-06-17 23:39:30 +08:00 via Android
    @ipconfiger
    @1iuh TAT 能说说?
    XYxe
        5
    XYxe  
       2017-06-17 23:40:22 +08:00 via Android   ❤️ 1
    log 定义成静态方法或者类方法,然后 @ a.log
    1iuh
        6
    1iuh  
       2017-06-17 23:41:27 +08:00   ❤️ 1
    @just1 #4 你为什么要把装饰器放类里面呀?放类外面不就完了。你调用装饰器的时候用 self 肯定不对啊。
    phithon
        7
    phithon  
       2017-06-17 23:42:44 +08:00   ❤️ 1
    这样?
    ![image]( )
    1iuh
        8
    1iuh  
       2017-06-17 23:43:24 +08:00   ❤️ 1
    @just1 #4 你如果想取对象里面的变量,也不是这样写的。这个各种教程里面有说,我就不说了。
    just1
        9
    just1  
    OP
       2017-06-17 23:44:21 +08:00 via Android
    @1iuh 因为我需要把数据放进 class a 里面去啊 QAQ
    @XYxe 变成静态之后得把 a 对象传进去,跟我思路 1 一个问题。。
    just1
        10
    just1  
    OP
       2017-06-17 23:46:37 +08:00 via Android
    @phithon 😃对的就是这个效果😭居然没想到,谢谢!
    SP00F
        11
    SP00F  
       2017-06-17 23:50:47 +08:00
    ```
    import functools

    def log():
    def decorator(func):
    @functools.wraps(func)
    def wrapper(self, *args, **kwargs):
    self.logs.append([func, args, kwargs])
    return func(self, *args, **kwargs)
    return wrapper
    return decorator

    class a:
    logs = []

    @log()
    def b(self, log):
    print(1)


    c = a()
    c.b("ccc")
    print(c.logs)
    ```


    不知道是不是你需要的结果。。`self.logs.append(func,args,kw)` 这里也是不对的,列表在进行 append 操作的时候只能添加一个。。
    SP00F
        12
    SP00F  
       2017-06-17 23:51:24 +08:00
    @SP00F

    完。。。全错了
    tomwei7
        13
    tomwei7  
       2017-06-17 23:51:40 +08:00
    首先 python 装饰器是编译时执行的,而且 self 代表当前类的实例在调用类方法的时候作为第一个参数,self 只是一个约定成俗的写法
    SP00F
        14
    SP00F  
       2017-06-17 23:55:54 +08:00
    billion
        15
    billion  
       2017-06-18 00:02:45 +08:00
    XYxe
        16
    XYxe  
       2017-06-18 00:03:57 +08:00 via Android
    @just1 self 是在创建对象实例之后调用函数的时候才绑定的,所以在外面是不能用 self 的。改成静态函数,然后把 logs 属性按照类属性来用 a.logs.append 就可以。
    just1
        17
    just1  
    OP
       2017-06-18 00:07:07 +08:00 via Android
    @SP00F 哈哈跟#7 一样,谢谢回复
    @XYxe 对,我知道。所以我没这样用。。。
    just1
        18
    just1  
    OP
       2017-06-18 00:08:39 +08:00 via Android
    @tomwei7 懂的
    @billion 😂这个问题的点不在这里,我的代码里已经解决了这个问题
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3665 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 10:27 · PVG 18:27 · LAX 02:27 · JFK 05:27
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.