python 装饰器参数,Python装饰器可选参数

from functools import wraps

def logged(func):

@wraps(func)

def with_logging(*args, **kwargs):

print func.__name__ + " was called"

return func(*args, **kwargs)

return with_logging

@logged

def f(x):

"""does some math"""

return x + x * x

print f.__name__ # prints 'f'

print f.__doc__ # prints 'does some math'

Given this sample code, how would I be able to do @logged(variable)?

I tried this

from functools import wraps

def logged(func):

def outer(var):

@wraps(func)

def with_logging(*args, **kwargs):

print func.__name__ + " was called"

return func(*args, **kwargs)

return with_logging

return outer

I was hoping to execute like this: logged(func)(session_variable)

But doesn't work.

Any idea? I want to be able to do @logged and @logged(var) ( or even @logged(var1, var2))

Thanks.

解决方案

The trick here is, you have to introspect what you are given:

def logged(*setting_args, **setting_kwargs):

no_args = False

if len(setting_args) == 1 \

and not setting_kwargs \

and callable(setting_args[0]):

# We were called without args

func = setting_args[0]

no_args = True

def outer(func):

@wraps(func)

def with_logging(*args, **kwargs):

print "{} was called".format(func.__name__)

print "Setting args are: {}".format(setting_args)

print "Setting keyword args are: {}".format(setting_kwargs)

return func(*args, **kwargs)

return with_logging

if no_args:

return outer(func)

else:

return outer

This will work with any of the following:

# No arguments

@logged

def some_function(x):

pass

# One or more arguments

@logged(1, 2, 3)

def some_function(x):

pass

# One or more keyword arguments

@logged(key=1, another_key=2)

def some_function(x):

pass

# A mix of the two

@logged(1, 2, key=3)

def some_function(x):

pass

It will not work if it is called with only one callable argument:

# This will break.

@logged(lambda: "Just for fun")

def some_function(x):

pass

There is no way to tell the difference between a single callable setting and a no-arg invocation of the decorator. However, you can pass a garbage keyword arg to get around even that if you need to:

# This gets around the above limitation

@logged(lambda: "Just for fun", ignored=True)

def some_function(x):

pass

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值