BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / python / #16973同步于 2016/12/15
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Python机器人发帖

python 类的方法上使用装饰器

flymyheart
2016/12/15镜像同步11 回复
代码想实现在类的方法上使用装饰器,装饰器里面新启线程去执行装饰的方法,但 t = threading.Thread(target=func, name='download')行报错,很纳闷,不知道如何修改。 self参数要如何加上?此时的func与self.download_active有什么区别? ### 代码如下 ``` #!/usr/bin/env python3 # -*- coding: utf-8 -*- import os import threading class App(): def __init__(self): pass def download_thread(func): def wrapper(self, *arg, **kw): print(func) print(self.download_active) t = threading.Thread(target=func, name='download') # TypeError: download_active() missing 1 required positional argument: 'self' print('==============Ready to download=============') t.start() return return wrapper def download(self): ##### 此行在无装饰器下测试 t = threading.Thread(target=self.download_active, name='download') t.start() @download_thread def download_active(self): print('=== download_active ===') def main(): app = App() app.download_active() pass if __name__ == '__main__': main() os.system("pause") pass ```
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
solosseason机器人#1 · 2016/12/16
def download_thread(func): @wraps(func) def wrapper(self, *arg, **kw): print(func) print(self.download_active) t = threading.Thread(target=func(self), name='download') # TypeError: download_active() missing 1 required positional argument: 'self' print('==============Ready to download=============') t.start() return return wrapper 其实我也不清楚为啥写成func(self),等待其他人的回复吧 这是func和self.download_active打印的结果 <function download_active at 0x02E23BF0> <bound method App.download_active of <__main__.App instance at 0x02DF3670>> ps: 个人习惯于把download_active写在类外面,给类添加__call__方法或者将download_thread改为@classmethod,不知这样处理是否满足楼主的设计思路
flymyheart机器人#2 · 2016/12/16
写成target=func(self)不对吧,那这句话的意思就变成先执行func(self),把结果传给target,这个过程的执行发生在线程开始之前。 我的目标是线程启动后才运行func函数 【 在 solosseason 的大作中提到: 】 : [code=python] : def download_thread(func): : @wraps(func) : ...................
flymyheart机器人#3 · 2016/12/16
另外我也不是要简单写一个classMethod,我想实现对类中某些函数使用装饰器,用新线程去运行 【 在 solosseason 的大作中提到: 】 : [code=python] : def download_thread(func): : @wraps(func) : ...................
solosseason机器人#4 · 2016/12/16
【 在 flymyheart 的大作中提到: 】 : 写成target=func(self)不对吧,那这句话的意思就变成先执行func(self),把结果传给target,这个过程的执行发生在线程开始之前。 : 我的目标是线程启动后才运行func函数 嗯,不好意思,的确不对。你看这样改可以吗? t = threading.Thread(target=func, name='download',args=(self,)) 我是倾向于把class仅仅作为一个修饰器,保持单一性。 class App(object): def __init__(self,func): self._func = func pass def __call__(self): print(self._func) #print(self.download_active) t = threading.Thread(target=self._func, name='download') # TypeError: download_active() missing 1 required positional argument: 'self' print('==============Ready to download=============') t.start() return @App def download_active(): print('=== download_active ===')
flymyheart机器人#5 · 2016/12/16
谢了,t = threading.Thread(target=func, name='download',args=(self,))这种方法可以,我对threading.Thread的参数还没仔细研究,这下好好看看 但类装饰器貌似不太适合我这个,download_active实际上是属于App类里面的操作,类似操作的有很多 (或者我没太理解你的意思?) 【 在 solosseason 的大作中提到: 】 : 嗯,不好意思,的确不对。你看这样改可以吗? : [code=python] : t = threading.Thread(target=func, name='download',args=(self,)) : ...................
asif12机器人#6 · 2016/12/17
在Python的类里面使用装饰器,这个装饰器对类方法的作用是在类还没有实例化的时候,所以没有绑定self。我认为解决办法一是显式传入self,二是在init中调用self.deco(self.func)来绑定self。 奇技淫巧有很多,但是应该把握根本原因~
flymyheart机器人#7 · 2016/12/17
嗯,谢谢,装饰器与self绑定的事儿我理解。按照我原来的程序,被装饰的函数和self的绑定关系是被装饰器破坏了的。 你说 “init中调用self.deco(self.func)来绑定self” 的事儿,是什么意思?deco还是装饰器么,多加入一个参数:def deco(self, func): 这个样子?这样做了,调用func时还是要传入self吧 【 在 asif12 的大作中提到: 】 : 在Python的类里面使用装饰器,这个装饰器对类方法的作用是在类还没有实例化的时候,所以没有绑定self。我认为解决办法一是显式传入self,二是在init中调用self.deco(self.func)来绑定self。 : 奇技淫巧有很多,但是应该把握根本原因~
asif12机器人#8 · 2016/12/17
Python中的装饰器归根结底只是语法糖,func函数在init中通过self.func引用会自动绑定self,这样再使用装饰器函数self.deco就是传入已经绑定self的func作为参数了 【 在 flymyheart 的大作中提到: 】 : 嗯,谢谢,装饰器与self绑定的事儿我理解。按照我原来的程序,被装饰的函数和self的绑定关系是被装饰器破坏了的。 : 你说 “init中调用self.deco(self.func)来绑定self” 的事儿,是什么意思?deco还是装饰器么,多加入一个参数:def deco(self, func): 这个样子?这样做了,调用func时还是要传入self吧 :
flymyheart机器人#9 · 2016/12/17
能给个具体例子么? self.deco(self.f)是报错的,因为deoc只有一个参数。 如果写成AppTest.deco(self.f),t = threading.Thread(target=func, name='f')这句话仍然是没有绑定self的 ``` class AppTest(): def __init__(self): AppTest.deco(self.f) pass def deco(func): def wrapper(self, *arg, **kw): print('wrapper') print(func) func(self) t = threading.Thread(target=func, name='f') print('==============Ready to f=============') t.start() return return wrapper @deco def f(self): print('function') ``` 【 在 asif12 的大作中提到: 】 : Python中的装饰器归根结底只是语法糖,func函数在init中通过self.func引用会自动绑定self,这样再使用装饰器函数self.deco就是传入已经绑定self的func作为参数了 : :