![](/img/trans.png)
[英]How do I use the python-decorator package to decorate classmethods?
[英]How do I decorate a partially applied function in Python 3?
我创建了一个装饰工厂,它由自定义日志记录功能参数化,如下所示:
def _log_error(logger):
def decorator(f):
@wraps(f)
def wrapper(*args, **kwargs):
try:
return f(*args, **kwargs)
except Exception as e:
logger(e)
return None
return wrapper
return decorator
我现在想用它来装饰部分应用的函数foo:
foo = partial(bar, someparam)
我已经尝试了以下所有方法:
@_log_error(logger)
foo = partial(bar, someparam)
log_error = _log_error(logger)
@log_error
foo = partial(...)
foo = partial(...)
@log_error
foo
@log_error
(foo = partial(...))
AFAICT log_error = _log_error(logger) / @log_error
和@_log_error(logger)
似乎是生成装饰器的完全有效的方法,它在正常声明的函数上工作正常。 但是当尝试使用部分应用的函数时,我在foo =
的开头得到语法错误,并且在使用装饰器和functools.partial
时获得优秀资源的googling通常没有给我任何关于这个特定情况的东西。
装饰器不适用于作业。 但是因为使用装饰器与调用装饰器是一样的,所以你可以这样做
foo = _log_error(logger)(partial(bar, someparam))
无论哪种方式都有效
这是使用Either
的另一种方式 - 这个答案的灵感来自Brian Lonsdorf的egghead系列: Frisby教授推出可组合功能JavaScript
我们将学习一些我们在那里学到的知识并编写一些超级甜蜜的功能python代码
class Map (dict):
def __init__(self, **xw):
super(Map, self).__init__(**xw)
self.__dict__ = self
def Left (x):
return Map(
fold = lambda f, g: f(x),
bimap = lambda f, g: Left(f(x))
)
def Right (x):
return Map(
fold = lambda f, g: g(x),
bimap = lambda f, g: Right(g(x))
)
注意:这是一个非常不完整的
Left
和Right
实现,但它足以完成这项特定的工作。 要充分利用这种超级数据类型的全部功能,您需要一个完整的实现。
泛型促进了代码重用
我们将设置一些更通用的功能
def identity (x):
return x
def try_catch (f):
try:
return Right(f())
except Exception as e:
return Left(e)
def partial (f, *xs, **xw):
def aux (*ys, **yw):
return f(*xs, *ys, **xw, **yw)
return aux
现在我们已经足够定义log_error
- 在Python中编写curried函数的语法有点log_error
,但一切都按预期工作。
用简单的英语:我们try
应用f
并获取一个值。 如果值是错误( Left
),则调用logger
,否则返回值( identity
)
def log_error (logger):
def wrapper (f):
def aux (*xs, **xw):
return try_catch (lambda: f(*xs, **xw)).bimap(logger, identity)
return aux
return wrapper
把它们放在一起
现在让我们尝试一下它的功能
def foo (x,y,z):
return (x + y) * z
您想要做的是在使用自定义记录器时包装部分应用的函数
foo_logger = log_error(lambda err: print("ERROR:" + str(err))) (partial(foo,'a'))
foo_logger('b',3).fold(print, print)
# ('a' + 'b') * 3
# 'ab' * 3
# => ababab
foo_logger(1,3).fold(print, print)
# ('a' + 1) * 3
# ERROR: Can't convert 'int' object to str implicitly
# => None
了解结果
如您所见,当没有错误存在时( Right
),评估只是继续移动,计算的值传递给print
。
发生错误( Left
)时,记录器将其拾取并将错误消息记录到控制台。 由于日志记录功能没有返回值,因此传递None
以进行print
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.