Dan*_*ana 328 python decorator
虽然我喜欢把自己想象成一个相当称职的Python编码器,但我从来没有能够理解的语言的一个方面就是装饰器.
我知道它们是什么(表面上),我已经阅读了有关Stack Overflow的教程,示例和问题,我理解语法,可以编写自己的,偶尔使用@classmethod和@staticmethod,但我从来没有想过使用装饰器解决我自己的Python代码中的问题.我从来没有遇到过这样的问题,"嗯......这看起来像装饰工作!"
所以,我想知道你们是否可以提供一些你在自己的程序中使用装饰器的例子,希望我会有一个"A-ha!" 一刻,得到他们.
RSa*_*bet 123
我使用装饰器主要用于计时目的
def time_dec(func):
def wrapper(*arg):
t = time.clock()
res = func(*arg)
print func.func_name, time.clock()-t
return res
return wrapper
@time_dec
def myFunction(n):
...
Run Code Online (Sandbox Code Playgroud)
Joh*_*uhy 95
我用它们进行同步.
import functools
def synchronized(lock):
""" Synchronization decorator """
def wrap(f):
@functools.wraps(f)
def newFunction(*args, **kw):
lock.acquire()
try:
return f(*args, **kw)
finally:
lock.release()
return newFunction
return wrap
Run Code Online (Sandbox Code Playgroud)
正如评论中指出的那样,从Python 2.5开始,您可以将with语句与threading.Lock(或multiprocessing.Lock自2.6版本)对象结合使用, 以简化装饰器的实现:
import functools
def synchronized(lock):
""" Synchronization decorator """
def wrap(f):
@functools.wraps(f)
def newFunction(*args, **kw):
with lock:
return f(*args, **kw)
return newFunction
return wrap
Run Code Online (Sandbox Code Playgroud)
无论如何,你这样使用它:
import threading
lock = threading.Lock()
@synchronized(lock)
def do_something():
# etc
@synchronzied(lock)
def do_something_else():
# etc
Run Code Online (Sandbox Code Playgroud)
基本上,它只是把lock.acquire()/ lock.release()在函数调用的两侧.
Sim*_*mon 68
我使用装饰器进行类型检查参数,这些参数通过一些RMI传递给我的Python方法.因此,不是重复相同的参数计数,而是一次又一次地异常提升mumbo-jumbo
def myMethod(ID, name):
if not (myIsType(ID, 'uint') and myIsType(name, 'utf8string')):
raise BlaBlaException() ...
Run Code Online (Sandbox Code Playgroud)
我只是宣布
@accepts(uint, utf8string)
def myMethod(ID, name):
...
Run Code Online (Sandbox Code Playgroud)
和accepts()为我做所有的工作.
cdl*_*ary 47
装饰器用于任何您希望透明地"包装"其他功能的东西.
Django使用它们在视图函数上包装"需要登录"功能,以及注册过滤器函数.
您可以使用类装饰器将命名日志添加到类中.
任何足够通用的功能,你可以"适应"现有的类或功能的行为是公平的装饰游戏.
还讨论了PEP 318指向的Python-Dev新闻组的用例- 函数和方法的装饰器.
Tor*_*rek 24
对于nosetests,您可以编写一个装饰器,它提供具有多组参数的单元测试函数或方法:
@parameters(
(2, 4, 6),
(5, 6, 11),
)
def test_add(a, b, expected):
assert a + b == expected
Run Code Online (Sandbox Code Playgroud)
DNS*_*DNS 23
Twisted库使用装饰器与生成器相结合,给出异步函数同步的错觉.例如:
@inlineCallbacks
def asyncf():
doStuff()
yield someAsynchronousCall()
doStuff()
yield someAsynchronousCall()
doStuff()
Run Code Online (Sandbox Code Playgroud)
使用它,本来可以分解成大量小回调函数的代码可以很自然地编写为单个块,使其更容易理解和维护.
Mis*_*hor 12
当然,一个显而易见的用途是记录:
import functools
def log(logger, level='info'):
def log_decorator(fn):
@functools.wraps(fn)
def wrapper(*a, **kwa):
getattr(logger, level)(fn.__name__)
return fn(*a, **kwa)
return wrapper
return log_decorator
# later that day ...
@log(logging.getLogger('main'), level='warning')
def potentially_dangerous_function(times):
for _ in xrange(times): rockets.get_rocket(NUCLEAR=True).fire()
Run Code Online (Sandbox Code Playgroud)
我使用以下装饰器来创建函数threadsafe.它使代码更具可读性.它几乎与John Fouhy提出的类似,但不同之处在于,它只能处理单个函数,并且不需要明确地创建锁定对象.
def threadsafe_function(fn):
"""decorator making sure that the decorated function is thread safe"""
lock = threading.Lock()
def new(*args, **kwargs):
lock.acquire()
try:
r = fn(*args, **kwargs)
except Exception as e:
raise e
finally:
lock.release()
return r
return new
class X:
var = 0
@threadsafe_function
def inc_var(self):
X.var += 1
return X.var
Run Code Online (Sandbox Code Playgroud)
装饰器既可用于定义函数的属性,也可用作修改函数的样板; 这是可能的,但反直觉的是他们返回完全不同的功能.看看这里的其他响应,似乎最常见的用途之一是限制其他一些进程的范围 - 无论是日志记录,分析,安全检查等.
CherryPy使用对象分派来匹配对象的URL,最终匹配方法.这些方法的装饰者发出信号,表明CherryPy是否被允许使用这些方法.例如,改编自教程:
class HelloWorld:
...
def secret(self):
return "You shouldn't be here."
@cherrypy.expose
def index(self):
return "Hello world!"
cherrypy.quickstart(HelloWorld())
Run Code Online (Sandbox Code Playgroud)
我最近在使用社交网络Web应用程序时使用它们.对于社区/团体,我应该授予成员资格以创建新的讨论并回复您必须成为该特定组成员的消息.所以,我写了一个装饰师@membership_required,把它放在我需要的地方.